Bläddra i källkod

Various fixes to multi-select list boxes
Fixed an issue where script interop objects for handle sliders weren't being deleted properly on assembly unload

BearishSun 10 år sedan
förälder
incheckning
0e88d4f0cb

+ 1 - 0
BansheeEditor/Source/BsBuiltinEditorResources.cpp

@@ -914,6 +914,7 @@ namespace BansheeEngine
 		dropDownToggleEntryBtnStyle.height = 18;
 		dropDownToggleEntryBtnStyle.height = 18;
 		dropDownToggleEntryBtnStyle.width = 30;
 		dropDownToggleEntryBtnStyle.width = 30;
 		dropDownToggleEntryBtnStyle.border.left = 17;
 		dropDownToggleEntryBtnStyle.border.left = 17;
+		dropDownToggleEntryBtnStyle.contentOffset.left = 17;
 		dropDownToggleEntryBtnStyle.font = font;
 		dropDownToggleEntryBtnStyle.font = font;
 		dropDownToggleEntryBtnStyle.fontSize = DefaultFontSize;
 		dropDownToggleEntryBtnStyle.fontSize = DefaultFontSize;
 		dropDownToggleEntryBtnStyle.textHorzAlign = THA_Left;
 		dropDownToggleEntryBtnStyle.textHorzAlign = THA_Left;

+ 12 - 0
BansheeEngine/Include/BsGUIDropDownContent.h

@@ -111,22 +111,34 @@ namespace BansheeEngine
 		 */
 		 */
 		bool _commandEvent(const GUICommandEvent& ev) override;
 		bool _commandEvent(const GUICommandEvent& ev) override;
 
 
+		/**
+		 * @copydoc	GUIElementContainer::_mouseEvent
+		 */
+		bool _mouseEvent(const GUIMouseEvent& ev) override;
+
 		/**
 		/**
 		 * @brief	Marks the element with the specified index as selected.
 		 * @brief	Marks the element with the specified index as selected.
+		 * 		
+		 * @param	Index of the displayed element (indexing visible elements).
 		 */
 		 */
 		void setSelected(UINT32 idx);
 		void setSelected(UINT32 idx);
 
 
 		/**
 		/**
 		 * @brief	Selects the next available non-separator entry.
 		 * @brief	Selects the next available non-separator entry.
+		 * 			
+		 * @param	Index of the menu element.
 		 */
 		 */
 		void selectNext(UINT32 startIdx);
 		void selectNext(UINT32 startIdx);
 
 
 		/**
 		/**
 		 * @brief	Selects the previous available non-separator entry.
 		 * @brief	Selects the previous available non-separator entry.
+		 * 			
+		 * @param	Index of the menu element.
 		 */
 		 */
 		void selectPrevious(UINT32 startIdx);
 		void selectPrevious(UINT32 startIdx);
 
 
 		GUIDropDownData mDropDownData;
 		GUIDropDownData mDropDownData;
+		Vector<bool> mStates;
 		Vector<VisibleElement> mVisibleElements;
 		Vector<VisibleElement> mVisibleElements;
 		UINT32 mSelectedIdx;
 		UINT32 mSelectedIdx;
 		UINT32 mRangeStart, mRangeEnd;
 		UINT32 mRangeStart, mRangeEnd;

+ 1 - 0
BansheeEngine/Include/BsGUIDropDownMenu.h

@@ -15,6 +15,7 @@ namespace BansheeEngine
 	struct BS_EXPORT GUIDropDownData
 	struct BS_EXPORT GUIDropDownData
 	{
 	{
 		Vector<GUIDropDownDataEntry> entries;
 		Vector<GUIDropDownDataEntry> entries;
+		Vector<bool> states;
 		UnorderedMap<WString, HString> localizedNames;
 		UnorderedMap<WString, HString> localizedNames;
 	};
 	};
 
 

+ 2 - 1
BansheeEngine/Include/BsGUIListBox.h

@@ -136,7 +136,8 @@ namespace BansheeEngine
 	private:
 	private:
 		Vector<HString> mElements;
 		Vector<HString> mElements;
 		Vector<bool> mElementStates;
 		Vector<bool> mElementStates;
-		bool mIsListBoxOpen;
+		GameObjectHandle<GUIDropDownMenu> mDropDownBox;
+
 		bool mIsMultiselect;
 		bool mIsMultiselect;
 	};
 	};
 }
 }

+ 33 - 6
BansheeEngine/Source/BsGUIDropDownContent.cpp

@@ -21,10 +21,11 @@ namespace BansheeEngine
 
 
 	GUIDropDownContent::GUIDropDownContent(GUIDropDownMenu::DropDownSubMenu* parent, const GUIDropDownData& dropDownData, 
 	GUIDropDownContent::GUIDropDownContent(GUIDropDownMenu::DropDownSubMenu* parent, const GUIDropDownData& dropDownData, 
 		const String& style, const GUIDimensions& dimensions)
 		const String& style, const GUIDimensions& dimensions)
-		:GUIElementContainer(dimensions, style), mDropDownData(dropDownData), mKeyboardFocus(true),
-		mSelectedIdx(UINT_MAX), mRangeStart(0), mRangeEnd(0), mParent(parent), mIsToggle(false)
+		:GUIElementContainer(dimensions, style), mDropDownData(dropDownData), mKeyboardFocus(true), 
+		mStates(dropDownData.states), mSelectedIdx(UINT_MAX), mRangeStart(0), mRangeEnd(0), mParent(parent), 
+		mIsToggle(parent->getType() == GUIDropDownType::MultiListBox)
 	{
 	{
-		mIsToggle = mParent->getType() == GUIDropDownType::MultiListBox;
+
 	}
 	}
 
 
 	GUIDropDownContent::~GUIDropDownContent()
 	GUIDropDownContent::~GUIDropDownContent()
@@ -86,6 +87,7 @@ namespace BansheeEngine
 			[&](UINT32 idx, UINT32 visIdx)
 			[&](UINT32 idx, UINT32 visIdx)
 		{ 
 		{ 
 			setSelected(visIdx);
 			setSelected(visIdx);
+			mStates[idx] = !mStates[idx];
 			mParent->elementActivated(idx, mVisibleElements[visIdx].button->_getLayoutData().area);
 			mParent->elementActivated(idx, mVisibleElements[visIdx].button->_getLayoutData().area);
 		};
 		};
 
 
@@ -101,6 +103,10 @@ namespace BansheeEngine
 		mRangeStart = start;
 		mRangeStart = start;
 		mRangeEnd = end;
 		mRangeEnd = end;
 		
 		
+		UINT32 range = end - start;
+		if (mSelectedIdx != UINT_MAX && mSelectedIdx > range)
+			mSelectedIdx = UINT_MAX;
+
 		mVisibleElements.clear();
 		mVisibleElements.clear();
 		UINT32 curVisIdx = 0;
 		UINT32 curVisIdx = 0;
 		for (UINT32 i = start; i < end; i++)
 		for (UINT32 i = start; i < end; i++)
@@ -124,7 +130,13 @@ namespace BansheeEngine
 			else
 			else
 			{
 			{
 				if (mIsToggle)
 				if (mIsToggle)
-					visElem.button = GUIToggle::create(getElementLocalizedName(i), getSubStyleName(ENTRY_STYLE_TYPE));
+				{
+					GUIToggle* toggle = GUIToggle::create(getElementLocalizedName(i), getSubStyleName(ENTRY_TOGGLE_STYLE_TYPE));
+					if (mStates[i])
+						toggle->toggleOn();
+
+					visElem.button = toggle;					
+				}
 				else
 				else
 					visElem.button = GUIButton::create(getElementLocalizedName(i), getSubStyleName(ENTRY_STYLE_TYPE));
 					visElem.button = GUIButton::create(getElementLocalizedName(i), getSubStyleName(ENTRY_STYLE_TYPE));
 
 
@@ -196,13 +208,13 @@ namespace BansheeEngine
 			if (mSelectedIdx == UINT_MAX)
 			if (mSelectedIdx == UINT_MAX)
 				selectNext(0);
 				selectNext(0);
 			else
 			else
-				selectNext(mSelectedIdx + 1);
+				selectNext(mVisibleElements[mSelectedIdx].idx + 1);
 			return true;
 			return true;
 		case GUICommandEventType::MoveUp:
 		case GUICommandEventType::MoveUp:
 			if (mSelectedIdx == UINT_MAX)
 			if (mSelectedIdx == UINT_MAX)
 				selectNext(0);
 				selectNext(0);
 			else
 			else
-				selectPrevious(mSelectedIdx - 1);
+				selectPrevious(mVisibleElements[mSelectedIdx].idx - 1);
 			return true;
 			return true;
 		case GUICommandEventType::Escape:
 		case GUICommandEventType::Escape:
 		case GUICommandEventType::MoveLeft:
 		case GUICommandEventType::MoveLeft:
@@ -236,6 +248,21 @@ namespace BansheeEngine
 		return baseReturn;
 		return baseReturn;
 	}
 	}
 
 
+	bool GUIDropDownContent::_mouseEvent(const GUIMouseEvent& ev)
+	{
+		if (ev.getType() == GUIMouseEventType::MouseWheelScroll)
+		{
+			if (ev.getWheelScrollAmount() < 0)
+				mParent->scrollDown();
+			else
+				mParent->scrollUp();
+
+			return true;
+		}
+
+		return false;
+	}
+
 	void GUIDropDownContent::setSelected(UINT32 idx)
 	void GUIDropDownContent::setSelected(UINT32 idx)
 	{
 	{
 		if (mSelectedIdx != UINT_MAX)
 		if (mSelectedIdx != UINT_MAX)

+ 4 - 0
BansheeEngine/Source/BsGUIDropDownMenu.cpp

@@ -131,6 +131,7 @@ namespace BansheeEngine
 		GUIElement::destroy(mBackHitBox);
 		GUIElement::destroy(mBackHitBox);
 		GUIElement::destroy(mCaptureHitBox);
 		GUIElement::destroy(mCaptureHitBox);
 		bs_delete(mRootMenu);
 		bs_delete(mRootMenu);
+		mRootMenu = nullptr;
 
 
 		CGUIWidget::onDestroyed();
 		CGUIWidget::onDestroyed();
 	}
 	}
@@ -395,6 +396,9 @@ namespace BansheeEngine
 
 
 		mContent->setRange(pageStart, pageEnd);
 		mContent->setRange(pageStart, pageEnd);
 
 
+		if (mSubMenu == nullptr)
+			mContent->setKeyboardFocus(true);
+
 		// Resize and reposition areas
 		// Resize and reposition areas
 		mBackgroundPanel->setWidth(width - contentOffset);
 		mBackgroundPanel->setWidth(width - contentOffset);
 		mBackgroundPanel->setHeight(pageHeight);
 		mBackgroundPanel->setHeight(pageHeight);

+ 21 - 15
BansheeEngine/Source/BsGUIListBox.cpp

@@ -20,8 +20,7 @@ namespace BansheeEngine
 	}
 	}
 
 
 	GUIListBox::GUIListBox(const String& styleName, const Vector<HString>& elements, bool isMultiselect, const GUIDimensions& dimensions)
 	GUIListBox::GUIListBox(const String& styleName, const Vector<HString>& elements, bool isMultiselect, const GUIDimensions& dimensions)
-		:GUIButtonBase(styleName, GUIContent(HString(L"")), dimensions), mElements(elements), mIsListBoxOpen(false),
-		mIsMultiselect(isMultiselect)
+		:GUIButtonBase(styleName, GUIContent(HString(L"")), dimensions), mElements(elements), mIsMultiselect(isMultiselect)
 	{
 	{
 		mElementStates.resize(elements.size(), false);
 		mElementStates.resize(elements.size(), false);
 		if (!mIsMultiselect && mElementStates.size() > 0)
 		if (!mIsMultiselect && mElementStates.size() > 0)
@@ -52,9 +51,9 @@ namespace BansheeEngine
 
 
 	void GUIListBox::setElements(const Vector<HString>& elements)
 	void GUIListBox::setElements(const Vector<HString>& elements)
 	{
 	{
-		bool wasOpen = mIsListBoxOpen;
+		bool wasOpen = mDropDownBox != nullptr;
 
 
-		if(mIsListBoxOpen)
+		if(wasOpen)
 			closeListBox();
 			closeListBox();
 
 
 		mElements = elements;
 		mElements = elements;
@@ -93,13 +92,20 @@ namespace BansheeEngine
 		if (!mIsMultiselect)
 		if (!mIsMultiselect)
 			return;
 			return;
 
 
+		bool wasOpen = mDropDownBox != nullptr;
+
+		if (wasOpen)
+			closeListBox();
+
 		UINT32 min = (UINT32)std::min(mElementStates.size(), states.size());
 		UINT32 min = (UINT32)std::min(mElementStates.size(), states.size());
 
 
 		for (UINT32 i = 0; i < min; i++)
 		for (UINT32 i = 0; i < min; i++)
-		{
-			if (mElementStates[i] != states[i])
-				elementSelected(i);
-		}
+			mElementStates[i] = states[i];
+
+		updateContents();
+
+		if (wasOpen)
+			openListBox();
 	}
 	}
 
 
 	bool GUIListBox::_mouseEvent(const GUIMouseEvent& ev)
 	bool GUIListBox::_mouseEvent(const GUIMouseEvent& ev)
@@ -108,7 +114,7 @@ namespace BansheeEngine
 
 
 		if(ev.getType() == GUIMouseEventType::MouseDown)
 		if(ev.getType() == GUIMouseEventType::MouseDown)
 		{
 		{
-			if(!mIsListBoxOpen)
+			if (mDropDownBox == nullptr)
 				openListBox();
 				openListBox();
 			else
 			else
 				closeListBox();
 				closeListBox();
@@ -168,28 +174,28 @@ namespace BansheeEngine
 		desc.camera = widget->getCamera();
 		desc.camera = widget->getCamera();
 		desc.skin = widget->getSkinResource();
 		desc.skin = widget->getSkinResource();
 		desc.placement = DropDownAreaPlacement::aroundBoundsHorz(mClippedBounds);
 		desc.placement = DropDownAreaPlacement::aroundBoundsHorz(mClippedBounds);
-		
+		desc.dropDownData.states = mElementStates;
+
 		GUIDropDownType type;
 		GUIDropDownType type;
 		if (mIsMultiselect)
 		if (mIsMultiselect)
 			type = GUIDropDownType::MultiListBox;
 			type = GUIDropDownType::MultiListBox;
 		else
 		else
 			type = GUIDropDownType::ListBox;
 			type = GUIDropDownType::ListBox;
 
 
-		GameObjectHandle<GUIDropDownMenu> dropDownBox = GUIDropDownBoxManager::instance().openDropDownBox(
+		mDropDownBox = GUIDropDownBoxManager::instance().openDropDownBox(
 			desc, type, std::bind(&GUIListBox::onListBoxClosed, this));
 			desc, type, std::bind(&GUIListBox::onListBoxClosed, this));
 
 
 		_setOn(true);
 		_setOn(true);
-		mIsListBoxOpen = true;
 	}
 	}
 
 
 	void GUIListBox::closeListBox()
 	void GUIListBox::closeListBox()
 	{
 	{
-		if(mIsListBoxOpen)
+		if (mDropDownBox != nullptr)
 		{
 		{
 			GUIDropDownBoxManager::instance().closeDropDownBox();
 			GUIDropDownBoxManager::instance().closeDropDownBox();
 
 
 			_setOn(false);
 			_setOn(false);
-			mIsListBoxOpen = false;
+			mDropDownBox = nullptr;
 		}
 		}
 	}
 	}
 
 
@@ -227,6 +233,6 @@ namespace BansheeEngine
 	void GUIListBox::onListBoxClosed()
 	void GUIListBox::onListBoxClosed()
 	{
 	{
 		_setOn(false);
 		_setOn(false);
-		mIsListBoxOpen = false;
+		mDropDownBox = nullptr;
 	}
 	}
 }
 }

+ 2 - 9
MBansheeEditor/Inspectors/CameraInspector.cs

@@ -54,15 +54,6 @@ namespace BansheeEditor
                     }
                     }
                 };
                 };
 
 
-                {
-                    ulong layers = 0;
-                    bool[] states = layersField.States;
-                    for (int i = 0; i < states.Length; i++)
-                        layers |= states[i] ? Layers.Values[i] : 0;
-
-                    layersValue = layers;
-                }
-
                 fieldOfView.OnChanged += x => camera.FieldOfView = x;
                 fieldOfView.OnChanged += x => camera.FieldOfView = x;
                 orthoHeight.OnChanged += x => camera.OrthoHeight = x;
                 orthoHeight.OnChanged += x => camera.OrthoHeight = x;
                 aspectField.OnChanged += x => camera.AspectRatio = x;
                 aspectField.OnChanged += x => camera.AspectRatio = x;
@@ -235,6 +226,8 @@ namespace BansheeEditor
                     states[i] = (camera.Layers & Layers.Values[i]) == Layers.Values[i];
                     states[i] = (camera.Layers & Layers.Values[i]) == Layers.Values[i];
 
 
                 layersField.States = states;
                 layersField.States = states;
+                layersValue = camera.Layers;
+
                 anythingModified = true;
                 anythingModified = true;
             }
             }
 
 

+ 1 - 1
SBansheeEditor/Include/BsScriptHandleSlider.h

@@ -15,7 +15,7 @@ namespace BansheeEngine
 	{
 	{
 	public:
 	public:
 		ScriptHandleSliderBase(MonoObject* managedInstance);
 		ScriptHandleSliderBase(MonoObject* managedInstance);
-		virtual ~ScriptHandleSliderBase() { }
+		virtual ~ScriptHandleSliderBase();
 
 
 		/**
 		/**
 		 * @brief	Returns the internal native handle slider.
 		 * @brief	Returns the internal native handle slider.

+ 11 - 1
SBansheeEditor/Source/BsScriptGUIEnumField.cpp

@@ -187,6 +187,16 @@ namespace BansheeEngine
 
 
 	void ScriptGUIEnumField::onSelectionChanged(MonoObject* instance, UINT64 newIndex, bool enabled)
 	void ScriptGUIEnumField::onSelectionChanged(MonoObject* instance, UINT64 newIndex, bool enabled)
 	{
 	{
-		MonoUtil::invokeThunk(onSelectionChangedThunk, instance, newIndex);
+		ScriptGUIEnumField* nativeInstance = ScriptGUIEnumField::toNative(instance);
+		GUIListBoxField* field = static_cast<GUIListBoxField*>(nativeInstance->getGUIElement());
+
+		UINT32 outValue = 0;
+
+		const Vector<UINT64>& values = nativeInstance->mValues;
+		Vector<bool> states = field->getElementStates();
+		for (UINT32 i = 0; i < (UINT32)values.size(); i++)
+			outValue |= states[i] ? values[i] : 0;
+
+		MonoUtil::invokeThunk(onSelectionChangedThunk, instance, outValue);
 	}
 	}
 }
 }

+ 5 - 0
SBansheeEditor/Source/BsScriptHandleSlider.cpp

@@ -11,6 +11,11 @@ namespace BansheeEngine
 		ScriptHandleSliderManager::instance().registerSlider(this);
 		ScriptHandleSliderManager::instance().registerSlider(this);
 	}
 	}
 
 
+	ScriptHandleSliderBase::~ScriptHandleSliderBase()
+	{
+		ScriptHandleSliderManager::instance().unregisterSlider(this);
+	}
+
 	void ScriptHandleSliderBase::destroy()
 	void ScriptHandleSliderBase::destroy()
 	{
 	{
 		ScriptHandleSliderManager::instance().unregisterSlider(this);
 		ScriptHandleSliderManager::instance().unregisterSlider(this);