Prechádzať zdrojové kódy

Added Selection classes to C++ and C#

Marko Pintera 11 rokov pred
rodič
commit
3c5c4b171f

+ 2 - 0
BansheeEditor/BansheeEditor.vcxproj

@@ -320,6 +320,7 @@
     <ClInclude Include="Include\BsSceneCameraController.h" />
     <ClInclude Include="Include\BsSceneEditorWidget.h" />
     <ClInclude Include="Include\BsSceneGrid.h" />
+    <ClInclude Include="Include\BsSelection.h" />
     <ClInclude Include="Include\BsTestTextSprite.h" />
     <ClInclude Include="Include\DbgEditorWidget1.h" />
     <ClInclude Include="Include\DbgEditorWidget2.h" />
@@ -375,6 +376,7 @@
     <ClCompile Include="Source\BsSceneCameraController.cpp" />
     <ClCompile Include="Source\BsSceneEditorWidget.cpp" />
     <ClCompile Include="Source\BsSceneGrid.cpp" />
+    <ClCompile Include="Source\BsSelection.cpp" />
     <ClCompile Include="Source\BsUndoRedo.cpp" />
     <ClCompile Include="Source\BsEditorApplication.cpp" />
     <ClCompile Include="Source\BsTestTextSprite.cpp" />

+ 6 - 0
BansheeEditor/BansheeEditor.vcxproj.filters

@@ -216,6 +216,9 @@
     <ClInclude Include="Include\BsGizmoManager.h">
       <Filter>Header Files\Editor</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsSelection.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsEditorWidgetContainer.cpp">
@@ -380,5 +383,8 @@
     <ClCompile Include="Source\BsGizmoManager.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsSelection.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 1 - 0
BansheeEditor/Include/BsProjectLibrary.h

@@ -59,6 +59,7 @@ namespace BansheeEngine
 		LibraryEntry* findEntry(const Path& fullPath) const;
 
 		ProjectResourceMetaPtr findResourceMeta(const String& uuid) const;
+		Path uuidToPath(const String& uuid) const;
 
 		void createEntry(const HResource& resource, const Path& path);
 		void moveEntry(const Path& oldPath, const Path& newPath);

+ 36 - 0
BansheeEditor/Include/BsSelection.h

@@ -0,0 +1,36 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsModule.h"
+
+namespace BansheeEngine
+{
+	class BS_ED_EXPORT Selection : public Module<Selection>
+	{
+	public:
+		Selection(GUISceneTreeView* sceneTreeView, GUIResourceTreeView* resourceTreeView);
+		~Selection();
+
+		const Vector<HSceneObject>& getSceneObjects() const;
+		void setSceneObjects(const Vector<HSceneObject>& sceneObjects);
+
+		const Vector<Path>& getResourcePaths() const;
+		void setResourcePaths(const Vector<Path>& paths);
+
+		Vector<String> getResourceUUIDs() const;
+		void setResourceUUIDs(const Vector<String>& UUIDs);
+
+	private:
+		void sceneSelectionChanged();
+		void resourceSelectionChanged();
+
+		GUISceneTreeView* mSceneTreeView;
+		GUIResourceTreeView* mResourceTreeView;
+
+		Vector<HSceneObject> mSelectedSceneObjects;
+		Vector<Path> mSelectedResourcePaths;
+
+		HEvent mSceneSelectionChangedConn;
+		HEvent mResourceSelectionChangedConn;
+	};
+}

+ 2 - 0
BansheeEditor/Source/BsGUIResourceTreeView.cpp

@@ -483,6 +483,8 @@ namespace BansheeEngine
 
 	void GUIResourceTreeView::setSelection(const Vector<Path>& paths)
 	{
+		unselectAll();
+
 		ResourceTreeElement& root = mRootElement;
 
 		Stack<ResourceTreeElement*> todo;

+ 2 - 0
BansheeEditor/Source/BsGUISceneTreeView.cpp

@@ -280,6 +280,8 @@ namespace BansheeEngine
 
 	void GUISceneTreeView::setSelection(const Vector<HSceneObject>& objects)
 	{
+		unselectAll();
+
 		SceneTreeElement& root = mRootElement;
 
 		Stack<SceneTreeElement*> todo;

+ 12 - 0
BansheeEditor/Source/BsProjectLibrary.cpp

@@ -484,6 +484,18 @@ namespace BansheeEngine
 		return resEntry->meta;
 	}
 
+	Path ProjectLibrary::uuidToPath(const String& uuid) const
+	{
+		if (mResourceManifest == nullptr)
+			return Path();
+
+		Path filePath;
+		if (!mResourceManifest->uuidToFilePath(uuid, filePath))
+			return Path();
+
+		return filePath;
+	}
+
 	void ProjectLibrary::createEntry(const HResource& resource, const Path& path)
 	{
 		if (resource == nullptr)

+ 81 - 0
BansheeEditor/Source/BsSelection.cpp

@@ -0,0 +1,81 @@
+#include "BsSelection.h"
+#include "BsGUISceneTreeView.h"
+#include "BsGUIResourceTreeView.h"
+#include "BsProjectLibrary.h"
+#include "BsProjectResourceMeta.h"
+
+namespace BansheeEngine
+{
+	Selection::Selection(GUISceneTreeView* sceneTreeView, GUIResourceTreeView* resourceTreeView)
+		:mSceneTreeView(sceneTreeView), mResourceTreeView(resourceTreeView)
+	{
+		mSceneSelectionChangedConn = mSceneTreeView->onSelectionChanged.connect(std::bind(&Selection::sceneSelectionChanged, this));
+		mResourceSelectionChangedConn = mResourceTreeView->onSelectionChanged.connect(std::bind(&Selection::resourceSelectionChanged, this));
+	}
+
+	Selection::~Selection()
+	{
+		mSceneSelectionChangedConn.disconnect();
+		mResourceSelectionChangedConn.disconnect();
+	}
+
+	const Vector<HSceneObject>& Selection::getSceneObjects() const
+	{
+		return mSelectedSceneObjects;
+	}
+
+	void Selection::setSceneObjects(const Vector<HSceneObject>& sceneObjects)
+	{
+		mSelectedSceneObjects = sceneObjects;
+		mResourceTreeView->setSelection(mSelectedResourcePaths);
+	}
+
+	const Vector<Path>& Selection::getResourcePaths() const
+	{
+		return mSelectedResourcePaths;
+	}
+
+	void Selection::setResourcePaths(const Vector<Path>& paths)
+	{
+		mSelectedResourcePaths = paths;
+	}
+
+	Vector<String> Selection::getResourceUUIDs() const
+	{
+		Vector<String> UUIDs;
+		for (auto& path : mSelectedResourcePaths)
+		{
+			ProjectLibrary::LibraryEntry* entry = ProjectLibrary::instance().findEntry(path);
+			if (entry != nullptr && entry->type == ProjectLibrary::LibraryEntryType::File)
+			{
+				ProjectLibrary::ResourceEntry* resEntry = static_cast<ProjectLibrary::ResourceEntry*>(entry);
+				UUIDs.push_back(resEntry->meta->getUUID());
+			}
+		}
+
+		return UUIDs;
+	}
+
+	void Selection::setResourceUUIDs(const Vector<String>& UUIDs)
+	{
+		mSelectedResourcePaths.clear();
+		for (auto& uuid : UUIDs)
+		{
+			Path path = ProjectLibrary::instance().uuidToPath(uuid);
+			if (path != Path::BLANK)
+				mSelectedResourcePaths.push_back(path);
+		}
+
+		mResourceTreeView->setSelection(mSelectedResourcePaths);
+	}
+
+	void Selection::sceneSelectionChanged()
+	{
+		mSelectedSceneObjects = mSceneTreeView->getSelection();
+	}
+
+	void Selection::resourceSelectionChanged()
+	{
+		mSelectedResourcePaths = mResourceTreeView->getSelection();
+	}
+}

+ 1 - 0
MBansheeEditor/MBansheeEditor.csproj

@@ -83,6 +83,7 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Scene\DrawGizmo.cs" />
     <Compile Include="Scene\Gizmos.cs" />
+    <Compile Include="Selection.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\MBansheeEngine\MBansheeEngine.csproj">

+ 68 - 0
MBansheeEditor/Selection.cs

@@ -0,0 +1,68 @@
+using System.Runtime.CompilerServices;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    public sealed class Selection
+    {
+        public SceneObject[] sceneObjects
+        {
+            get
+            {
+                SceneObject[] selection;
+                Internal_GetSceneObjectSelection(out selection);
+                return selection;
+            }
+            set
+            {
+                Internal_SetSceneObjectSelection(value);
+            }
+        }
+
+        public string[] resourceUUIDs
+        {
+            get
+            {
+                string[] selection;
+                Internal_GetResourceUUIDSelection(out selection);
+                return selection;
+            }
+            set
+            {
+                Internal_SetResourceUUIDSelection(value);
+            }
+        }
+
+        public string[] resourcePaths
+        {
+            get
+            {
+                string[] selection;
+                Internal_GetResourcePathSelection(out selection);
+                return selection;
+            }
+            set
+            {
+                Internal_SetResourcePathSelection(value);
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern void Internal_GetSceneObjectSelection(out SceneObject[] selection);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern void Internal_SetSceneObjectSelection(SceneObject[] selection);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern void Internal_GetResourceUUIDSelection(out string[] selection);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern void Internal_SetResourceUUIDSelection(string[] selection);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern void Internal_GetResourcePathSelection(out string[] selection);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern void Internal_SetResourcePathSelection(string[] selection);
+    }
+}

+ 23 - 0
SBansheeEditor/Include/BsScriptSelection.h

@@ -0,0 +1,23 @@
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptObject.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BED_EXPORT ScriptSelection : public ScriptObject<ScriptSelection>
+	{
+	public:
+		SCRIPT_OBJ(BansheeEditorAssemblyName, "BansheeEditor", "Selection")
+
+	private:
+		static void internal_GetSceneObjectSelection(MonoArray** selection);
+		static void internal_SetSceneObjectSelection(MonoArray* selection);
+
+		static void internal_GetResourceUUIDSelection(MonoArray** selection);
+		static void internal_SetResourceUUIDSelection(MonoArray* selection);
+
+		static void internal_GetResourcePathSelection(MonoArray** selection);
+		static void internal_SetResourcePathSelection(MonoArray* selection);
+	};
+}

+ 2 - 0
SBansheeEditor/SBansheeEditor.vcxproj

@@ -248,6 +248,7 @@
     <ClInclude Include="Include\BsScriptGUIVector3Field.h" />
     <ClInclude Include="Include\BsScriptGUIVector4Field.h" />
     <ClInclude Include="Include\BsScriptProjectLibrary.h" />
+    <ClInclude Include="Include\BsScriptSelection.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsEditorScriptManager.cpp" />
@@ -272,6 +273,7 @@
     <ClCompile Include="Source\BsScriptGUIVector3Field.cpp" />
     <ClCompile Include="Source\BsScriptGUIVector4Field.cpp" />
     <ClCompile Include="Source\BsScriptProjectLibrary.cpp" />
+    <ClCompile Include="Source\BsScriptSelection.cpp" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">

+ 6 - 0
SBansheeEditor/SBansheeEditor.vcxproj.filters

@@ -81,6 +81,9 @@
     <ClInclude Include="Include\BsScriptGizmoManager.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptSelection.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptEditorPlugin.cpp">
@@ -149,5 +152,8 @@
     <ClCompile Include="Source\BsScriptGizmoManager.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptSelection.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 130 - 0
SBansheeEditor/Source/BsScriptSelection.cpp

@@ -0,0 +1,130 @@
+#include "BsScriptSelection.h"
+#include "BsScriptMeta.h"
+#include "BsMonoClass.h"
+#include "BsSelection.h"
+#include "BsScriptSceneObject.h"
+#include "BsMonoUtil.h"
+#include "BsPath.h"
+#include "BsScriptGameObjectManager.h"
+
+namespace BansheeEngine
+{
+	void ScriptSelection::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_GetSceneObjectSelection", &ScriptSelection::internal_GetSceneObjectSelection);
+		metaData.scriptClass->addInternalCall("Internal_SetSceneObjectSelection", &ScriptSelection::internal_SetSceneObjectSelection);
+		metaData.scriptClass->addInternalCall("Internal_GetResourceUUIDSelection", &ScriptSelection::internal_GetResourceUUIDSelection);
+		metaData.scriptClass->addInternalCall("Internal_SetResourceUUIDSelection", &ScriptSelection::internal_SetResourceUUIDSelection);
+		metaData.scriptClass->addInternalCall("Internal_GetResourcePathSelection", &ScriptSelection::internal_GetResourcePathSelection);
+		metaData.scriptClass->addInternalCall("Internal_SetResourcePathSelection", &ScriptSelection::internal_SetResourcePathSelection);
+	}
+
+	void ScriptSelection::internal_GetSceneObjectSelection(MonoArray** selection)
+	{
+		Vector<HSceneObject> sceneObjects = Selection::instance().getSceneObjects();
+
+		::MonoClass* sceneObjectMonoClass = ScriptSceneObject::getMetaData()->scriptClass->_getInternalClass();
+		MonoArray* sceneObjectArray = mono_array_new(MonoManager::instance().getDomain(),
+			sceneObjectMonoClass, (UINT32)sceneObjects.size());
+
+		for (UINT32 i = 0; i < (UINT32)sceneObjects.size(); i++)
+		{
+			// TODO - This bit is commonly used, I should add a method in ScriptGameObjectManager
+			ScriptSceneObject* scriptSceneObject = ScriptGameObjectManager::instance().getScriptSceneObject(sceneObjects[i]);
+			if (scriptSceneObject == nullptr)
+				scriptSceneObject = ScriptGameObjectManager::instance().createScriptSceneObject(sceneObjects[i]);
+
+			MonoObject* sceneMonoObject = scriptSceneObject->getManagedInstance();
+
+			void* elemAddr = mono_array_addr_with_size(sceneObjectArray, sizeof(MonoObject*), i);
+			memcpy(elemAddr, &sceneMonoObject, sizeof(MonoObject*));
+		}
+
+		*selection = sceneObjectArray;
+	}
+
+	void ScriptSelection::internal_SetSceneObjectSelection(MonoArray* selection)
+	{
+		Vector<HSceneObject> sceneObjects;
+
+		UINT32 arrayLen = (UINT32)mono_array_length(selection);
+		for (UINT32 i = 0; i < arrayLen; i++)
+		{
+			MonoObject* monoSO = mono_array_get(selection, MonoObject*, i);
+			ScriptSceneObject* scriptSO = ScriptSceneObject::toNative(monoSO);
+			HSceneObject so = static_object_cast<SceneObject>(scriptSO->getNativeHandle());
+
+			sceneObjects.push_back(so);
+		}
+
+		Selection::instance().setSceneObjects(sceneObjects);
+	}
+
+	void ScriptSelection::internal_GetResourceUUIDSelection(MonoArray** selection)
+	{
+		Vector<String> uuids = Selection::instance().getResourceUUIDs();
+
+		MonoArray* uuidArray = mono_array_new(MonoManager::instance().getDomain(),
+			mono_get_string_class(), (UINT32)uuids.size());
+
+		for (UINT32 i = 0; i < (UINT32)uuids.size(); i++)
+		{
+			MonoString* monoString = MonoUtil::stringToMono(MonoManager::instance().getDomain(), uuids[i]);
+
+			void* elemAddr = mono_array_addr_with_size(uuidArray, sizeof(MonoString*), i);
+			memcpy(elemAddr, &monoString, sizeof(MonoString*));
+		}
+
+		*selection = uuidArray;
+	}
+
+	void ScriptSelection::internal_SetResourceUUIDSelection(MonoArray* selection)
+	{
+		Vector<String> uuids;
+
+		UINT32 arrayLen = (UINT32)mono_array_length(selection);
+		for (UINT32 i = 0; i < arrayLen; i++)
+		{
+			MonoString* monoString = mono_array_get(selection, MonoString*, i);
+			String uuid = MonoUtil::monoToString(monoString);
+
+			uuids.push_back(uuid);
+		}
+
+		Selection::instance().setResourceUUIDs(uuids);
+	}
+
+	void ScriptSelection::internal_GetResourcePathSelection(MonoArray** selection)
+	{
+		Vector<Path> paths = Selection::instance().getResourcePaths();
+
+		MonoArray* pathArray = mono_array_new(MonoManager::instance().getDomain(),
+			mono_get_string_class(), (UINT32)paths.size());
+
+		for (UINT32 i = 0; i < (UINT32)paths.size(); i++)
+		{
+			MonoString* monoString = MonoUtil::stringToMono(MonoManager::instance().getDomain(), paths[i].toString());
+
+			void* elemAddr = mono_array_addr_with_size(pathArray, sizeof(MonoString*), i);
+			memcpy(elemAddr, &monoString, sizeof(MonoString*));
+		}
+
+		*selection = pathArray;
+	}
+
+	void ScriptSelection::internal_SetResourcePathSelection(MonoArray* selection)
+	{
+		Vector<Path> paths;
+
+		UINT32 arrayLen = (UINT32)mono_array_length(selection);
+		for (UINT32 i = 0; i < arrayLen; i++)
+		{
+			MonoString* monoString = mono_array_get(selection, MonoString*, i);
+			Path path  = MonoUtil::monoToString(monoString);
+
+			paths.push_back(path);
+		}
+
+		Selection::instance().setResourcePaths(paths);
+	}
+}

+ 1 - 3
SceneView.txt

@@ -4,13 +4,11 @@ TODO:
 
 CONCRETE TASK:
  - SceneView editor window: Add a way to detect exact mouse position on the render texture
- - Extend SceneTreeView and ResourceTreeView that have events that occurr when selection changes
-    - Events need to return SceneObject, Resource or Path (an array of any of those if needed)
- - Extend SceneTreeView and ResourceTreeView so that they have setSelection method accepting SceneObject/Resource-Path arrays
  - Similar to how I have onRenderViewport callback in Renderer have another one that gets triggered from core thread
    - Hook up gizmo rendering there
  - Hook up gizmo manager to ScenePicking so gizmos are considered when picking
    - I'll likely need to update GizmoManager so I can query gizmo SceneObject based on gizmo index
+ - Selection/ScenePicking/GizmoManager need to be started
 
 IMMEDIATE:
  - SceneGrid is very ugly. Consider using default lines for now and come back with a better approach later.