Browse Source

Fixed an issue with GUI manager where meshes were not getting released properly
Fixed an issue with GUI element destruction where layouts would get destroyed but not unregistered from their parent
Added GUIFoldout component

Marko Pintera 11 years ago
parent
commit
5bd0616417

+ 2 - 0
BansheeEditor/BansheeEditor.vcxproj

@@ -283,6 +283,7 @@
     <ClInclude Include="Include\BsGUIFieldBase.h" />
     <ClInclude Include="Include\BsGUIFloatField.h" />
     <ClInclude Include="Include\BsGUIComponentFoldout.h" />
+    <ClInclude Include="Include\BsGUIFoldout.h" />
     <ClInclude Include="Include\BsGUIIntField.h" />
     <ClInclude Include="Include\BsGUIDropButton.h" />
     <ClInclude Include="Include\BsGUITextField.h" />
@@ -342,6 +343,7 @@
     <ClCompile Include="Source\BsGUIFieldBase.cpp" />
     <ClCompile Include="Source\BsGUIFloatField.cpp" />
     <ClCompile Include="Source\BsGUIComponentFoldout.cpp" />
+    <ClCompile Include="Source\BsGUIFoldout.cpp" />
     <ClCompile Include="Source\BsGUIIntField.cpp" />
     <ClCompile Include="Source\BsGUIMenuBar.cpp" />
     <ClCompile Include="Source\BsGUIDropButton.cpp" />

+ 6 - 0
BansheeEditor/BansheeEditor.vcxproj.filters

@@ -201,6 +201,9 @@
     <ClInclude Include="Include\BsGUIComponentFoldout.h">
       <Filter>Header Files\Editor</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsGUIFoldout.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsEditorWidgetContainer.cpp">
@@ -350,5 +353,8 @@
     <ClCompile Include="Source\BsGUIComponentFoldout.cpp">
       <Filter>Source Files\Editor</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsGUIFoldout.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 1 - 0
BansheeEditor/Include/BsEditorPrerequisites.h

@@ -41,6 +41,7 @@ namespace BansheeEngine
 	class GUIColorField;
 	class GUIColor;
 	class GUIComponentFoldout;
+	class GUIFoldout;
 	class GUIDropButton;
 	class EditorWindowManager;
 	class DockManager;

+ 47 - 0
BansheeEditor/Include/BsGUIFoldout.h

@@ -0,0 +1,47 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsGUIElementContainer.h"
+
+namespace BansheeEngine
+{
+	class BS_ED_EXPORT GUIFoldout : public GUIElementContainer
+	{
+		struct PrivatelyConstruct {};
+
+	public:
+		static const String& getGUITypeName();
+		static const String& getFoldoutButtonStyleType();
+		static const String& getLabelStyleType();
+
+		static GUIFoldout* create(const HString& label, const GUIOptions& layoutOptions, const String& style = StringUtil::BLANK);
+		static GUIFoldout* create(const HString& label, const String& style = StringUtil::BLANK);
+
+		GUIFoldout(const PrivatelyConstruct& dummy, const HString& label, const String& style, const GUILayoutOptions& layoutOptions);
+
+		bool isExpanded() const { return mIsExpanded; }
+		void setExpanded(bool expanded);
+
+		/**
+		 * Changes the label of the foldout.
+		 */
+		void setContent(const GUIContent& content);
+
+		void _updateLayoutInternal(INT32 x, INT32 y, UINT32 width, UINT32 height,
+			RectI clipRect, UINT8 widgetDepth, UINT16 areaDepth);
+
+		Vector2I _getOptimalSize() const;
+
+		Event<void(bool)> onStateChanged;
+	protected:
+		virtual ~GUIFoldout();
+
+		void toggleTriggered(bool value);
+		void styleUpdated();
+
+		GUILabel* mLabel;
+		GUIToggle* mToggle;
+
+		bool mIsExpanded;
+	};
+}

+ 15 - 0
BansheeEditor/Source/BsEditorGUI.cpp

@@ -19,6 +19,7 @@
 #include "BsGUIVector3Field.h"
 #include "BsGUIVector4Field.h"
 #include "BsGUIComponentFoldout.h"
+#include "BsGUIFoldout.h"
 
 #include "BsFont.h"
 #include "BsFontImportOptions.h"
@@ -939,6 +940,20 @@ namespace BansheeEngine
 		cmpFoldoutStyle.subStyles[GUIComponentFoldout::getBackgroundStyleType()] = GUIComponentFoldout::getBackgroundStyleType();
 
 		mSkin.setStyle(GUIComponentFoldout::getGUITypeName(), cmpFoldoutStyle);
+
+		/************************************************************************/
+		/* 							     FOLDOUT                      		    */
+		/************************************************************************/
+		mSkin.setStyle(GUIFoldout::getFoldoutButtonStyleType(), cmpFoldoutBtnStyle);
+
+		GUIElementStyle foldoutStyle;
+		foldoutStyle.fixedHeight = true;
+		foldoutStyle.height = 12;
+		foldoutStyle.minWidth = 30;
+		foldoutStyle.subStyles[GUIFoldout::getLabelStyleType()] = GUIFoldout::getLabelStyleType();
+		foldoutStyle.subStyles[GUIFoldout::getFoldoutButtonStyleType()] = GUIFoldout::getFoldoutButtonStyleType();
+
+		mSkin.setStyle(GUIFoldout::getGUITypeName(), foldoutStyle);
 	}
 
 	HSpriteTexture EditorGUI::getTexture(const WString& name)

+ 156 - 0
BansheeEditor/Source/BsGUIFoldout.cpp

@@ -0,0 +1,156 @@
+#include "BsGUIFoldout.h"
+#include "BsGUIArea.h"
+#include "BsGUILayout.h"
+#include "BsGUILabel.h"
+#include "BsGUIToggle.h"
+#include "BsGUITexture.h"
+#include "BsBuiltinResources.h"
+#include "BsGUIWidget.h"
+#include "BsGUIMouseEvent.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	GUIFoldout::GUIFoldout(const PrivatelyConstruct& dummy, const HString& label, const String& style,
+		const GUILayoutOptions& layoutOptions)
+		:GUIElementContainer(layoutOptions, style), mToggle(nullptr), mIsExpanded(false)
+	{
+		mLabel = GUILabel::create(label, getSubStyleName(getLabelStyleType()));
+		mToggle = GUIToggle::create(HString(L""), getSubStyleName(getFoldoutButtonStyleType()));
+
+		_registerChildElement(mLabel);
+		_registerChildElement(mToggle);
+
+		mToggle->onToggled.connect(std::bind(&GUIFoldout::toggleTriggered, this, _1));
+	}
+
+	GUIFoldout::~GUIFoldout()
+	{
+
+	}
+
+	GUIFoldout* GUIFoldout::create(const HString& label, const GUIOptions& layoutOptions,
+		const String& style)
+	{
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIFoldout>(PrivatelyConstruct(), label, *curStyle, GUILayoutOptions::create(layoutOptions));
+	}
+
+	GUIFoldout* GUIFoldout::create(const HString& label, const String& style)
+	{
+		const String* curStyle = &style;
+		if (*curStyle == StringUtil::BLANK)
+			curStyle = &getGUITypeName();
+
+		return bs_new<GUIFoldout>(PrivatelyConstruct(), label, *curStyle, GUILayoutOptions::create());
+	}
+
+	void GUIFoldout::setExpanded(bool expanded)
+	{
+		if (mIsExpanded != expanded)
+		{
+			mIsExpanded = expanded;
+
+			if (mIsExpanded)
+				mToggle->toggleOn();
+			else
+				mToggle->toggleOff();
+
+			markContentAsDirty();
+
+			if (!onStateChanged.empty())
+				onStateChanged(mIsExpanded);
+		}
+	}
+
+	void GUIFoldout::setContent(const GUIContent& content)
+	{
+		mLabel->setContent(content);
+	}
+
+	void GUIFoldout::toggleTriggered(bool value)
+	{
+		mIsExpanded = value;
+
+		markContentAsDirty();
+
+		onStateChanged(value);
+	}
+
+	void GUIFoldout::_updateLayoutInternal(INT32 x, INT32 y, UINT32 width, UINT32 height,
+		RectI clipRect, UINT8 widgetDepth, UINT16 areaDepth)
+	{
+		UINT32 toggleOffset = 0;
+
+		{
+			Vector2I optimalSize = mToggle->_getOptimalSize();
+			INT32 yOffset = Math::roundToInt(((INT32)height - optimalSize.y) * 0.5f);
+
+			Vector2I offset(x, y + yOffset);
+			mToggle->_setOffset(offset);
+			mToggle->_setWidth(optimalSize.x);
+			mToggle->_setHeight(optimalSize.y);
+			mToggle->_setAreaDepth(areaDepth);
+			mToggle->_setWidgetDepth(widgetDepth);
+
+			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
+			mToggle->_setClipRect(elemClipRect);
+
+			toggleOffset = optimalSize.x;
+		}
+
+		{
+			Vector2I optimalSize = mLabel->_getOptimalSize();
+			INT32 yOffset = Math::roundToInt(((INT32)height - optimalSize.y) * 0.5f);
+
+			Vector2I offset(x + toggleOffset, y + yOffset);
+			mLabel->_setOffset(offset);
+			mLabel->_setWidth(optimalSize.x);
+			mLabel->_setHeight(optimalSize.y);
+			mLabel->_setAreaDepth(areaDepth);
+			mLabel->_setWidgetDepth(widgetDepth);
+
+			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
+			mLabel->_setClipRect(elemClipRect);
+		}
+	}
+
+	Vector2I GUIFoldout::_getOptimalSize() const
+	{
+		Vector2I optimalsize = mToggle->_getOptimalSize();
+		Vector2I labelOptimalSize = mLabel->_getOptimalSize();
+
+		optimalsize.x += labelOptimalSize.x;
+		optimalsize.y = std::max(optimalsize.y, labelOptimalSize.y);
+
+		return optimalsize;
+	}
+
+	void GUIFoldout::styleUpdated()
+	{
+		mLabel->setStyle(getSubStyleName(getLabelStyleType()));
+		mToggle->setStyle(getSubStyleName(getFoldoutButtonStyleType()));
+	}
+
+	const String& GUIFoldout::getGUITypeName()
+	{
+		static String typeName = "Foldout";
+		return typeName;
+	}
+
+	const String& GUIFoldout::getFoldoutButtonStyleType()
+	{
+		static String FOLDOUT_BUTTON_STYLE = "FoldoutButton";
+		return FOLDOUT_BUTTON_STYLE;
+	}
+
+	const String& GUIFoldout::getLabelStyleType()
+	{
+		static String FOLDOUT_LABEL_STYLE = "EditorFieldLabel";
+		return FOLDOUT_LABEL_STYLE;
+	}
+}

+ 7 - 0
BansheeEngine/Source/BsGUIElementBase.cpp

@@ -24,7 +24,14 @@ namespace BansheeEngine
 				GUIElement::destroy(element);
 			}
 			else
+			{
+				auto iterFind = std::find(mChildren.begin(), mChildren.end(), child);
+
+				if (iterFind != mChildren.end())
+					mChildren.erase(iterFind);
+
 				bs_delete(child);
+			}
 		}
 	}
 

+ 5 - 0
BansheeEngine/Source/BsGUIManager.cpp

@@ -134,6 +134,8 @@ namespace BansheeEngine
 
 		bs_delete<PoolAlloc>(mInputCaret);
 		bs_delete<PoolAlloc>(mInputSelection);
+
+		assert(mCachedGUIData.size() == 0);
 	}
 
 	void GUIManager::registerWidget(GUIWidget* widget)
@@ -521,6 +523,9 @@ namespace BansheeEngine
 
 			if(numMeshes < oldNumMeshes)
 			{
+				for (UINT32 i = numMeshes; i < oldNumMeshes; i++)
+					mMeshHeap->dealloc(renderData.cachedMeshes[i]);
+
 				renderData.cachedMeshes.resize(numMeshes);
 			}
 

+ 0 - 1
Inspector.txt

@@ -9,7 +9,6 @@ ARRAY TODO:
  - Need a GUIFoldout that doesn't have BG and is just a single button.
 
 TODO:
- - Ensure fields aren't updated from the app when in focus
  - Entire foldout should be clickable, not just the toggle button
  - Properly hook up UndoRedo, for both in-field and object-wide changes
    - How do I track Ctrl+Z and Ctrl+Y keys? And in general how do I distinguish when I send

+ 63 - 0
MBansheeEditor/GUI/GUIFoldout.cs

@@ -0,0 +1,63 @@
+using System;
+using System.Runtime.CompilerServices;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    public sealed class GUIFoldout : GUIElement
+    {
+        public delegate void OnToggledDelegate(bool expanded);
+
+        public event OnToggledDelegate OnToggled;
+
+        public GUIFoldout(GUIContent content, string style, params GUIOption[] options)
+        {
+            Internal_CreateInstance(this, content, style, options);
+        }
+
+        public GUIFoldout(GUIContent content, string style)
+        {
+            Internal_CreateInstance(this, content, style, new GUIOption[0]);
+        }
+
+        public GUIFoldout(GUIContent content, params GUIOption[] options)
+        {
+            Internal_CreateInstance(this, content, "", options);
+        }
+
+        public void SetContent(GUIContent content)
+        {
+            Internal_SetContent(mCachedPtr, content);
+        }
+
+        public bool IsExpanded()
+        {
+            bool expanded;
+            Internal_IsExpanded(mCachedPtr, out expanded);
+            return expanded;
+        }
+
+        public void SetExpanded(bool expanded)
+        {
+            Internal_SetExpanded(mCachedPtr, expanded);
+        }
+
+        private void DoOnToggled(bool expanded)
+        {
+            if (OnToggled != null)
+                OnToggled(expanded);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_CreateInstance(GUIFoldout instance, GUIContent content, string style, GUIOption[] options);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetContent(IntPtr nativeInstance, GUIContent content);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetExpanded(IntPtr nativeInstance, bool expanded);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_IsExpanded(IntPtr nativeInstance, out bool expanded);
+    }
+}

+ 1 - 0
MBansheeEditor/MBansheeEditor.csproj

@@ -46,6 +46,7 @@
     <Compile Include="Debug_Component2.cs" />
     <Compile Include="EditorApplication.cs" />
     <Compile Include="EditorWindow.cs" />
+    <Compile Include="GUI\GUIFoldout.cs" />
     <Compile Include="GUI\GUIGameObjectField.cs" />
     <Compile Include="GUI\GUIResourceField.cs" />
     <Compile Include="GUI\GUIVector3Field.cs" />

+ 27 - 0
SBansheeEditor/Include/BsScriptGUIFoldout.h

@@ -0,0 +1,27 @@
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptGUIElement.h"
+
+namespace BansheeEngine
+{
+	class BS_SCR_BED_EXPORT ScriptGUIFoldout : public TScriptGUIElement<ScriptGUIFoldout>
+	{
+	public:
+		SCRIPT_OBJ(BansheeEditorAssemblyName, "BansheeEditor", "GUIFoldout")
+
+	private:
+		static void internal_createInstance(MonoObject* instance, MonoObject* content, MonoString* style, MonoArray* guiOptions);
+		static void internal_setContent(ScriptGUIFoldout* nativeInstance, MonoObject* content);
+		static void internal_setExpanded(ScriptGUIFoldout* nativeInstance, bool expanded);
+		static void internal_getIsExpanded(ScriptGUIFoldout* nativeInstance, bool* isExpanded);
+
+		static void onToggled(MonoObject* instance, bool expanded);
+
+		ScriptGUIFoldout(MonoObject* instance, GUIFoldout* foldout);
+
+		typedef void(__stdcall *OnToggledThunkDef) (MonoObject*, bool, MonoException**);
+
+		static OnToggledThunkDef onToggledThunk;
+	};
+}

+ 2 - 0
SBansheeEditor/SBansheeEditor.vcxproj

@@ -235,6 +235,7 @@
     <ClInclude Include="Include\BsScriptGUIColorField.h" />
     <ClInclude Include="Include\BsScriptGUIFloatField.h" />
     <ClInclude Include="Include\BsScriptGUIComponentFoldout.h" />
+    <ClInclude Include="Include\BsScriptGUIFoldout.h" />
     <ClInclude Include="Include\BsScriptGUIGameObjectField.h" />
     <ClInclude Include="Include\BsScriptGUIIntField.h" />
     <ClInclude Include="Include\BsScriptGUIPanelContainer.h" />
@@ -256,6 +257,7 @@
     <ClCompile Include="Source\BsScriptGUIColorField.cpp" />
     <ClCompile Include="Source\BsScriptGUIFloatField.cpp" />
     <ClCompile Include="Source\BsScriptGUIComponentFoldout.cpp" />
+    <ClCompile Include="Source\BsScriptGUIFoldout.cpp" />
     <ClCompile Include="Source\BsScriptGUIGameObjectField.cpp" />
     <ClCompile Include="Source\BsScriptGUIIntField.cpp" />
     <ClCompile Include="Source\BsScriptGUIPanelContainer.cpp" />

+ 6 - 0
SBansheeEditor/SBansheeEditor.vcxproj.filters

@@ -72,6 +72,9 @@
     <ClInclude Include="Include\BsScriptGUIComponentFoldout.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptGUIFoldout.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptEditorPlugin.cpp">
@@ -131,5 +134,8 @@
     <ClCompile Include="Source\BsScriptGUIComponentFoldout.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptGUIFoldout.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 86 - 0
SBansheeEditor/Source/BsScriptGUIFoldout.cpp

@@ -0,0 +1,86 @@
+#include "BsScriptGUIFoldout.h"
+#include "BsScriptMeta.h"
+#include "BsMonoField.h"
+#include "BsMonoClass.h"
+#include "BsMonoManager.h"
+#include "BsMonoMethod.h"
+#include "BsSpriteTexture.h"
+#include "BsMonoUtil.h"
+#include "BsGUILayout.h"
+#include "BsGUIFoldout.h"
+#include "BsGUIOptions.h"
+#include "BsGUIContent.h"
+#include "BsScriptGUIElementStyle.h"
+#include "BsScriptGUILayout.h"
+#include "BsScriptGUIArea.h"
+#include "BsScriptHString.h"
+#include "BsScriptGUIContent.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	ScriptGUIFoldout::OnToggledThunkDef ScriptGUIFoldout::onToggledThunk;
+
+	ScriptGUIFoldout::ScriptGUIFoldout(MonoObject* instance, GUIFoldout* foldout)
+		:TScriptGUIElement(instance, foldout)
+	{
+
+	}
+
+	void ScriptGUIFoldout::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptGUIFoldout::internal_createInstance);
+		metaData.scriptClass->addInternalCall("Internal_SetContent", &ScriptGUIFoldout::internal_setContent);
+		metaData.scriptClass->addInternalCall("Internal_SetExpanded", &ScriptGUIFoldout::internal_setExpanded);
+		metaData.scriptClass->addInternalCall("Internal_IsExpanded", &ScriptGUIFoldout::internal_getIsExpanded);
+
+		onToggledThunk = (OnToggledThunkDef)metaData.scriptClass->getMethod("DoOnToggled", 1).getThunk();
+	}
+
+	void ScriptGUIFoldout::internal_createInstance(MonoObject* instance, MonoObject* content, MonoString* style, MonoArray* guiOptions)
+	{
+		GUIOptions options;
+
+		UINT32 arrayLen = (UINT32)mono_array_length(guiOptions);
+		for (UINT32 i = 0; i < arrayLen; i++)
+			options.addOption(mono_array_get(guiOptions, GUIOption, i));
+
+		HString label = ScriptGUIContent::getText(content);
+		GUIFoldout* guiFoldout = GUIFoldout::create(label);
+
+		guiFoldout->onStateChanged.connect(std::bind(&ScriptGUIFoldout::onToggled, instance, _1));
+
+		ScriptGUIFoldout* nativeInstance = new (bs_alloc<ScriptGUIFoldout>()) ScriptGUIFoldout(instance, guiFoldout);
+	}
+
+	void ScriptGUIFoldout::internal_setContent(ScriptGUIFoldout* nativeInstance, MonoObject* content)
+	{
+		GUIContent nativeContent(ScriptGUIContent::getText(content), ScriptGUIContent::getImage(content), ScriptGUIContent::getTooltip(content));
+
+		GUIFoldout* guiFoldout = static_cast<GUIFoldout*>(nativeInstance->getGUIElement());
+		guiFoldout->setContent(nativeContent);
+	}
+
+	void ScriptGUIFoldout::internal_setExpanded(ScriptGUIFoldout* nativeInstance, bool expanded)
+	{
+		GUIFoldout* foldout = static_cast<GUIFoldout*>(nativeInstance->getGUIElement());
+
+		foldout->setExpanded(expanded);
+	}
+
+	void ScriptGUIFoldout::internal_getIsExpanded(ScriptGUIFoldout* nativeInstance, bool* isExpanded)
+	{
+		GUIFoldout* foldout = static_cast<GUIFoldout*>(nativeInstance->getGUIElement());
+
+		*isExpanded = foldout->isExpanded();
+	}
+
+	void ScriptGUIFoldout::onToggled(MonoObject* instance, bool expanded)
+	{
+		MonoException* exception = nullptr;
+		onToggledThunk(instance, expanded, &exception);
+
+		MonoUtil::throwIfException(exception);
+	}
+}