Ver código fonte

Added menu items for builtin components

Marko Pintera 10 anos atrás
pai
commit
087cb42638

+ 2 - 2
BansheeEditor/Source/BsMainEditorWindow.cpp

@@ -28,8 +28,8 @@ namespace BansheeEngine
 
 
 		mMenuBar->addMenuItem(L"File/New project", nullptr, 100);
 		mMenuBar->addMenuItem(L"File/New project", nullptr, 100);
 		mMenuBar->addMenuItem(L"File/Open project", nullptr, 100);
 		mMenuBar->addMenuItem(L"File/Open project", nullptr, 100);
-		mMenuBar->addSeparator(L"File", 99);
-		mMenuBar->addMenuItem(L"File/Exit", nullptr, 98);
+		mMenuBar->addSeparator(L"File", 0);
+		mMenuBar->addMenuItem(L"File/Exit", nullptr, 0);
 
 
 		TestSuitePtr testSuite = TestSuite::create<EditorTestSuite>();
 		TestSuitePtr testSuite = TestSuite::create<EditorTestSuite>();
 		testSuite->run(ExceptionTestOutput());
 		testSuite->run(ExceptionTestOutput());

+ 123 - 13
MBansheeEditor/EditorApplication.cs

@@ -119,7 +119,7 @@ namespace BansheeEditor
             ProjectLibrary.Update();
             ProjectLibrary.Update();
         }
         }
 
 
-        [MenuItem("File/Save Prefab", ButtonModifier.Ctrl, ButtonCode.S)]
+        [MenuItem("File/Save Prefab", ButtonModifier.Ctrl, ButtonCode.S, 50, true)]
         private static void SavePrefab()
         private static void SavePrefab()
         {
         {
             if (!string.IsNullOrEmpty(Scene.ActiveSceneUUID))
             if (!string.IsNullOrEmpty(Scene.ActiveSceneUUID))
@@ -128,23 +128,27 @@ namespace BansheeEditor
                 Internal_SaveScene(scenePath);
                 Internal_SaveScene(scenePath);
             }
             }
             else
             else
-            {
-                string scenePath = "";
-                BrowseDialog.SaveFile(ProjectLibrary.ResourceFolder, "", out scenePath);
+                SavePrefabAs();
+        }
 
 
-                if (!PathEx.IsPartOf(scenePath, ProjectLibrary.ResourceFolder))
-                    DialogBox.Open("Error", "The location must be inside the Resources folder of the project.", DialogBox.Type.OK);
-                else
-                {
-                    // TODO - If path points to an existing non-scene asset or folder I should delete it otherwise
-                    //        Internal_SaveScene will silently fail.
+        [MenuItem("File/Save Prefab As", 50)]
+        private static void SavePrefabAs()
+        {
+            string scenePath = "";
+            BrowseDialog.SaveFile(ProjectLibrary.ResourceFolder, "", out scenePath);
+
+            if (!PathEx.IsPartOf(scenePath, ProjectLibrary.ResourceFolder))
+                DialogBox.Open("Error", "The location must be inside the Resources folder of the project.", DialogBox.Type.OK);
+            else
+            {
+                // TODO - If path points to an existing non-scene asset or folder I should delete it otherwise
+                //        Internal_SaveScene will silently fail.
 
 
-                    Scene.ActiveSceneUUID = Internal_SaveScene(scenePath);
-                }
+                Scene.ActiveSceneUUID = Internal_SaveScene(scenePath);
             }
             }
         }
         }
 
 
-        [MenuItem("File/Load Prefab", ButtonModifier.Ctrl, ButtonCode.L)]
+        [MenuItem("File/Load Prefab", ButtonModifier.Ctrl, ButtonCode.L, 50)]
         private static void LoadPrefab()
         private static void LoadPrefab()
         {
         {
             Action doLoad =
             Action doLoad =
@@ -178,6 +182,112 @@ namespace BansheeEditor
                 doLoad();
                 doLoad();
         }
         }
 
 
+        [MenuItem("Components/Camera")]
+        private static void AddCamera()
+        {
+            SceneObject so = Selection.sceneObject;
+            if (so == null)
+                return;
+
+            UndoRedo.RecordSO(so, "Added a Camera component");
+            so.AddComponent<Camera>();
+        }
+
+        [MenuItem("Components/Renderable")]
+        private static void AddRenderable()
+        {
+            SceneObject so = Selection.sceneObject;
+            if (so == null)
+                return;
+
+            UndoRedo.RecordSO(so, "Added a Renderable component");
+            so.AddComponent<Renderable>();
+        }
+
+        [MenuItem("Components/Point light")]
+        private static void AddPointLight()
+        {
+            SceneObject so = Selection.sceneObject;
+            if (so == null)
+                return;
+
+            UndoRedo.RecordSO(so, "Added a Light component");
+            Light light = so.AddComponent<Light>();
+            light.Type = LightType.Point;
+        }
+
+        [MenuItem("Components/Spot light")]
+        private static void AddSpotLight()
+        {
+            SceneObject so = Selection.sceneObject;
+            if (so == null)
+                return;
+
+            UndoRedo.RecordSO(so, "Added a Light component");
+            Light light = so.AddComponent<Light>();
+            light.Type = LightType.Spot;
+        }
+
+        [MenuItem("Components/Directional light")]
+        private static void AddDirectionalLight()
+        {
+            SceneObject so = Selection.sceneObject;
+            if (so == null)
+                return;
+
+            UndoRedo.RecordSO(so, "Added a Light component");
+            Light light = so.AddComponent<Light>();
+            light.Type = LightType.Directional;
+        }
+
+        [MenuItem("Scene Objects/Camera")]
+        private static void AddCameraSO()
+        {
+            SceneObject so = UndoRedo.CreateSO("Camera", "Created a Camera");
+            so.AddComponent<Camera>();
+
+            Selection.sceneObject = so;
+        }
+
+        [MenuItem("Scene Objects/Renderable")]
+        private static void AddRenderableSO()
+        {
+            SceneObject so = UndoRedo.CreateSO("Renderable", "Created a Renderable");
+            so.AddComponent<Renderable>();
+
+            Selection.sceneObject = so;
+        }
+
+        [MenuItem("Scene Objects/Point light")]
+        private static void AddPointLightSO()
+        {
+            SceneObject so = UndoRedo.CreateSO("Point light", "Created a Light");
+            Light light = so.AddComponent<Light>();
+            light.Type = LightType.Point;
+
+            Selection.sceneObject = so;
+        }
+
+        [MenuItem("Scene Objects/Spot light")]
+        private static void AddSpotLightSO()
+        {
+            SceneObject so = UndoRedo.CreateSO("Spot light", "Created a Light");
+            Light light = so.AddComponent<Light>();
+            light.Type = LightType.Spot;
+
+            Selection.sceneObject = so;
+        }
+
+        [MenuItem("Scene Objects/Directional light")]
+        private static void AddDirectionalLightSO()
+        {
+            SceneObject so = UndoRedo.CreateSO("Directional light", "Created a Light");
+            Light light = so.AddComponent<Light>();
+            light.Type = LightType.Directional;
+
+            Selection.sceneObject = so;
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern string Internal_GetProjectPath();
         private static extern string Internal_GetProjectPath();
 
 

+ 5 - 2
MBansheeEditor/MenuItem.cs

@@ -6,21 +6,24 @@ namespace BansheeEditor
     [AttributeUsage(AttributeTargets.Method)]
     [AttributeUsage(AttributeTargets.Method)]
     public sealed class MenuItem : Attribute
     public sealed class MenuItem : Attribute
     {
     {
-        public MenuItem(string path, ButtonModifier shortcutModifier, ButtonCode shortcutKey,  int priority = 0)
+        public MenuItem(string path, ButtonModifier shortcutModifier, ButtonCode shortcutKey, int priority = 0, bool separator = false)
         {
         {
             this.path = path;
             this.path = path;
             this.shortcut = new ShortcutKey(shortcutModifier, shortcutKey);
             this.shortcut = new ShortcutKey(shortcutModifier, shortcutKey);
             this.priority = priority;
             this.priority = priority;
+            this.separator = separator;
         }
         }
 
 
-        public MenuItem(string path, int priority = 0)
+        public MenuItem(string path, int priority = 0, bool separator = false)
         {
         {
             this.path = path;
             this.path = path;
             this.priority = priority;
             this.priority = priority;
+            this.separator = separator;
         }
         }
 
 
         private string path;
         private string path;
         private ShortcutKey shortcut;
         private ShortcutKey shortcut;
         private int priority;
         private int priority;
+        private bool separator;
     }
     }
 }
 }

+ 18 - 0
MBansheeEditor/Selection.cs

@@ -10,6 +10,24 @@ namespace BansheeEditor
         public static Action<SceneObject> OnSceneObjectPing;
         public static Action<SceneObject> OnSceneObjectPing;
         public static Action<string> OnResourcePing;
         public static Action<string> OnResourcePing;
 
 
+        public static SceneObject sceneObject
+        {
+            get
+            {
+                SceneObject[] selection;
+                Internal_GetSceneObjectSelection(out selection);
+
+                if(selection.Length > 0)
+                    return selection[0];
+
+                return null;
+            }
+            set
+            {
+                Internal_SetSceneObjectSelection(new SceneObject[] { value });
+            }
+        }
+
         public static SceneObject[] sceneObjects
         public static SceneObject[] sceneObjects
         {
         {
             get
             get

+ 1 - 1
MBansheeEngine/LightInternal.cs

@@ -9,7 +9,7 @@ namespace BansheeEngine
     // Don't reorder, used by native code
     // Don't reorder, used by native code
     public enum LightType
     public enum LightType
     {
     {
-        Directional, Point, Light
+        Directional, Point, Spot
     }
     }
 
 
     internal class LightInternal : ScriptObject
     internal class LightInternal : ScriptObject

+ 3 - 1
SBansheeEditor/Include/BsMenuItemManager.h

@@ -35,11 +35,12 @@ namespace BansheeEngine
 		 * @param	path		Output path defined in the MenuItem attribute.
 		 * @param	path		Output path defined in the MenuItem attribute.
 		 * @param	shortcut	Shortcut key defined in the MenuItem attribute.
 		 * @param	shortcut	Shortcut key defined in the MenuItem attribute.
 		 * @param	priority	Menu item priority defined in the MenuItem attribute.
 		 * @param	priority	Menu item priority defined in the MenuItem attribute.
+		 * @param	separator	Should the separator be inserted before the menu item.
 		 *
 		 *
 		 * @return	True if the method has a MenuItem attribute. If false is returned output parameters
 		 * @return	True if the method has a MenuItem attribute. If false is returned output parameters
 		 *			from this method are undefined.
 		 *			from this method are undefined.
 		 */
 		 */
-		bool parseMenuItemMethod(MonoMethod* method, WString& path, ShortcutKey& shortcut, INT32& priority) const;
+		bool parseMenuItemMethod(MonoMethod* method, WString& path, ShortcutKey& shortcut, INT32& priority, bool& separator) const;
 
 
 		/**
 		/**
 		 * @brief	Triggered when one of the managed menu items is clicked. 
 		 * @brief	Triggered when one of the managed menu items is clicked. 
@@ -55,6 +56,7 @@ namespace BansheeEngine
 		MonoField* mPathField;
 		MonoField* mPathField;
 		MonoField* mShortcutField;
 		MonoField* mShortcutField;
 		MonoField* mPriorityField;
 		MonoField* mPriorityField;
+		MonoField* mSeparatorField;
 
 
 		Vector<WString> mMenuItems;
 		Vector<WString> mMenuItems;
 	};
 	};

+ 19 - 2
SBansheeEditor/Source/BsMenuItemManager.cpp

@@ -50,6 +50,7 @@ namespace BansheeEngine
 		mPathField = mMenuItemAttribute->getField("path");
 		mPathField = mMenuItemAttribute->getField("path");
 		mShortcutField = mMenuItemAttribute->getField("shortcut");
 		mShortcutField = mMenuItemAttribute->getField("shortcut");
 		mPriorityField = mMenuItemAttribute->getField("priority");
 		mPriorityField = mMenuItemAttribute->getField("priority");
+		mSeparatorField = mMenuItemAttribute->getField("separator");
 
 
 		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
 		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
 
 
@@ -68,10 +69,25 @@ namespace BansheeEngine
 					WString path;
 					WString path;
 					ShortcutKey shortcutKey = ShortcutKey::NONE;
 					ShortcutKey shortcutKey = ShortcutKey::NONE;
 					INT32 priority = 0;
 					INT32 priority = 0;
-					if (parseMenuItemMethod(curMethod, path, shortcutKey, priority))
+					bool separator = false;
+					if (parseMenuItemMethod(curMethod, path, shortcutKey, priority, separator))
 					{
 					{
 						std::function<void()> callback = std::bind(&MenuItemManager::menuItemCallback, curMethod);
 						std::function<void()> callback = std::bind(&MenuItemManager::menuItemCallback, curMethod);
 
 
+						if (separator)
+						{
+							Vector<WString> pathElements = StringUtil::split(path, L"/");
+							WString separatorPath;
+							if (pathElements.size() > 1)
+							{
+								const WString& lastElem = pathElements[pathElements.size() - 1];
+								separatorPath = path;
+								separatorPath.erase(path.size() - lastElem.size() - 1, lastElem.size() + 1);
+							}
+
+							mainWindow->getMenuBar().addSeparator(separatorPath, priority);
+						}
+
 						mainWindow->getMenuBar().addMenuItem(path, callback, priority, shortcutKey);
 						mainWindow->getMenuBar().addMenuItem(path, callback, priority, shortcutKey);
 						mMenuItems.push_back(path);
 						mMenuItems.push_back(path);
 					}
 					}
@@ -80,7 +96,7 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	bool MenuItemManager::parseMenuItemMethod(MonoMethod* method, WString& path, ShortcutKey& shortcut, INT32& priority) const
+	bool MenuItemManager::parseMenuItemMethod(MonoMethod* method, WString& path, ShortcutKey& shortcut, INT32& priority, bool& separator) const
 	{
 	{
 		if (!method->hasAttribute(mMenuItemAttribute))
 		if (!method->hasAttribute(mMenuItemAttribute))
 			return false;
 			return false;
@@ -99,6 +115,7 @@ namespace BansheeEngine
 		mShortcutField->getValue(menuItemAttrib, &shortcut);
 		mShortcutField->getValue(menuItemAttrib, &shortcut);
 		path = MonoUtil::monoToWString(monoPath);
 		path = MonoUtil::monoToWString(monoPath);
 		mPriorityField->getValue(menuItemAttrib, &priority);
 		mPriorityField->getValue(menuItemAttrib, &priority);
+		mSeparatorField->getValue(menuItemAttrib, &separator);
 
 
 		return true;
 		return true;
 	}
 	}

+ 11 - 17
TODO.txt

@@ -54,29 +54,22 @@ Code quality improvements:
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 Polish
 Polish
 
 
- - Duplicating a mesh doesn't properly render the mesh
-  - RenderableHandler, CameraHandler, LightInternal needs to be serialized by value to avoid issues when cloning them
-  - Per-object parameters should be updated just before object rendering
-  - (Later) Material will need a clone() method, in both C++ and C#, for when the user needs to customize a specific object instance
-
 Ribek use:
 Ribek use:
+ - Test level save/load (also test hidden & non-saveable scene objects)
+ - Hook up color picker to guicolor field
  - Camera, Renderable, Material, Texture inspector
  - Camera, Renderable, Material, Texture inspector
  - Project create/open window
  - Project create/open window
  - Load default layout on initial start
  - Load default layout on initial start
  - Test release mode
  - Test release mode
- - Test inspector selection, selecting a resource and adding/removing component updates
- - Test level save/load (also test hidden & non-saveable scene objects)
  - Ability to create assets in Project view (At least Material)
  - Ability to create assets in Project view (At least Material)
  - Need a way to add scene objects and components (and remove them)
  - Need a way to add scene objects and components (and remove them)
   - Need to add default components (Camera, Renderable, Light) to main menu
   - Need to add default components (Camera, Renderable, Light) to main menu
   - Adding scene objects should be doable from context menu in Hierarchy, by dropping a Prefab or by main Menu (undoable)
   - Adding scene objects should be doable from context menu in Hierarchy, by dropping a Prefab or by main Menu (undoable)
- - Hook up color picker to guicolor field
  - (Optionally, needed for GUI editing) GUISkin resource inspector & a way to inspect and save the default editor skin
  - (Optionally, needed for GUI editing) GUISkin resource inspector & a way to inspect and save the default editor skin
    - Will need C# wrapper for GUISkin (and a way to assign the current skin to a window)
    - Will need C# wrapper for GUISkin (and a way to assign the current skin to a window)
 
 
 First screenshot:
 First screenshot:
  - Additional menu bar items: 
  - Additional menu bar items: 
-  - File: Exit, Save Project, New Project, Open Project, Save Scene As
   - Edit: Undo/Redo, Cut/Copy/Paste/Duplicate/Delete(need to make sure it works in Hierarchy, with shortcuts), Frame Selected, Preferences, Play/Pause/Step, View/Move/rotate/scale
   - Edit: Undo/Redo, Cut/Copy/Paste/Duplicate/Delete(need to make sure it works in Hierarchy, with shortcuts), Frame Selected, Preferences, Play/Pause/Step, View/Move/rotate/scale
   - Assets (also add to context): Create(Folder, Material, Shader, Script, Prefab, GUI Skin), Show in explorer
   - Assets (also add to context): Create(Folder, Material, Shader, Script, Prefab, GUI Skin), Show in explorer
   - Game Object (also add to context): Create(Empty, Empty Child, Camera, Renderable, Point/Spot/Directional Light), Apply prefab, Break prefab, Revert prefab
   - Game Object (also add to context): Create(Empty, Empty Child, Camera, Renderable, Point/Spot/Directional Light), Apply prefab, Break prefab, Revert prefab
@@ -89,15 +82,13 @@ First screenshot:
  - (Optionally) Console window
  - (Optionally) Console window
 
 
 Other polish:
 Other polish:
+ - CmdRecordSO records an SO and all its children but it should only record a single SO
+   - Also it doesn't record a diff, but instead the whole object
+ - Crash on shutdown in mono_gchandle_free
  - C# inspectors for Point/Spot/Directional light
  - C# inspectors for Point/Spot/Directional light
  - C# interface for Font
  - C# interface for Font
  - Handle seems to lag behind the selected mesh
  - Handle seems to lag behind the selected mesh
  - ProjectLibrary seems to import some files on every start-up
  - ProjectLibrary seems to import some files on every start-up
- - Crash on shutdown in mono_gchandle_free
- - Add "focus on object" key (F) - animate it: rotate camera towards then speed towards while zooming in
- - Ortographic camera views (+ gizmo in scene view corner that shows camera orientation)
- - Drag to select in scene view
- - Update GUISlider so it works with the new style (and to have min/max limits, plus step size)
  - Replace "minimize" button in tabbed title bar with maximize and make sure it works (in both docked and floating mode)
  - Replace "minimize" button in tabbed title bar with maximize and make sure it works (in both docked and floating mode)
  - When I expand inspector elements and them come back to that object it should remember the previous state
  - When I expand inspector elements and them come back to that object it should remember the previous state
    - Add a chaching mechanism to inspector (likely based on instance ID & property names)
    - Add a chaching mechanism to inspector (likely based on instance ID & property names)
@@ -105,11 +96,13 @@ Other polish:
    - Consider saving this information with the serialized object
    - Consider saving this information with the serialized object
  - Make sure to persist EditorSettings
  - Make sure to persist EditorSettings
  - Import option inspectors for Texture, Mesh, Font
  - Import option inspectors for Texture, Mesh, Font
+ - Update GUISlider so it works with the new style (and to have min/max limits, plus step size)
+ - Add "focus on object" key (F) - animate it: rotate camera towards then speed towards while zooming in
+ - Ortographic camera views (+ gizmo in scene view corner that shows camera orientation)
+ - Drag to select in scene view
  - MenuBar - will likely need a way to mark elements as disabled when not appropriate (e.g. no "frame selected unless scene is focused")
  - MenuBar - will likely need a way to mark elements as disabled when not appropriate (e.g. no "frame selected unless scene is focused")
    - Likely use a user-provided callback to trigger when populating the menus
    - Likely use a user-provided callback to trigger when populating the menus
- - CmdRecordSO records an SO and all its children but it should only record a single SO
-   - Also it doesn't record a diff, but instead the whole object
- - Ctrl+D should perform duplicate in scene view as well
+ 
 
 
 Stage 2 polish:
 Stage 2 polish:
  - Inject an icon into an .exe (Win32 specific)
  - Inject an icon into an .exe (Win32 specific)
@@ -138,6 +131,7 @@ Finalizing:
  - Settings/Preferences window
  - Settings/Preferences window
  - Documentation
  - Documentation
  - Need to generate a proper merge of dev and preview branches
  - Need to generate a proper merge of dev and preview branches
+ - Save/Load project menu item does nothing at the moment
  - (Optionally) GUI tabbing to switch between elements
  - (Optionally) GUI tabbing to switch between elements
 
 
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------

+ 6 - 0
TODOExperimentation.txt

@@ -21,6 +21,12 @@ Before any rendering is done generate separate render queues for all elements
  - Initially this would be different queues for transparent & opaque, but later there might be more types
  - Initially this would be different queues for transparent & opaque, but later there might be more types
  - Store these queues per-camera
  - Store these queues per-camera
  - Do the same for lights (separate them by type most likely)
  - Do the same for lights (separate them by type most likely)
+ - Later:
+  - Extend render queues so they also sort by material (if needed, it should be easy to change sort order)
+  - Materials should be transformed into a set of material diffs (e.g. only set new shader, buffer, texture or cbuffer
+    if they don't match the previous material)
+	 - i.e. some elements in the render queue would be renderable elements (with no material info) and others
+	   would be material diffs that change the state
 
 
 Generate different RenderableController for each set of elements
 Generate different RenderableController for each set of elements
  - Will likely want to rename current LitTexRenderableController to OpaqueSomething
  - Will likely want to rename current LitTexRenderableController to OpaqueSomething