Parcourir la source

Fixed a recently introduced resource loading issue
Added hover/active states to toolbar buttons
Fixed missing icons for GUISkin resource
Fixed incorrect icon for SpriteTexture resource
Removed splitter active state from menu bar as it looked bad

BearishSun il y a 10 ans
Parent
commit
a74ef4d6f8

+ 4 - 2
BansheeCore/Include/BsResources.h

@@ -200,9 +200,11 @@ namespace BansheeEngine
 		Event<void(const HResource&)> onResourceModified; // TODO - Not used, implement when I add hot-swapping
 	private:
 		/**
-		 * @brief	Starts resource loading or returns an already loaded resource.
+		 * @brief	Starts resource loading or returns an already loaded resource. Both UUID and filePath must match the
+		 * 			same resource, although you may provide an empty path in which case the resource will be retrieved
+		 * 			from memory if its currently loaded.
 		 */
-		HResource loadInternal(const Path& filePath, bool synchronous, bool loadDependencies);
+		HResource loadInternal(const String& UUID, const Path& filePath, bool synchronous, bool loadDependencies);
 
 		/**
 		 * @brief	Performs actually reading and deserializing of the resource file. 

+ 93 - 112
BansheeCore/Source/BsResources.cpp

@@ -35,45 +35,28 @@ namespace BansheeEngine
 
 	HResource Resources::load(const Path& filePath, bool loadDependencies)
 	{
-		return loadInternal(filePath, true, loadDependencies);
+		String uuid;
+		bool foundUUID = getUUIDFromFilePath(filePath, uuid);
+
+		if (!foundUUID)
+			uuid = UUIDGenerator::generateRandom();
+
+		return loadInternal(uuid, filePath, true, loadDependencies);
 	}
 
 	HResource Resources::loadAsync(const Path& filePath, bool loadDependencies)
 	{
-		return loadInternal(filePath, false, loadDependencies);
+		String uuid;
+		bool foundUUID = getUUIDFromFilePath(filePath, uuid);
+
+		if (!foundUUID)
+			uuid = UUIDGenerator::generateRandom();
+
+		return loadInternal(uuid, filePath, false, loadDependencies);
 	}
 
 	HResource Resources::loadFromUUID(const String& uuid, bool async, bool loadDependencies)
 	{
-		HResource outputResource;
-		bool alreadyLoading = false;
-		{
-			BS_LOCK_MUTEX(mLoadedResourceMutex);
-			auto iterFind = mLoadedResources.find(uuid);
-			if (iterFind != mLoadedResources.end()) // Resource is already loaded
-			{
-				outputResource = iterFind->second;
-				alreadyLoading = true;
-
-			}
-		}
-
-		if (!alreadyLoading)
-		{
-			BS_LOCK_MUTEX(mInProgressResourcesMutex);
-			auto iterFind2 = mInProgressResources.find(uuid);
-			if (iterFind2 != mInProgressResources.end())
-			{
-				outputResource = iterFind2->second->resource;
-
-				// Previously being loaded as async but now we want it synced, so we wait
-				if (!async)
-					outputResource.blockUntilLoaded();
-
-				alreadyLoading = true;
-			}
-		}
-
 		Path filePath;
 		bool foundPath = false;
 
@@ -88,52 +71,28 @@ namespace BansheeEngine
 			}
 		}
 
-		if (!alreadyLoading)
+		if (!foundPath)
 		{
-			if (!foundPath)
-			{
-				gDebug().logWarning("Cannot load resource. Resource with UUID '" + uuid + "' doesn't exist.");
-
-				HResource outputResource(uuid);
-				return outputResource;
-			}
+			gDebug().logWarning("Cannot load resource. Resource with UUID '" + uuid + "' doesn't exist.");
 
-			return loadInternal(filePath, !async, loadDependencies);
-		}
-		else
-		{
-			// Load dependencies
-			if (loadDependencies && foundPath)
-			{
-				// Load saved resource data
-				FileDecoder fs(filePath);
-				SPtr<SavedResourceData> savedResourceData = std::static_pointer_cast<SavedResourceData>(fs.decode());
-
-				{
-					for (auto& dependency : savedResourceData->getDependencies())
-					{
-						loadFromUUID(dependency, async);
-					}
-				}
-			}
+			HResource outputResource(uuid);
+			loadComplete(outputResource);
 
 			return outputResource;
 		}
+
+		return loadInternal(uuid, filePath, !async, loadDependencies);
 	}
 
-	HResource Resources::loadInternal(const Path& filePath, bool synchronous, bool loadDependencies)
+	HResource Resources::loadInternal(const String& UUID, const Path& filePath, bool synchronous, bool loadDependencies)
 	{
-		String uuid;
-		bool foundUUID = getUUIDFromFilePath(filePath, uuid);
-
-		if(!foundUUID)
-			uuid = UUIDGenerator::generateRandom();
-
 		HResource outputResource;
+
+		// Check if resource is already full loaded
 		bool alreadyLoading = false;
 		{
 			BS_LOCK_MUTEX(mLoadedResourceMutex);
-			auto iterFind = mLoadedResources.find(uuid);
+			auto iterFind = mLoadedResources.find(UUID);
 			if(iterFind != mLoadedResources.end()) // Resource is already loaded
 			{
 				outputResource = iterFind->second;
@@ -141,77 +100,81 @@ namespace BansheeEngine
 			}
 		}
 
+		// Check if resource is already being loaded on a worker thread
+		bool loadInProgress = false;
 		if (!alreadyLoading) // If not already detected as loaded
 		{
-			BS_LOCK_MUTEX(mInProgressResourcesMutex);
-			auto iterFind2 = mInProgressResources.find(uuid);
-			if(iterFind2 != mInProgressResources.end()) 
 			{
-				outputResource = iterFind2->second->resource;
-
-				// Previously being loaded as async but now we want it synced, so we wait
-				if (synchronous)
-					outputResource.blockUntilLoaded();
+				BS_LOCK_MUTEX(mInProgressResourcesMutex);
+				auto iterFind2 = mInProgressResources.find(UUID);
+				if (iterFind2 != mInProgressResources.end())
+				{
+					outputResource = iterFind2->second->resource;
 
-				alreadyLoading = true;
+					alreadyLoading = true;
+					loadInProgress = true;
+				}
 			}
+
+			// Previously being loaded as async but now we want it synced, so we wait
+			if (loadInProgress && synchronous)
+				outputResource.blockUntilLoaded();
 		}
 
 		// Not loaded and not in progress, start loading of new resource
 		// (or if already loaded or in progress, load any dependencies)
 		if (!alreadyLoading)
+			outputResource = HResource(UUID);
+
+		// We have nowhere to load from, warn and complete load if a file path was provided,
+		// otherwise pass through as we might just want to load from memory. 
+		if (!filePath.isEmpty() && !FileSystem::isFile(filePath))
 		{
-			outputResource = HResource(uuid);
+			LOGWRN("Specified file: " + filePath.toString() + " doesn't exist.");
 
-			if (!FileSystem::isFile(filePath))
-			{
-				LOGWRN("Specified file: " + filePath.toString() + " doesn't exist.");
+			// Complete the load as that the depedency counter is properly reduced, in case this 
+			// is a dependency of some other resource.
+			loadComplete(outputResource);
+			assert(!loadInProgress); // Resource already being loaded but we can't find its path now?
 
-				loadComplete(outputResource);
-				return outputResource;
-			}
+			return outputResource;
 		}
-		else
+
+		// Load dependency data if a file path is provided
+		SPtr<SavedResourceData> savedResourceData;
+		if (!filePath.isEmpty())
 		{
-			if (!FileSystem::isFile(filePath))
-			{
-				LOGWRN("Specified file: " + filePath.toString() + " doesn't exist.");
-				return outputResource;
-			}
+			FileDecoder fs(filePath);
+			savedResourceData = std::static_pointer_cast<SavedResourceData>(fs.decode());
 		}
 
-		// Load saved resource data
-		FileDecoder fs(filePath);
-		SPtr<SavedResourceData> savedResourceData = std::static_pointer_cast<SavedResourceData>(fs.decode());
-
-		// If already loading keep the old load operation active, 
-		// otherwise create a new one
+		// If already loading keep the old load operation active, otherwise create a new one
 		if (!alreadyLoading)
 		{
-			BS_LOCK_MUTEX(mInProgressResourcesMutex);
+			{
+				BS_LOCK_MUTEX(mInProgressResourcesMutex);
 
-			ResourceLoadData* loadData = bs_new<ResourceLoadData>(outputResource, 0);
-			mInProgressResources[uuid] = loadData;
-			loadData->resource = outputResource;
-			loadData->remainingDependencies = 1;
-			loadData->notifyImmediately = synchronous; // Make resource listener trigger before exit if loading synchronously
+				ResourceLoadData* loadData = bs_new<ResourceLoadData>(outputResource, 0);
+				mInProgressResources[UUID] = loadData;
+				loadData->resource = outputResource;
+				loadData->remainingDependencies = 1;
+				loadData->notifyImmediately = synchronous; // Make resource listener trigger before exit if loading synchronously
 
-			if (loadDependencies)
-			{
-				for (auto& dependency : savedResourceData->getDependencies())
+				// Register dependencies and count them so we know when the resource is fully loaded
+				if (loadDependencies && savedResourceData != nullptr)
 				{
-					if (dependency != uuid)
+					for (auto& dependency : savedResourceData->getDependencies())
 					{
-						mDependantLoads[dependency].push_back(loadData);
-						loadData->remainingDependencies++;
+						if (dependency != UUID)
+						{
+							mDependantLoads[dependency].push_back(loadData);
+							loadData->remainingDependencies++;
+						}
 					}
 				}
 			}
-		}
 
-		// Load dependencies
-		if (loadDependencies)
-		{
+			if (loadDependencies && savedResourceData != nullptr)
 			{
 				for (auto& dependency : savedResourceData->getDependencies())
 				{
@@ -220,14 +183,15 @@ namespace BansheeEngine
 			}
 		}
 
-		// Actually queue the load
-		if (!alreadyLoading)
+		// Actually start the file read operation if not already loaded or in progress
+		if (!alreadyLoading && !filePath.isEmpty())
 		{
+			// Synchronous or the resource doesn't support async, read the file immediately
 			if (synchronous || !savedResourceData->allowAsyncLoading())
 			{
 				loadCallback(filePath, outputResource);
 			}
-			else
+			else // Asynchronous, read the file on a worker thread
 			{
 				String fileName = filePath.getFilename();
 				String taskName = "Resource load: " + fileName;
@@ -236,6 +200,23 @@ namespace BansheeEngine
 				TaskScheduler::instance().addTask(task);
 			}
 		}
+		else // File already loaded or in progress
+		{
+			// Complete the load unless its in progress in which case we wait for its worker thread to complete it.
+			// In case file is already loaded this will only decrement dependency count in case this resource is a dependency.
+			if (!loadInProgress)
+				loadComplete(outputResource);
+			else
+			{
+				// In case loading finished in the meantime we cannot be sure at what point ::loadComplete was triggered,
+				// so trigger it manually so that the dependency count is properly decremented in case this resource
+				// is a dependency.
+				BS_LOCK_MUTEX(mLoadedResourceMutex);
+				auto iterFind = mLoadedResources.find(UUID);
+				if (iterFind != mLoadedResources.end())
+					loadComplete(outputResource);
+			}
+		}
 
 		return outputResource;
 	}

+ 2 - 1
BansheeEditor/Include/BsBuiltinEditorResources.h

@@ -12,7 +12,7 @@ namespace BansheeEngine
 	 */
 	enum class ProjectIcon
 	{
-		Folder, Mesh, Font, Texture, PlainText, ScriptCode, SpriteTexture, Shader, ShaderInclude, Material, Prefab
+		Folder, Mesh, Font, Texture, PlainText, ScriptCode, SpriteTexture, Shader, ShaderInclude, Material, Prefab, GUISkin
 	};
 
 	/**
@@ -282,6 +282,7 @@ namespace BansheeEngine
 		static const WString MaterialIconTex;
 		static const WString SpriteTextureIconTex;
 		static const WString PrefabIconTex;
+		static const WString GUISkinIconTex;
 
 		static const WString LogInfoIconTex;
 		static const WString LogWarningIconTex;

+ 0 - 17
BansheeEditor/Include/BsGUIMenuBar.h

@@ -206,16 +206,6 @@ namespace BansheeEngine
 		 */
 		void onSubMenuClosed();
 
-		/**
-		 * @brief	Triggered when the user enters the area of the menu bar.
-		 */
-		void onMenuBarHover();
-
-		/**
-		 * @brief	Triggered when the user leaves the area of the menu bar.
-		 */
-		void onMenuBarOut();
-
 		/**
 		 * @brief	Triggered when the minimize button is clicked.
 		 *			Minimizes the attached window.
@@ -234,11 +224,6 @@ namespace BansheeEngine
 		 */
 		void onCloseClicked();
 
-		/**
-		 * @brief	Changes the look for the menu bar depending whether it's being interacted with or not.
-		 */
-		void setActiveState(bool active);
-
 		/**
 		 * @brief	Refreshes the OS client area that allow the window to be dragged
 		 *			by dragging the empty areas on the menu bar. Should be called when top
@@ -251,7 +236,6 @@ namespace BansheeEngine
 
 		RenderWindow* mParentWindow;
 		CGUIWidget* mParentWidget;
-		GUIPanel* mOverlayPanel;
 		GUIPanel* mMainPanel;
 		GUIPanel* mBgPanel;
 		GUILayout* mMenuItemLayout;
@@ -259,7 +243,6 @@ namespace BansheeEngine
 		GUITexture* mBgTexture;
 		GUITexture* mLogoTexture;
 		GUITexture* mSplitterLine;
-		GUIHoverHitBox* mHoverHitBox;
 
 		GUIButton* mMinBtn;
 		GUIButton* mMaxBtn;

+ 5 - 2
BansheeEditor/Source/BsBuiltinEditorResources.cpp

@@ -99,6 +99,7 @@ namespace BansheeEngine
 	const WString BuiltinEditorResources::MaterialIconTex = L"MaterialIcon.psd";
 	const WString BuiltinEditorResources::SpriteTextureIconTex = L"SpriteIcon.psd";
 	const WString BuiltinEditorResources::PrefabIconTex = L"PrefabIcon.psd";
+	const WString BuiltinEditorResources::GUISkinIconTex = L"GUISkinIcon.psd";
 
 	const WString BuiltinEditorResources::LogInfoIconTex = L"IconInfo.psd";
 	const WString BuiltinEditorResources::LogWarningIconTex = L"IconWarning.psd";
@@ -234,8 +235,8 @@ namespace BansheeEngine
 	const WString BuiltinEditorResources::MenuBarLineActiveTex = L"MenuBarLineActive.png";
 
 	const WString BuiltinEditorResources::ToolBarBtnNormalTex = L"ToolBarButtonNormal.png";
-	const WString BuiltinEditorResources::ToolBarBtnHoverTex = L"ToolBarButtonNormal.png";
-	const WString BuiltinEditorResources::ToolBarBtnActiveTex = L"ToolBarButtonNormal.png";
+	const WString BuiltinEditorResources::ToolBarBtnHoverTex = L"ToolBarButtonHover.png";
+	const WString BuiltinEditorResources::ToolBarBtnActiveTex = L"ToolBarButtonActive.png";
 
 	const WString BuiltinEditorResources::ToolBarSeparatorTex = L"ToolBarSeparator.png";
 
@@ -1898,6 +1899,8 @@ namespace BansheeEngine
 			return getGUIIcon(SpriteTextureIconTex);
 		case ProjectIcon::Prefab:
 			return getGUIIcon(PrefabIconTex);
+		case ProjectIcon::GUISkin:
+			return getGUIIcon(GUISkinIconTex);
 		}
 
 		return HSpriteTexture();

+ 0 - 37
BansheeEditor/Source/BsGUIMenuBar.cpp

@@ -61,10 +61,6 @@ namespace BansheeEngine
 		:mParentWidget(parent), mParentWindow(parentWindow), mMainPanel(nullptr), mMenuItemLayout(nullptr),
 		mBgTexture(nullptr), mLogoTexture(nullptr), mSubMenuOpen(false), mSubMenuButton(nullptr), mBgPanel(nullptr)
 	{
-		mOverlayPanel = parent->getPanel()->addNewElement<GUIPanel>(std::numeric_limits<INT16>::min() + 10);
-		mOverlayPanel->setWidth(1);
-		mOverlayPanel->setHeight(50);
-
 		mMainPanel = parent->getPanel()->addNewElement<GUIPanel>(std::numeric_limits<INT16>::min() + 15);
 		mMainPanel->setWidth(1);
 		mMainPanel->setHeight(50);
@@ -110,12 +106,6 @@ namespace BansheeEngine
 		mMaxBtn->onClick.connect(std::bind(&GUIMenuBar::onMaximizeClicked, this));
 		mCloseBtn->onClick.connect(std::bind(&GUIMenuBar::onCloseClicked, this));
 
-		mHoverHitBox = GUIHoverHitBox::create();
-		mOverlayPanel->addElement(mHoverHitBox);
-
-		mHoverHitBox->onHover.connect(std::bind(&GUIMenuBar::onMenuBarHover, this));
-		mHoverHitBox->onOut.connect(std::bind(&GUIMenuBar::onMenuBarOut, this));
-
 		refreshNonClientAreas();
 	}
 
@@ -509,27 +499,12 @@ namespace BansheeEngine
 			if(mSubMenuButton != subMenu->button)
 				openSubMenu(name);
 		}
-
-		setActiveState(true);
 	}
 
 	void GUIMenuBar::onSubMenuClosed()
 	{
 		mSubMenuButton->_setOn(false);
 		mSubMenuOpen = false;
-
-		setActiveState(false);
-	}
-
-	void GUIMenuBar::onMenuBarHover()
-	{
-		setActiveState(true);
-	}
-
-	void GUIMenuBar::onMenuBarOut()
-	{
-		if (!mSubMenuOpen)
-			setActiveState(false);
 	}
 
 	void GUIMenuBar::onMinimizeClicked()
@@ -550,16 +525,6 @@ namespace BansheeEngine
 		gCoreApplication().stopMainLoop();
 	}
 
-	void GUIMenuBar::setActiveState(bool active)
-	{
-		const GUIElementStyle* style = mParentWidget->getSkin().getStyle(getLineStyleType());
-
-		if (active)
-			mSplitterLine->setTexture(style->normalOn.texture);
-		else
-			mSplitterLine->setTexture(style->normal.texture);
-	}
-
 	void GUIMenuBar::refreshNonClientAreas()
 	{
 		Rect2I mainArea = mMenuItemLayout->getBounds();
@@ -584,7 +549,5 @@ namespace BansheeEngine
 
 		Rect2I menuBarBounds = mMenuItemLayout->getBounds();
 		menuBarBounds.width = menuWidth;
-
-		mHoverHitBox->setBounds(menuBarBounds);
 	}
 }

+ 6 - 0
MBansheeEditor/EditorBuiltin.cs

@@ -75,6 +75,9 @@ namespace BansheeEditor
         /// <summary>Icon used for displaying prefab resources in the library window.</summary>
         public static SpriteTexture PrefabIcon { get { return Internal_GetPrefabIcon(); } }
 
+        /// <summary>Icon used for displaying GUI skin resources in the library window.</summary>
+        public static SpriteTexture GUISkinIcon { get { return Internal_GetGUISkinIcon(); } }
+
         public static SpriteTexture XBtnIcon { get { return Internal_GetXBtnIcon(); } }
 
         /// <summary>Returns text contained in the default "empty" shader.</summary>
@@ -157,6 +160,9 @@ namespace BansheeEditor
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern SpriteTexture Internal_GetPrefabIcon();
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern SpriteTexture Internal_GetGUISkinIcon();
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern SpriteTexture Internal_GetXBtnIcon();
 

+ 2 - 0
MBansheeEditor/Library/LibraryGUIEntry.cs

@@ -329,6 +329,8 @@ namespace BansheeEditor
                         return EditorBuiltin.MaterialIcon;
                     case ResourceType.Prefab:
                         return EditorBuiltin.PrefabIcon;
+                    case ResourceType.GUISkin:
+                        return EditorBuiltin.GUISkinIcon;
                 }
             }
 

+ 1 - 0
SBansheeEditor/Include/BsScriptEditorBuiltin.h

@@ -30,6 +30,7 @@ namespace BansheeEngine
 		static MonoObject* internal_getShaderIncludeIcon();
 		static MonoObject* internal_getMaterialIcon();
 		static MonoObject* internal_getSpriteTextureIcon();
+		static MonoObject* internal_getGUISkinIcon();
 		static MonoObject* internal_getPrefabIcon();
 		static MonoObject* internal_getXBtnIcon();
 

+ 9 - 1
SBansheeEditor/Source/BsScriptEditorBuiltin.cpp

@@ -24,6 +24,7 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_GetShaderIncludeIcon", &ScriptEditorBuiltin::internal_getShaderIncludeIcon);
 		metaData.scriptClass->addInternalCall("Internal_GetMaterialIcon", &ScriptEditorBuiltin::internal_getMaterialIcon);
 		metaData.scriptClass->addInternalCall("Internal_GetSpriteTextureIcon", &ScriptEditorBuiltin::internal_getSpriteTextureIcon);
+		metaData.scriptClass->addInternalCall("Internal_GetGUISkinIcon", &ScriptEditorBuiltin::internal_getGUISkinIcon);
 		metaData.scriptClass->addInternalCall("Internal_GetPrefabIcon", &ScriptEditorBuiltin::internal_getPrefabIcon);
 		metaData.scriptClass->addInternalCall("Internal_GetXBtnIcon", &ScriptEditorBuiltin::internal_getXBtnIcon);
 		metaData.scriptClass->addInternalCall("Internal_GetEmptyShaderCode", &ScriptEditorBuiltin::internal_GetEmptyShaderCode);
@@ -99,7 +100,14 @@ namespace BansheeEngine
 
 	MonoObject* ScriptEditorBuiltin::internal_getSpriteTextureIcon()
 	{
-		HSpriteTexture tex = BuiltinEditorResources::instance().getLibraryIcon(ProjectIcon::ScriptCode);
+		HSpriteTexture tex = BuiltinEditorResources::instance().getLibraryIcon(ProjectIcon::SpriteTexture);
+
+		return ScriptSpriteTexture::toManaged(tex);
+	}
+
+	MonoObject* ScriptEditorBuiltin::internal_getGUISkinIcon()
+	{
+		HSpriteTexture tex = BuiltinEditorResources::instance().getLibraryIcon(ProjectIcon::GUISkin);
 
 		return ScriptSpriteTexture::toManaged(tex);
 	}