diff --git a/AutomatedTesting/Gem/Code/Platform/Mac/runtime_dependencies.cmake b/AutomatedTesting/Gem/Code/Platform/Mac/runtime_dependencies.cmake index 4d5680a30d..f9d1e60dda 100644 --- a/AutomatedTesting/Gem/Code/Platform/Mac/runtime_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/Platform/Mac/runtime_dependencies.cmake @@ -8,3 +8,8 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # + +set(GEM_DEPENDENCIES + Gem::Atom_RHI_Metal.Private + Gem::Atom_RHI_Null.Private +) \ No newline at end of file diff --git a/AutomatedTesting/Gem/Code/Platform/Mac/tool_dependencies.cmake b/AutomatedTesting/Gem/Code/Platform/Mac/tool_dependencies.cmake index 4d5680a30d..ee7be9ac6d 100644 --- a/AutomatedTesting/Gem/Code/Platform/Mac/tool_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/Platform/Mac/tool_dependencies.cmake @@ -8,3 +8,10 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # + +set(GEM_DEPENDENCIES + Gem::Atom_RHI_Null.Private + Gem::Atom_RHI_Null.Builders + Gem::Atom_RHI_Metal.Private + Gem::Atom_RHI_Metal.Builders +) \ No newline at end of file diff --git a/Code/CryEngine/CMakeLists.txt b/Code/CryEngine/CMakeLists.txt index 38fcbf4a27..96f6427268 100644 --- a/Code/CryEngine/CMakeLists.txt +++ b/Code/CryEngine/CMakeLists.txt @@ -10,5 +10,4 @@ # add_subdirectory(CryCommon) -add_subdirectory(CryFont) add_subdirectory(CrySystem) diff --git a/Code/CryEngine/CryCommon/CryFontBus.h b/Code/CryEngine/CryCommon/CryFontBus.h deleted file mode 100644 index 9922193f42..0000000000 --- a/Code/CryEngine/CryCommon/CryFontBus.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - */ - -#pragma once - -#include - -#include - -namespace AZ -{ - /*! - * Signal LY to create an ICryFont - */ - class CryFontCreationRequests - : public AZ::EBusTraits - { - public: - using MutexType = AZStd::recursive_mutex; - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - - virtual bool CreateCryFont([[maybe_unused]] SSystemGlobalEnvironment& env, [[maybe_unused]] const SSystemInitParams& initParams) {return false;} //! return false to fall back to default CryFont initialization - }; - using CryFontCreationRequestBus = AZ::EBus; - -} diff --git a/Code/CryEngine/CryFont/CryFont.cpp b/Code/CryEngine/CryFont/CryFont.cpp deleted file mode 100644 index ab39a0fa4d..0000000000 --- a/Code/CryEngine/CryFont/CryFont.cpp +++ /dev/null @@ -1,845 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : CCryFont class. - - -#include "CryFont_precompiled.h" - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "CryFont.h" -#include "CryPath.h" -#include "FFont.h" -#include "FontTexture.h" -#include "FontRenderer.h" -#include "ILocalizationManager.h" - -#include -#include - -// Static member definitions -const Vec2i CCryFont::defaultGlyphSize = Vec2i(ICryFont::defaultGlyphSizeX, ICryFont::defaultGlyphSizeY); - -#if !defined(_RELEASE) -static void DumpFontTexture(IConsoleCmdArgs* pArgs) -{ - if (pArgs->GetArgCount() != 2) - { - return; - } - - const char* pFontName = pArgs->GetArg(1); - - if (pFontName && *pFontName && *pFontName != '0') - { - string fontFile("@devroot@/"); - fontFile += pFontName; - fontFile += ".bmp"; - - CFFont* pFont = (CFFont*) gEnv->pCryFont->GetFont(pFontName); - if (pFont) - { - pFont->GetFontTexture()->WriteToFile(fontFile.c_str()); - gEnv->pLog->LogWithType(IMiniLog::eInputResponse, "Dumped \"%s\" texture to \"%s\"!", pFontName, fontFile.c_str()); - } - } -} - -static void DumpFontNames([[maybe_unused]] IConsoleCmdArgs* pArgs) -{ - string names = gEnv->pCryFont->GetLoadedFontNames(); - gEnv->pLog->LogWithType(IMiniLog::eInputResponse, "Currently loaded fonts: %s", names.c_str()); -} - -static void ReloadFonts([[maybe_unused]] IConsoleCmdArgs* pArgs) -{ - gEnv->pCryFont->ReloadAllFonts(); -} -#endif - -namespace -{ - //! Stores paths to styled font assets for a given set of languages - //! This struct stores the XML data contained within the tag of - //! an enclosing definition: - //! - //! - //! - //! - //! - //! - //! - //! - //! - struct FontTagXml - { - //! \return True if all font asset paths are non-empty, false otherwise - bool IsValid() const - { - // Note that "lang" can be empty - return !m_fontFilename.empty() - && !m_boldFontFilename.empty() - && !m_italicFontFilename.empty() - && !m_boldItalicFontFilename.empty(); - } - - string m_lang; //!< Stores a comma-separated list of languages this collection of fonts applies to. - //!< If this is an empty string, it implies that these set of fonts will be applied - //!< by default (when a language is being used but no fonts in the font family are - //!< mapped to that language). - - string m_fontFilename; //!< Font used when no styling is applied. - string m_boldFontFilename; //!< Bold-styled font - string m_italicFontFilename; //!< Italic-styled font - string m_boldItalicFontFilename; //!< Bold-italic-styled font - }; - - //! Stores parsed font family XML data. - //! This struct contains the name of the font family and a list of font - //! file XML data for all the language-specific mappings of this - //! font family. - //! - //! Example XML: - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - struct FontFamilyTagXml - { - //! Returns true if all font file fields were parsed, false otherwise. - bool IsValid() const - { - for (const FontTagXml& fontTagXml : m_fontTagsXml) - { - if (!fontTagXml.IsValid()) - { - return false; - } - } - - // Every font family must have a name - return !m_fontFamilyName.empty(); - } - - string m_fontFamilyName; //!< Value of the "name" font-family tag attribute - AZStd::list m_fontTagsXml; //!< List of child tag data. - }; - - //! Returns true if the XML tree was traversed successfully, false otherwise. - //! - //! Note that, if this function returns true, it simply means that there were - //! no unexpected structure issues with the given XML tree, it doesn't - //! necessarily mean that all the required fields were parsed. - bool ParseFontFamilyXml(const XmlNodeRef& node, FontFamilyTagXml& xmlData) - { - if (!node) - { - return false; - } - - // - if (AZStd::string(node->getTag()) == "fontfamily") - { - const int numAttributes = node->getNumAttributes(); - - if (numAttributes <= 0) - { - // Expecting at least one attribute - return false; - } - - string name; - - for (int i = 0, count = node->getNumAttributes(); i < count; ++i) - { - const char* key = ""; - const char* value = ""; - if (node->getAttributeByIndex(i, &key, &value)) - { - if (string(key) == "name") - { - name = value; - } - else - { - // Unexpected font tag attribute - return false; - } - } - } - - name.Trim(); - if (!name.empty()) - { - xmlData.m_fontFamilyName = name; - } - else - { - // Font family must have a name - return false; - } - } - - // - if (AZStd::string(node->getTag()) == "font") - { - xmlData.m_fontTagsXml.push_back(FontTagXml()); - - string lang; - for (int i = 0, count = node->getNumAttributes(); i < count; ++i) - { - const char* key = ""; - const char* value = ""; - if (node->getAttributeByIndex(i, &key, &value)) - { - if (string(key) == "lang") - { - lang = value; - } - else - { - // Unexpected font tag attribute - return false; - } - } - } - - lang.Trim(); - if (!lang.empty()) - { - xmlData.m_fontTagsXml.back().m_lang = lang; - } - } - - // - else if (AZStd::string(node->getTag()) == "file") - { - const int numAttributes = node->getNumAttributes(); - - if (numAttributes <= 0) - { - // Expecting at least one attribute - return false; - } - - string path; - string tags; - - for (int i = 0, count = node->getNumAttributes(); i < count; ++i) - { - const char* key = ""; - const char* value = ""; - if (node->getAttributeByIndex(i, &key, &value)) - { - if (string(key) == "path") - { - path = value; - } - else if (string(key) == "tags") - { - tags = value; - } - else - { - // Unexpected font tag attribute - return false; - } - } - } - - tags.Trim(); - if (tags.empty()) - { - xmlData.m_fontTagsXml.back().m_fontFilename = path; - } - else if (tags == "b") - { - xmlData.m_fontTagsXml.back().m_boldFontFilename = path; - } - else if (tags == "i") - { - xmlData.m_fontTagsXml.back().m_italicFontFilename = path; - } - else - { - // We'll just assume any other tag indicates bold italic - xmlData.m_fontTagsXml.back().m_boldItalicFontFilename = path; - } - } - - for (int i = 0, count = node->getChildCount(); i < count; ++i) - { - XmlNodeRef child = node->getChild(i); - if (!ParseFontFamilyXml(child, xmlData)) - { - return false; - } - } - - return true; - } - - //! Only attempt XML file load if file exists. - //! There are use-cases where the XML path is not fully known (such as - //! when referencing font family names from font family XML files), and - //! attempting to load the XML files directly via ISystem() methods can - //! produce a lot of warning noise. - XmlNodeRef SafeLoadXmlFromFile(const string& xmlPath) - { - if (gEnv->pCryPak->IsFileExist(xmlPath.c_str())) - { - return GetISystem()->LoadXmlFromFile(xmlPath.c_str()); - } - - return XmlNodeRef(); - } - -} - -CCryFont::CCryFont(ISystem* pSystem) - : m_pSystem(pSystem) - , m_fonts() - , m_rndPropIsRGBA(false) - , m_rndPropHalfTexelOffset(0.5f) -{ - assert(m_pSystem); - - CryLogAlways("Using FreeType %d.%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH); - - // Persist fonts for application lifetime to prevent unnecessary work - REGISTER_CVAR(r_persistFontFamilies, r_persistFontFamilies, VF_NULL, "Persist loaded font families for lifetime of application."); - -#if !defined(_RELEASE) - REGISTER_COMMAND("r_DumpFontTexture", DumpFontTexture, 0, - "Dumps the specified font's texture to a bitmap file\n" - "Use r_DumpFontTexture to get the loaded font names\n" - "Usage: r_DumpFontTexture "); - REGISTER_COMMAND("r_DumpFontNames", DumpFontNames, 0, - "Logs a list of fonts currently loaded"); - REGISTER_COMMAND("r_ReloadFonts", ReloadFonts, VF_NULL, - "Reload all fonts"); -#endif -} - -CCryFont::~CCryFont() -{ - // Persist fonts for application lifetime to prevent unnecessary work - m_persistedFontFamilies.clear(); - - for (FontMapItor it = m_fonts.begin(), itEnd = m_fonts.end(); it != itEnd; ) - { - CFFont* pFont = it->second; - ++it; // iterate as Release() below will remove font from the map - SAFE_RELEASE(pFont); - } -} - -void CCryFont::Release() -{ - delete this; -} - -IFFont* CCryFont::NewFont(const char* pFontName) -{ - string name = pFontName; - name.MakeLower(); - - FontMapItor it = m_fonts.find(CONST_TEMP_STRING(name.c_str())); - if (it != m_fonts.end()) - { - return it->second; - } - - CFFont* pFont = new CFFont(m_pSystem, this, name.c_str()); - m_fonts.insert(FontMapItor::value_type(name, pFont)); - return pFont; -} - -IFFont* CCryFont::GetFont(const char* pFontName) const -{ - FontMapConstItor it = m_fonts.find(CONST_TEMP_STRING(string(pFontName).MakeLower())); - return it != m_fonts.end() ? it->second : 0; -} - -FontFamilyPtr CCryFont::LoadFontFamily(const char* pFontFamilyName) -{ - FontFamilyPtr fontFamily(nullptr); - string fontFamilyPath; - string fontFamilyFullPath; - - XmlNodeRef root = LoadFontFamilyXml(pFontFamilyName, fontFamilyPath, fontFamilyFullPath); - - if (root) - { - FontFamilyTagXml xmlData; - const bool parseSuccess = ParseFontFamilyXml(root, xmlData); - if (parseSuccess && xmlData.IsValid()) - { - const char* currentLanguage = gEnv->pSystem->GetLocalizationManager()->GetLanguage(); - FontTagXml* defaultFont = nullptr; - FontTagXml* langSpecificFont = nullptr; - - // Note that we don't break out of this for-loop early because we - // want to find both the default font family and the - // language-specific font family. We prefer the lang-specific - // family but will fall back on the default if it doesn't exist. - for (FontTagXml& fontTagXml : xmlData.m_fontTagsXml) - { - if (fontTagXml.m_lang.empty()) - { - defaultFont = &fontTagXml; - } - else - { - int searchPos = 0; - string langToken; - - // "lang" font-tag attribute could be comma-separated - while (!(langToken = fontTagXml.m_lang.Tokenize(",", searchPos)).empty()) - { - if (langToken.Trim() == currentLanguage) - { - langSpecificFont = &fontTagXml; - break; - } - } - } - } - - if (langSpecificFont || defaultFont) - { - // Prefer lang-specific font-family over default, if it exists - FontTagXml* fontTagXml = langSpecificFont ? langSpecificFont : defaultFont; - - // Pre-pend font family's path to make font family XML paths - // relative to font family file - fontTagXml->m_fontFilename = fontFamilyPath + fontTagXml->m_fontFilename; - fontTagXml->m_boldFontFilename = fontFamilyPath + fontTagXml->m_boldFontFilename; - fontTagXml->m_italicFontFilename = fontFamilyPath + fontTagXml->m_italicFontFilename; - fontTagXml->m_boldItalicFontFilename = fontFamilyPath + fontTagXml->m_boldItalicFontFilename; - - IFFont* normal = LoadFont(fontTagXml->m_fontFilename.c_str()); - IFFont* bold = LoadFont(fontTagXml->m_boldFontFilename.c_str()); - IFFont* italic = LoadFont(fontTagXml->m_italicFontFilename.c_str()); - IFFont* boldItalic = LoadFont(fontTagXml->m_boldItalicFontFilename.c_str()); - - // Only continue if all fonts were created successfully - if (normal && bold && italic && boldItalic) - { - fontFamily.reset(new FontFamily(), - [this](FontFamily* pFontFamily) - { - ReleaseFontFamily(pFontFamily); - }); - - // Map the font family name both by path and by name defined - // within the Font Family XML itself. This allows font - // families to also be referenced simply by name. - if (!AddFontFamilyToMaps(fontFamilyFullPath, xmlData.m_fontFamilyName, fontFamily)) - { - SAFE_RELEASE(normal); - SAFE_RELEASE(bold); - SAFE_RELEASE(italic); - SAFE_RELEASE(boldItalic); - - return nullptr; - } - - fontFamily->familyName = xmlData.m_fontFamilyName; - fontFamily->normal = normal; - fontFamily->bold = bold; - fontFamily->italic = italic; - fontFamily->boldItalic = boldItalic; - } - else - { - SAFE_RELEASE(normal); - SAFE_RELEASE(bold); - SAFE_RELEASE(italic); - SAFE_RELEASE(boldItalic); - } - } - } - } - - if (!fontFamily) - { - // Unable to load font family XML, so load font normally and associate - // it with a font family - IFFont* pFont = LoadFont(pFontFamilyName); - - if (pFont) - { - // Create a font family from a single font by assigning all the - // font family stylings to the same font - fontFamily.reset(new FontFamily(), - [this](FontFamily* pFontFamily) - { - ReleaseFontFamily(pFontFamily); - }); - - // Use filepath as familyName so font loading/unloading doesn't break with duplicate file names - fontFamily->familyName = pFontFamilyName; - - if (!AddFontFamilyToMaps(pFontFamilyName, fontFamily->familyName, fontFamily)) - { - SAFE_RELEASE(pFont); - - return nullptr; - } - - // Assign all stylings to the same font - fontFamily->normal = pFont; - fontFamily->bold = pFont; - fontFamily->italic = pFont; - fontFamily->boldItalic = pFont; - - // The other three stylings need to have their ref count - // incremented (even though in this particular case its all the - // same font) because when ReleaseFontFamily executes all fonts - // in the family will be (corresondingly) Release'd. - fontFamily->bold->AddRef(); - fontFamily->italic->AddRef(); - fontFamily->boldItalic->AddRef(); - } - } - - // Persist fonts for application lifetime to prevent unnecessary work - if (r_persistFontFamilies > 0) - { - m_persistedFontFamilies.emplace_back(FontFamilyPtr(fontFamily)); - } - - return fontFamily; -} - -FontFamilyPtr CCryFont::GetFontFamily(const char* pFontFamilyName) -{ - FontFamilyPtr fontFamily = nullptr; - - // The given string could either be: a font family name (defined in font - // family XML), a file path (for regular fonts mapped as font families), - // or just the filename of a font itself. Fonts are mapped by font family - // name or by filepath, so attempt lookup using the map first since it's - // the fastest. - string loweredName = string(pFontFamilyName).Trim().MakeLower(); - auto it = m_fontFamilies.find(PathUtil::MakeGamePath(loweredName).c_str()); - if (it != m_fontFamilies.end()) - { - fontFamily = FontFamilyPtr(it->second); - } - else - { - // Iterate through all fonts, returning the first match where simply - // the filename of a font could be a match. This case will likely be - // hit when text markup references a font that doesn't belong to a - // font family. - for (const auto& fontFamilyIter : m_fontFamilies) - { - const AZStd::string& mappedFontFamilyName = fontFamilyIter.first; - string mappedFilenameNoExtension = PathUtil::GetFileName(mappedFontFamilyName.c_str()); - - string searchStringFilenameNoExtension = PathUtil::GetFileName(loweredName); - - if (mappedFilenameNoExtension == searchStringFilenameNoExtension) - { - fontFamily = FontFamilyPtr(fontFamilyIter.second); - break; - } - } - } - - return fontFamily; -} - -void CCryFont::AddCharsToFontTextures(FontFamilyPtr pFontFamily, const char* pChars, int glyphSizeX, int glyphSizeY) -{ - pFontFamily->normal->AddCharsToFontTexture(pChars, glyphSizeX, glyphSizeY); - pFontFamily->bold->AddCharsToFontTexture(pChars, glyphSizeX, glyphSizeY); - pFontFamily->italic->AddCharsToFontTexture(pChars, glyphSizeX, glyphSizeY); - pFontFamily->boldItalic->AddCharsToFontTexture(pChars, glyphSizeX, glyphSizeY); -} - -void CCryFont::SetRendererProperties(IRenderer* pRenderer) -{ - if (pRenderer) - { - m_rndPropIsRGBA = (pRenderer->GetFeatures() & RFT_RGBA) != 0; - m_rndPropHalfTexelOffset = 0.0f; - } -} - -void CCryFont::GetMemoryUsage(ICrySizer* pSizer) const -{ - if (!pSizer->Add(*this)) - { - return; - } - - pSizer->AddObject(m_fonts); -} - -string CCryFont::GetLoadedFontNames() const -{ - string ret; - for (FontMapConstItor it = m_fonts.begin(), itEnd = m_fonts.end(); it != itEnd; ++it) - { - CFFont* pFont = it->second; - if (pFont) - { - if (!ret.empty()) - { - ret += ","; - } - ret += pFont->GetName(); - } - } - return ret; -} - -void CCryFont::OnLanguageChanged() -{ - ReloadAllFonts(); - - EBUS_EVENT(LanguageChangeNotificationBus, LanguageChanged); -} - -void CCryFont::ReloadAllFonts() -{ - // Persist fonts for application lifetime to prevent unnecessary work - m_persistedFontFamilies.clear(); - - AZStd::list fontFamilyFilenames; - AZStd::list fontFamilyWeakPtrs; - - // Iterate through all currently loaded font families - for (auto it : m_fontFamilyReverseLookup) - { - fontFamilyWeakPtrs.push_back(it.first); - fontFamilyFilenames.push_back(it.second->first); - } - - // Release font-family resources and unmap them - for (auto fontFamily : fontFamilyWeakPtrs) - { - ReleaseFontFamily(fontFamily); - } - - // Reload the font families - for (auto familyFilename : fontFamilyFilenames) - { - LoadFontFamily(familyFilename.c_str()); - } - - // All UI text components need to reload their font assets (both in-game - // and in-editor). - EBUS_EVENT(FontNotificationBus, OnFontsReloaded); -} - -void CCryFont::UnregisterFont(const char* pFontName) -{ - FontMapItor it = m_fonts.find(CONST_TEMP_STRING(pFontName)); - -#if defined(AZ_ENABLE_TRACING) - IFFont* fontPtr = it->second; -#endif - - if (it != m_fonts.end()) - { - m_fonts.erase(it); - } - -#if defined(AZ_ENABLE_TRACING) - // Make sure the font being released isn't currently in use by a font family. - // If it is, the FontFamily will have a dangling pointer and will cause a - // crash when the FontFamily eventually gets released. - for (auto reverseMapEntry : m_fontFamilyReverseLookup) - { - FontFamily* fontFamily = reverseMapEntry.first; - AZ_Assert(fontFamily->normal != fontPtr, - "The following font is being freed but still in use by a FontFamily: %s", - pFontName); - AZ_Assert(fontFamily->italic != fontPtr, - "The following font is being freed but still in use by a FontFamily: %s", - pFontName); - AZ_Assert(fontFamily->bold != fontPtr, - "The following font is being freed but still in use by a FontFamily: %s", - pFontName); - AZ_Assert(fontFamily->boldItalic != fontPtr, - "The following font is being freed but still in use by a FontFamily: %s", - pFontName); - } -#endif -} - -IFFont* CCryFont::LoadFont(const char* pFontName) -{ - string fontName = pFontName; - fontName.MakeLower(); - - IFFont* font = GetFont(fontName); - if (font) - { - font->AddRef(); // use existing loaded font - } - else - { - // attempt to create and load a new font, use the font pathname as the font name - font = NewFont(fontName); - if (!font) - { - string errorMsg = "Error creating a new font named "; - errorMsg += fontName; - errorMsg += "."; - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, errorMsg.c_str()); - } - else - { - // creating font adds one to its refcount so no need for AddRef here - if (!font->Load(fontName)) - { - string errorMsg = "Error loading a font from "; - errorMsg += fontName; - errorMsg += "."; - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, errorMsg); - font->Release(); - font = nullptr; - } - } - } - - return font; -} - -void CCryFont::ReleaseFontFamily(FontFamily* pFontFamily) -{ - // Ensure that Font Family was mapped prior to destruction - const bool isMapped = m_fontFamilyReverseLookup.find(pFontFamily) != m_fontFamilyReverseLookup.end(); - if (!isMapped) - { - return; - } - - // Note that the FontFamily is mapped both by filename and by "family name" - auto it = m_fontFamilyReverseLookup[pFontFamily]; - m_fontFamilies.erase(it); - string familyName(pFontFamily->familyName); - m_fontFamilies.erase(familyName.MakeLower().c_str()); - - // Reverse lookup is used to avoid needing to store filename path with - // the font family, so we need to remove that entry also. - m_fontFamilyReverseLookup.erase(pFontFamily); - - SAFE_RELEASE(pFontFamily->normal); - SAFE_RELEASE(pFontFamily->bold); - SAFE_RELEASE(pFontFamily->italic); - SAFE_RELEASE(pFontFamily->boldItalic); -} - -bool CCryFont::AddFontFamilyToMaps(const char* pFontFamilyFilename, const char* pFontFamilyName, FontFamilyPtr fontFamily) -{ - if (!pFontFamilyFilename || !pFontFamilyName || !fontFamily.get()) - { - return false; - } - - // We don't support "updating" mapped values. - AZStd::string loweredFilename(PathUtil::MakeGamePath(string(pFontFamilyFilename)).c_str()); - AZStd::to_lower(loweredFilename.begin(), loweredFilename.end()); - if (m_fontFamilies.find(loweredFilename) != m_fontFamilies.end()) - { - string warnMsg; - warnMsg.Format("Couldn't load Font Family '%s': already loaded", pFontFamilyFilename); - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, warnMsg.c_str()); - return false; - } - - // Similarly, we don't support Font Family XMLs that have the same font - // family name (we assume all Font Family names are unique). - AZStd::string loweredFontFamilyName(pFontFamilyName); - AZStd::to_lower(loweredFontFamilyName.begin(), loweredFontFamilyName.end()); - if (m_fontFamilies.find(loweredFontFamilyName) != m_fontFamilies.end()) - { - string warnMsg; - warnMsg.Format("Couldn't load Font Family '%s': already loaded", pFontFamilyName); - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, warnMsg.c_str()); - return false; - } - - // First, insert by filename - AZStd::pair> insertPair(loweredFilename, fontFamily); - auto iterPosition = m_fontFamilies.insert(insertPair).first; - m_fontFamilyReverseLookup[fontFamily.get()] = iterPosition; - - // Then, by Font Family name - AZStd::pair> nameInsertPair(loweredFontFamilyName, fontFamily); - m_fontFamilies.insert(nameInsertPair); - - return true; -} - -XmlNodeRef CCryFont::LoadFontFamilyXml(const char* pFontFamilyName, string& outputDirectory, string& outputFullPath) -{ - outputFullPath = pFontFamilyName; - outputDirectory = PathUtil::GetPath(pFontFamilyName); - XmlNodeRef root = SafeLoadXmlFromFile(outputFullPath); - - // When parsing a tag in markup, only the font name is given and - // not a path, so we try to build a "best guess" path from the name. - if (!root) - { - string fileNoExtension(PathUtil::GetFileName(pFontFamilyName)); - string fileExtension(PathUtil::GetExt(pFontFamilyName)); - - if (fileExtension.empty()) - { - fileExtension = ".fontfamily"; - } - - // Try: "fonts/fontName.fontfamily" - outputDirectory = string("fonts/"); - outputFullPath = outputDirectory + fileNoExtension + fileExtension; - root = SafeLoadXmlFromFile(outputFullPath); - - // Finally, try: "fonts/fontName/fontName.fontfamily" - if (!root) - { - outputDirectory = string("fonts/") + fileNoExtension + "/"; - outputFullPath = outputDirectory + fileNoExtension + fileExtension; - root = SafeLoadXmlFromFile(outputFullPath); - } - } - - return root; -} - -#endif - diff --git a/Code/CryEngine/CryFont/CryFont.def b/Code/CryEngine/CryFont/CryFont.def deleted file mode 100644 index 43bfe0b13d..0000000000 --- a/Code/CryEngine/CryFont/CryFont.def +++ /dev/null @@ -1,3 +0,0 @@ -EXPORTS - ModuleInitISystem @2 - CryModuleGetMemoryInfo @8 diff --git a/Code/CryEngine/CryFont/CryFont.h b/Code/CryEngine/CryFont/CryFont.h deleted file mode 100644 index 726818f5a7..0000000000 --- a/Code/CryEngine/CryFont/CryFont.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_CRYFONT_CRYFONT_H -#define CRYINCLUDE_CRYFONT_CRYFONT_H -#pragma once - - -#if !defined(USE_NULLFONT_ALWAYS) - -#include -#include -#include -#include - -class CFFont; - - -class CCryFont - : public ICryFont -{ - friend class CFFont; - -public: - - static const Vec2i defaultGlyphSize; //!< Default glyph size indicates that glyphs in the font texture - //!< should be rendered at the maximum resolution supported by - //!< the font texture's glyph cell/slot configuration (configured - //!< via font XML). - -public: - CCryFont(ISystem* pSystem); - virtual ~CCryFont(); - - virtual void Release(); - virtual IFFont* NewFont(const char* pFontName); - virtual IFFont* GetFont(const char* pFontName) const; - virtual FontFamilyPtr LoadFontFamily(const char* pFontFamilyName) override; - virtual FontFamilyPtr GetFontFamily(const char* pFontFamilyName) override; - virtual void AddCharsToFontTextures(FontFamilyPtr pFontFamily, const char* pChars, int glyphSizeX = ICryFont::defaultGlyphSizeX, int glyphSizeY = ICryFont::defaultGlyphSizeY) override; - virtual void SetRendererProperties(IRenderer* pRenderer); - virtual void GetMemoryUsage(ICrySizer* pSizer) const; - virtual string GetLoadedFontNames() const; - virtual void OnLanguageChanged() override; - virtual void ReloadAllFonts() override; - -public: - void UnregisterFont(const char* pFontName); - bool RndPropIsRGBA() const { return m_rndPropIsRGBA; } - float RndPropHalfTexelOffset() const { return m_rndPropHalfTexelOffset; } - -private: - typedef std::map FontMap; - typedef FontMap::iterator FontMapItor; - typedef FontMap::const_iterator FontMapConstItor; - - typedef AZStd::map> FontFamilyMap; - typedef AZStd::map FontFamilyReverseLookupMap; - -private: - //! Convenience method for loading fonts - IFFont* LoadFont(const char* fontName); - - //! Called when final FontFamily shared_ptr is destroyed; do not call directly. - void ReleaseFontFamily(FontFamily* pFontFamily); - - //! Adds new entries into both font family maps for the given font family - //! - //! Note that it's not possible to update Font Family mappings with this - //! method. The only way to do that would be to release the font family - //! and re-load it with the new values. - //! - //! \return True only if the Font Family was added to the maps, false for all other cases (such as - //! when the font family is already mapped). - bool AddFontFamilyToMaps(const char* pFontFamilyFilename, const char* pFontFamilyName, FontFamilyPtr fontFamily); - - //! Internal method that (possibly) makes several attempts at locating and loading a given font family XML. - //! \param pFontFamilyName The name of the font family, or path to a font family file. - //! \param outputDirectory Path to loaded font family (no filename), may need resolving with PathUtil::MakeGamePath. - //! \param outputFullPath Full path to loaded font family, may need resolving with PathUtil::MakeGamePath. - XmlNodeRef LoadFontFamilyXml(const char* pFontFamilyName, string& outputDirectory, string& outputFullPath); - -private: - FontMap m_fonts; - FontFamilyMap m_fontFamilies; //!< Map font family names to weak ptrs so we can construct shared_ptrs but not keep a ref ourselves. - FontFamilyReverseLookupMap m_fontFamilyReverseLookup; // m_persistedFontFamilies; //!< Stores persisted fonts (if "persist font families" is enabled) - -}; - -#endif - -#endif // CRYINCLUDE_CRYFONT_CRYFONT_H diff --git a/Code/CryEngine/CryFont/CryFont.rc b/Code/CryEngine/CryFont/CryFont.rc deleted file mode 100644 index 5730d0a537..0000000000 --- a/Code/CryEngine/CryFont/CryFont.rc +++ /dev/null @@ -1,111 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Russian resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) -#ifdef _WIN32 -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT -#pragma code_page(1251) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // Russian resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// German (Germany) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) -#ifdef _WIN32 -LANGUAGE LANG_GERMAN, SUBLANG_GERMAN -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000904b0" - BEGIN - VALUE "CompanyName", "Amazon.com, Inc." - VALUE "FileVersion", "1, 0, 0, 1" - VALUE "LegalCopyright", "Portions of this file Copyright (c) Amazon.com, Inc. or its affiliates. All Rights Reserved. Original file Copyright (c) Crytek GMBH. Used under license by Amazon.com, Inc. and its affiliates." - VALUE "ProductName", "Lumberyard" - VALUE "ProductVersion", "1, 0, 0, 1" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x9, 1200 - END -END - -#endif // German (Germany) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/Code/CryEngine/CryFont/CryFont_precompiled.h b/Code/CryEngine/CryFont/CryFont_precompiled.h deleted file mode 100644 index e37845aa35..0000000000 --- a/Code/CryEngine/CryFont/CryFont_precompiled.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#pragma once - -#include - -#define CRYFONT_EXPORTS - -#include - -#include - -#include -#include -#include -#include - -#define USE_NULLFONT - -#if defined(DEDICATED_SERVER) -#define USE_NULLFONT_ALWAYS 1 -#endif - diff --git a/Code/CryEngine/CryFont/FBitmap.h b/Code/CryEngine/CryFont/FBitmap.h deleted file mode 100644 index 93f5505726..0000000000 --- a/Code/CryEngine/CryFont/FBitmap.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#pragma once -#ifndef CRYINCLUDE_CRYFONT_FBITMAP_H -#define CRYINCLUDE_CRYFONT_FBITMAP_H - - -class CFBitmap -{ -public: - CFBitmap(); - ~CFBitmap(); - - int Blur(int iIterations); - int Scale(float fScaleX, float fScaleY); - - int BlitFrom(CFBitmap* pSrc, int iSX, int iSY, int iDX, int iDY, int iW, int iH); - int BlitTo(CFBitmap* pDst, int iDX, int iDY, int iSX, int iSY, int iW, int iH); - - int Create(int iWidth, int iHeight); - int Release(); - - int SaveBitmap(const string& szFileName); - int Get32Bpp(unsigned int** pBuffer) - { - (*pBuffer) = new unsigned int[m_iWidth * m_iHeight]; - - if (!(*pBuffer)) - { - return 0; - } - - int iDataSize = m_iWidth * m_iHeight; - - for (int i = 0; i < iDataSize; i++) - { - (*pBuffer)[i] = (m_pData[i] << 24) | (m_pData[i] << 16) | (m_pData[i] << 8) | (m_pData[i]); - } - - return 1; - } - - int GetWidth() { return m_iWidth; } - int GetHeight() { return m_iHeight; } - - void SetRenderData(void* pRenderData) { m_pIRenderData = pRenderData; }; - void* GetRenderData() { return m_pIRenderData; }; - - void GetMemoryUsage (class ICrySizer* pSizer); - - unsigned char* GetData() { return m_pData; } - -public: - - int m_iWidth; - int m_iHeight; - - unsigned char* m_pData; - void* m_pIRenderData; -}; - - -#endif // CRYINCLUDE_CRYFONT_FBITMAP_H diff --git a/Code/CryEngine/CryFont/FFont.cpp b/Code/CryEngine/CryFont/FFont.cpp deleted file mode 100644 index c028a0827e..0000000000 --- a/Code/CryEngine/CryFont/FFont.cpp +++ /dev/null @@ -1,1550 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Font class. - - -#include "CryFont_precompiled.h" - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "FFont.h" -#include "CryFont.h" -#include "FontTexture.h" -#include "UnicodeIterator.h" - -#include -#include - -static ColorB ColorTable[10] = -{ - ColorB(0x00, 0x00, 0x00), // black - ColorB(0xff, 0xff, 0xff), // white - ColorB(0x00, 0x00, 0xff), // blue - ColorB(0x00, 0xff, 0x00), // green - ColorB(0xff, 0x00, 0x00), // red - ColorB(0x00, 0xff, 0xff), // cyan - ColorB(0xff, 0xff, 0x00), // yellow - ColorB(0xff, 0x00, 0xff), // purple - ColorB(0xff, 0x80, 0x00), // orange - ColorB(0x8f, 0x8f, 0x8f), // grey -}; - -static const int TabCharCount = 4; -static const size_t MsgBufferSize = 1024; -static const size_t MaxDrawVBQuads = 128; - -CFFont::CFFont(ISystem* pSystem, CCryFont* pCryFont, const char* pFontName) - : m_name(pFontName) - , m_curPath("") - , m_pFontTexture(0) - , m_fontBufferSize(0) - , m_pFontBuffer(0) - , m_texID(-1) - , m_textureVersion(0) - , m_pSystem(pSystem) - , m_pCryFont(pCryFont) - , m_fontTexDirty(false) - , m_effects() - , m_pDrawVB(0) - , m_nRefCount(0) - , m_monospacedFont(false) -{ - assert(m_name.c_str()); - assert(m_pSystem); - assert(m_pCryFont); - - // create default effect - SEffect* pEffect = AddEffect("default"); - pEffect->AddPass(); - - m_pDrawVB = new SVF_P3F_C4B_T2F[MaxDrawVBQuads * 6]; - - AddRef(); -} - -CFFont::~CFFont() -{ - // The font should already be unregistered through a call to - // CFFont::Release() at this point. - CRY_ASSERT(m_pCryFont == nullptr); - - Free(); - - SAFE_DELETE_ARRAY(m_pDrawVB); -} - -int32 CFFont::AddRef() -{ - int32 nRef = CryInterlockedIncrement(&m_nRefCount); - return nRef; -} - -int32 CFFont::Release() -{ - if (m_nRefCount > 0) - { - int32 nRef = CryInterlockedDecrement(&m_nRefCount); - if (nRef < 0) - { - CryFatalError("CBaseResource::Release() called more than once!"); - } - - if (nRef <= 0) - { - if (m_pCryFont) - { - AZStd::lock_guard locker(m_fontMutex); - - // Unregister font so no one can increase it's ref count while it is queued for deletion - m_pCryFont->UnregisterFont(m_name); - m_pCryFont = nullptr; - } - - if (gEnv->pRenderer) - { - gEnv->pRenderer->DeleteFont(this); - } - return 0; - } - return nRef; - } - return 0; -} - -// Load a font from a TTF file -bool CFFont::Load(const char* pFontFilePath, unsigned int width, unsigned int height, unsigned int widthNumSlots, unsigned int heightNumSlots, unsigned int flags, float sizeRatio) -{ - if (!pFontFilePath) - { - return false; - } - - Free(); - - auto pPak = gEnv->pCryPak; - - string fullFile; - if (pPak->IsAbsPath(pFontFilePath)) - { - fullFile = pFontFilePath; - } - else - { - fullFile = m_curPath + pFontFilePath; - } - - int iSmoothMethod = (flags & TTFFLAG_SMOOTH_MASK) >> TTFFLAG_SMOOTH_SHIFT; - int iSmoothAmount = (flags & TTFFLAG_SMOOTH_AMOUNT_MASK) >> TTFFLAG_SMOOTH_AMOUNT_SHIFT; - - AZ::IO::HandleType fileHandle = pPak->FOpen(fullFile.c_str(), "rb"); - if (fileHandle == AZ::IO::InvalidHandle) - { - return false; - } - - size_t fileSize = pPak->FGetSize(fileHandle); - if (!fileSize) - { - pPak->FClose(fileHandle); - return false; - } - - unsigned char* pBuffer = new unsigned char[fileSize]; - if (!pPak->FReadRaw(pBuffer, fileSize, 1, fileHandle)) - { - pPak->FClose(fileHandle); - delete [] pBuffer; - return false; - } - - pPak->FClose(fileHandle); - - if (!m_pFontTexture) - { - m_pFontTexture = new CFontTexture(); - } - - if (!m_pFontTexture || !m_pFontTexture->CreateFromMemory(pBuffer, (int)fileSize, width, height, iSmoothMethod, iSmoothAmount, widthNumSlots, heightNumSlots, sizeRatio)) - { - delete [] pBuffer; - return false; - } - - m_monospacedFont = m_pFontTexture->GetMonospaced(); - m_pFontBuffer = pBuffer; - m_fontBufferSize = fileSize; - m_fontTexDirty = false; - m_sizeRatio = sizeRatio; - - InitCache(); - - return true; -} - - -void CFFont::Free() -{ - IRenderer* pRenderer = gEnv->pRenderer; - if (m_texID >= 0 && pRenderer) - { - pRenderer->RemoveTexture(m_texID); - m_texID = -1; - m_textureVersion = 0; - } - - delete m_pFontTexture; - m_pFontTexture = 0; - - delete [] m_pFontBuffer; - m_pFontBuffer = 0; -} - -void CFFont::DrawString(float x, float y, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - IF (!pStr, 0) - { - return; - } - - DrawStringUInternal(x, y, 1.0f, pStr, asciiMultiLine, ctx); -} - -void CFFont::DrawString(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - IF (!pStr, 0) - { - return; - } - - DrawStringUInternal(x, y, z, pStr, asciiMultiLine, ctx); -} - -void CFFont::DrawStringUInternal(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - IF (!pStr || !m_pFontTexture || ctx.m_fxIdx >= m_effects.size() || m_effects[ctx.m_fxIdx].m_passes.empty(), 0) - { - return; - } - - AZStd::lock_guard locker(m_fontMutex); - - IRenderer* pRenderer = gEnv->pRenderer; - AZ_Assert(pRenderer, "gEnv->pRenderer is NULL"); - - pRenderer->DrawStringU(this, x, y, z, pStr, asciiMultiLine, ctx); -} - -ILINE uint32 COLCONV(uint32 clr) -{ - return ((clr & 0xff00ff00) | ((clr & 0xff0000) >> 16) | ((clr & 0xff) << 16)); -} - -void CFFont::RenderCallback(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - AZStd::lock_guard locker(m_fontMutex); - - const size_t fxSize = m_effects.size(); - - IF (fxSize && m_texID == -1 && !InitTexture(), 0) - { - return; - } - - // if the font is about to be deleted then m_pCryFont can be nullptr - if (!m_pCryFont) - { - return; - } - - SVF_P3F_C4B_T2F* pVertex = m_pDrawVB; - size_t vbOffset = 0; - - bool isFontRenderStateSet = false; - TransformationMatrices backupSceneMatrices; - IRenderer* pRenderer = gEnv->pRenderer; - AZ_Assert(pRenderer, "gEnv->pRenderer is NULL"); - - int baseState = ctx.m_baseState; - bool overrideViewProjMatrices = ctx.m_overrideViewProjMatrices; - int texId = m_texID; - - // Local function to share code needed when we render the vertex buffer so far - AZStd::function RenderVB = [&pVertex, &vbOffset, pRenderer] - { - gEnv->pRenderer->DrawDynVB(pVertex, 0, vbOffset, 0, prtTriangleList); - vbOffset = 0; - }; - - // Local function that is passed into CreateQuadsForText as the AddQuad function - AddFunction AddQuad = [&pVertex, &vbOffset, RenderVB] - (const Vec3& v0, const Vec3& v1, const Vec3& v2, const Vec3& v3, const Vec2& tc0, const Vec2& tc1, const Vec2& tc2, const Vec2& tc3, uint32 packedColor) - { - // define char quad - pVertex[vbOffset].xyz = v0; - pVertex[vbOffset].color.dcolor = packedColor; - pVertex[vbOffset].st = tc0; - - pVertex[vbOffset + 1].xyz = v1; - pVertex[vbOffset + 1].color.dcolor = packedColor; - pVertex[vbOffset + 1].st = tc1; - - pVertex[vbOffset + 2].xyz = v2; - pVertex[vbOffset + 2].color.dcolor = packedColor; - pVertex[vbOffset + 2].st = tc2; - - pVertex[vbOffset + 3].xyz = v2; - pVertex[vbOffset + 3].color.dcolor = packedColor; - pVertex[vbOffset + 3].st = tc2; - - pVertex[vbOffset + 4].xyz = v3; - pVertex[vbOffset + 4].color.dcolor = packedColor; - pVertex[vbOffset + 4].st = tc3; - - pVertex[vbOffset + 5].xyz = v0; - pVertex[vbOffset + 5].color.dcolor = packedColor; - pVertex[vbOffset + 5].st = tc0; - - vbOffset += 6; - - if (vbOffset >= MaxDrawVBQuads * 6) - { - RenderVB(); - } - }; - - // Local function that is passed into CreateQuadsForText as the BeginPass function - BeginPassFunction BeginPass = [&pVertex, &vbOffset, &isFontRenderStateSet, &backupSceneMatrices, texId, pRenderer, baseState, RenderVB, overrideViewProjMatrices] - (const SRenderingPass* pPass) - { - // We don't want to set this state before the call to CreateQuadsForText since that calls Prepare, - // which is needed before FontSetTexture - if (!isFontRenderStateSet) - { - pRenderer->FontSetTexture(texId, FILTER_TRILINEAR); - pRenderer->FontSetRenderingState(overrideViewProjMatrices, backupSceneMatrices); - gEnv->pRenderer->FontSetBlending(pPass->m_blendSrc, pPass->m_blendDest, baseState); - isFontRenderStateSet = true; - } - - if (vbOffset > 0) - { - RenderVB(); - } - - gEnv->pRenderer->FontSetBlending(pPass->m_blendSrc, pPass->m_blendDest, baseState); - }; - - CreateQuadsForText(x, y, z, pStr, asciiMultiLine, ctx, AddQuad, BeginPass); - - if (vbOffset > 0) - { - RenderVB(); - } - - // restore the old states - if (isFontRenderStateSet) - { - pRenderer->FontRestoreRenderingState(overrideViewProjMatrices, backupSceneMatrices); - } -} - -Vec2 CFFont::GetTextSize(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - IF (!pStr, 0) - { - return Vec2(0.0f, 0.0f); - } - - return GetTextSizeUInternal(pStr, asciiMultiLine, ctx); -} - -Vec2 CFFont::GetTextSizeUInternal(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - const size_t fxSize = m_effects.size(); - - IF (!pStr || !m_pFontTexture || !fxSize, 0) - { - return Vec2(0, 0); - } - - AZStd::lock_guard locker(m_fontMutex); - - Prepare(pStr, false, ctx.m_requestSize); - - IRenderer* pRenderer = gEnv->pRenderer; - AZ_Assert(pRenderer, "gEnv->pRenderer is NULL"); - - // This is the "logical" size of the font (in pixels). The actual size of - // the glyphs in the font texture may have additional scaling applied or - // could have been re-rendered at a different size. - Vec2 size = ctx.m_size; - if (ctx.m_sizeIn800x600) - { - pRenderer->ScaleCoord(size.x, size.y); - } - - // This scaling takes into account the logical size of the font relative - // to any additional scaling applied (such as from "size ratio"). - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); - - float maxW = 0; - float maxH = 0; - - const size_t fxIdx = ctx.m_fxIdx < fxSize ? ctx.m_fxIdx : 0; - const SEffect& fx = m_effects[fxIdx]; - - for (size_t i = 0, numPasses = fx.m_passes.size(); i < numPasses; ++i) - { - const SRenderingPass* pPass = &fx.m_passes[numPasses - i - 1]; - - // gather pass data - Vec2 offset = pPass->m_posOffset; - - float charX = offset.x; - float charY = offset.y + size.y; - - if (charY > maxH) - { - maxH = charY; - } - - // parse the string, ignoring control characters - uint32_t nextCh = 0; - Unicode::CIterator pChar(pStr); - while (uint32_t ch = *pChar) - { - ++pChar; - nextCh = *pChar; - switch (ch) - { - case '\\': - { - if (*pChar != 'n' || !asciiMultiLine) - { - break; - } - - ++pChar; - } - case '\n': - { - if (charX > maxW) - { - maxW = charX; - } - - charX = offset.x; - charY += size.y; - - if (charY > maxH) - { - maxH = charY; - } - - continue; - } - break; - case '\r': - { - if (charX > maxW) - { - maxW = charX; - } - - charX = offset.x; - continue; - } - break; - case '\t': - { - if (ctx.m_proportional) - { - charX += TabCharCount * size.x * FONT_SPACE_SIZE; - } - else - { - charX += TabCharCount * size.x * ctx.m_widthScale; - } - continue; - } - break; - case '$': - { - if (ctx.m_processSpecialChars) - { - if (*pChar == '$') - { - ++pChar; - } - else if (isdigit(*pChar)) - { - ++pChar; - continue; - } - else if (*pChar == 'O' || *pChar == 'o') - { - ++pChar; - continue; - } - } - } - break; - default: - break; - } - - const bool rerenderGlyphs = m_sizeBehavior == SizeBehavior::Rerender; - const Vec2i requestSize = rerenderGlyphs ? ctx.m_requestSize : CCryFont::defaultGlyphSize; - int horizontalAdvance = m_pFontTexture->GetHorizontalAdvance(ch, requestSize); - float advance; - - if (ctx.m_proportional) - { - advance = horizontalAdvance * scaleInfo.scale.x; - } - else - { - advance = size.x * ctx.m_widthScale; - } - - // Adjust "advance" here for kerning purposes - Vec2 kerningOffset(Vec2_Zero); - if (ctx.m_kerningEnabled && nextCh) - { - kerningOffset = m_pFontTexture->GetKerning(ch, nextCh) * scaleInfo.scale.x; - } - - // Adjust char width with tracking only if there is a next character - if (nextCh) - { - charX += ctx.m_tracking; - } - - charX += advance + kerningOffset.x; - } - - if (charX > maxW) - { - maxW = charX; - } - } - - return Vec2(maxW, maxH); -} - -uint32 CFFont::GetNumQuadsForText(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - uint32 numQuads = 0; - - const size_t fxSize = m_effects.size(); - const size_t fxIdx = ctx.m_fxIdx < fxSize ? ctx.m_fxIdx : 0; - const SEffect& fx = m_effects[fxIdx]; - - for (size_t j = 0, numPasses = fx.m_passes.size(); j < numPasses; ++j) - { - size_t i = numPasses - j - 1; - bool drawFrame = ctx.m_framed && i == numPasses - 1; - - if (drawFrame) - { - ++numQuads; - } - - uint32_t nextCh = 0; - Unicode::CIterator pChar(pStr); - while (uint32_t ch = *pChar) - { - ++pChar; - nextCh = *pChar; - - switch (ch) - { - case '\\': - { - if (*pChar != 'n' || !asciiMultiLine) - { - break; - } - ++pChar; - } - case '\n': - { - continue; - } - break; - case '\r': - { - continue; - } - break; - case '\t': - { - continue; - } - break; - case '$': - { - if (ctx.m_processSpecialChars) - { - if (*pChar == '$') - { - ++pChar; - } - else if (isdigit(*pChar)) - { - ++pChar; - continue; - } - else if (*pChar == 'O' || *pChar == 'o') - { - ++pChar; - continue; - } - } - } - break; - default: - break; - } - - ++numQuads; - } - } - - return numQuads; -} - -uint32 CFFont::WriteTextQuadsToBuffers(SVF_P2F_C4B_T2F_F4B* verts, uint16* indices, uint32 maxQuads, float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - AZStd::lock_guard locker(m_fontMutex); - - uint32 numQuadsWritten = 0; - - const size_t fxSize = m_effects.size(); - IF (fxSize && m_texID == -1 && !InitTexture(), 0) - { - return numQuadsWritten; - } - - // if the font is about to be deleted then m_pCryFont can be nullptr - if (!m_pCryFont) - { - return numQuadsWritten; - } - - SVF_P2F_C4B_T2F_F4B* pVertex = verts; - uint16* pIndex = indices; - size_t vbOffset = 0; - size_t ibOffset = 0; - - // Local function that is passed into CreateQuadsForText as the AddQuad function - AddFunction AddQuad = [&pVertex, &pIndex, &vbOffset, &ibOffset, maxQuads, &numQuadsWritten] - (const Vec3& v0, const Vec3& v1, const Vec3& v2, const Vec3& v3, const Vec2& tc0, const Vec2& tc1, const Vec2& tc2, const Vec2& tc3, uint32 packedColor) - { - Vec2 xy0(v0); - Vec2 xy1(v1); - Vec2 xy2(v2); - Vec2 xy3(v3); - - AZ_Assert(vbOffset + 3 < maxQuads * 4, "Vertex buffer overflow"); - AZ_Assert(ibOffset + 5 < maxQuads * 6, "Index buffer overflow"); - - // This should never happen but for safety make sure we never write off end of buffers (should hit asserts above if this is the case) - if (numQuadsWritten < maxQuads) - { - // define char quad - pVertex[vbOffset].xy = xy0; - pVertex[vbOffset].color.dcolor = packedColor; - pVertex[vbOffset].st = tc0; - pVertex[vbOffset].texIndex = 0; - pVertex[vbOffset].texHasColorChannel = 0; - pVertex[vbOffset].texIndex2 = 0; - pVertex[vbOffset].pad = 0; - - pVertex[vbOffset + 1].xy = xy1; - pVertex[vbOffset + 1].color.dcolor = packedColor; - pVertex[vbOffset + 1].st = tc1; - pVertex[vbOffset + 1].texIndex = 0; - pVertex[vbOffset + 1].texHasColorChannel = 0; - pVertex[vbOffset + 1].texIndex2 = 0; - pVertex[vbOffset + 1].pad = 0; - - pVertex[vbOffset + 2].xy = xy2; - pVertex[vbOffset + 2].color.dcolor = packedColor; - pVertex[vbOffset + 2].st = tc2; - pVertex[vbOffset + 2].texIndex = 0; - pVertex[vbOffset + 2].texHasColorChannel = 0; - pVertex[vbOffset + 2].texIndex2 = 0; - pVertex[vbOffset + 2].pad = 0; - - pVertex[vbOffset + 3].xy = xy3; - pVertex[vbOffset + 3].color.dcolor = packedColor; - pVertex[vbOffset + 3].st = tc3; - pVertex[vbOffset + 3].texIndex = 0; - pVertex[vbOffset + 3].texHasColorChannel = 0; - pVertex[vbOffset + 3].texIndex2 = 0; - pVertex[vbOffset + 3].pad = 0; - - pIndex[ibOffset] = vbOffset; - pIndex[ibOffset + 1] = vbOffset + 1; - pIndex[ibOffset + 2] = vbOffset + 2; - pIndex[ibOffset + 3] = vbOffset + 2; - pIndex[ibOffset + 4] = vbOffset + 3; - pIndex[ibOffset + 5] = vbOffset + 0; - - vbOffset += 4; - ibOffset += 6; - - ++numQuadsWritten; - } - }; - - // Local function that is passed into CreateQuadsForText as the BeginPass function - BeginPassFunction BeginPass = [] - (const SRenderingPass* /* pPass */) - { - }; - - - CreateQuadsForText(x, y, z, pStr, asciiMultiLine, ctx, AddQuad, BeginPass); - - return numQuadsWritten; -} - -int CFFont::GetFontTextureId() -{ - if (m_texID == -1 && !InitTexture()) - { - return -1; - } - - return m_texID; -} - -uint32 CFFont::GetFontTextureVersion() -{ - return m_textureVersion; -} - -void CFFont::CreateQuadsForText(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx, - AddFunction AddQuad, BeginPassFunction BeginPass) -{ - const size_t fxSize = m_effects.size(); - - Prepare(pStr, true, ctx.m_requestSize); - - const size_t fxIdx = ctx.m_fxIdx < fxSize ? ctx.m_fxIdx : 0; - const SEffect& fx = m_effects[fxIdx]; - - bool isRGB = m_pCryFont->RndPropIsRGBA(); - - float halfTexelShift = m_pCryFont->RndPropHalfTexelOffset(); - - bool passZeroColorOverridden = ctx.IsColorOverridden(); - - uint32 alphaBlend = passZeroColorOverridden ? ctx.m_colorOverride.a : fx.m_passes[0].m_color.a; - if (alphaBlend > 128) - { - ++alphaBlend; // 0..256 for proper blending - } - IRenderer* pRenderer = gEnv->pRenderer; - AZ_Assert(pRenderer, "gEnv->pRenderer is NULL"); - - // This is the "logical" size of the font (in pixels). The actual size of - // the glyphs in the font texture may have additional scaling applied or - // could have been re-rendered at a different size. - Vec2 size = ctx.m_size; - if (ctx.m_sizeIn800x600) - { - pRenderer->ScaleCoord(size.x, size.y); - } - - // This scaling takes into account the logical size of the font relative - // to any additional scaling applied (such as from "size ratio"). - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); - - Vec2 baseXY = Vec2(x, y); // in pixels - if (ctx.m_sizeIn800x600) - { - pRenderer->ScaleCoord(baseXY.x, baseXY.y); - } - - // Apply overscan border - const int flags = ctx.GetFlags(); - if ((flags & eDrawText_2D) && !(flags & eDrawText_IgnoreOverscan)) - { - Vec2 overscanBorder = Vec2(0.0f, 0.0f); - pRenderer->EF_Query(EFQ_OverscanBorders, overscanBorder); - - const float screenWidth = (float)pRenderer->GetOverlayWidth(); - const float screenHeight = (float)pRenderer->GetOverlayHeight(); - Vec2 overscanBorderOffset = ZERO; - if (!(flags & eDrawText_Center)) - { - overscanBorderOffset.x = (overscanBorder.x * screenWidth); - } - if (!(flags & eDrawText_CenterV)) - { - overscanBorderOffset.y = (overscanBorder.y * screenHeight); - } - if (flags & eDrawText_Right) - { - overscanBorderOffset.x = -overscanBorderOffset.x; - } - if (flags & eDrawText_Bottom) - { - overscanBorderOffset.y = -overscanBorderOffset.y; - } - baseXY += overscanBorderOffset; - } - - // snap for pixel perfect rendering (better quality for text) - if (ctx.m_pixelAligned) - { - baseXY.x = floor(baseXY.x); - baseXY.y = floor(baseXY.y); - - // for smaller fonts (half res or less) it's better to average multiple pixels (we don't miss lines) - if (scaleInfo.scale.x < 0.9f) - { - baseXY.x += 0.5f; // try to average two columns (for exact half res) - } - if (scaleInfo.scale.y < 0.9f) - { - baseXY.y += 0.25f; // hand tweaked value to get a good result with tiny font (640x480 underscore in console) - } - } - - for (size_t j = 0, numPasses = fx.m_passes.size(); j < numPasses; ++j) - { - size_t i = numPasses - j - 1; - - const SRenderingPass* pPass = &fx.m_passes[i]; - - if (!i) - { - alphaBlend = 256; - } - - ColorB passColor = !i && passZeroColorOverridden ? ctx.m_colorOverride : fx.m_passes[i].m_color; - - // gather pass data - Vec2 offset = pPass->m_posOffset; // in pixels - - float charX = baseXY.x + offset.x; // in pixels - float charY = baseXY.y + offset.y; // in pixels - - ColorB color = passColor; - - bool drawFrame = ctx.m_framed && i == numPasses - 1; - - BeginPass(pPass); - - if (drawFrame) - { - ColorB tempColor(255, 255, 255, 255); - uint32 frameColor = tempColor.pack_abgr8888(); - if (!isRGB) - { - frameColor = COLCONV(frameColor); - } - - Vec2 textSize = GetTextSizeUInternal(pStr, asciiMultiLine, ctx); - - float x0 = baseXY.x - 12; - float y0 = baseXY.y - 6; - float x1 = baseXY.x + textSize.x + 12; - float y1 = baseXY.y + textSize.y + 6; - - bool culled = false; - IF (ctx.m_clippingEnabled, 0) - { - float clipX = ctx.m_clipX; - float clipY = ctx.m_clipY; - float clipR = ctx.m_clipX + ctx.m_clipWidth; - float clipB = ctx.m_clipY + ctx.m_clipHeight; - - if ((x0 >= clipR) || (y0 >= clipB) || (x1 < clipX) || (y1 < clipY)) - { - culled = true; - } - - x0 = max(clipX, x0); - y0 = max(clipY, y0); - x1 = min(clipR, x1); - y1 = min(clipB, y1); - - //if (!culled && ((x1 - x0 <= 0.0f) || (y1 - y0 <= 0.0f))) - // culled = true; - } - - IF (!culled, 1) - { - Vec3 v0(x0, y0, z); - Vec3 v2(x1, y1, z); - Vec3 v1(v2.x, v0.y, v0.z); // to avoid float->half conversion - Vec3 v3(v0.x, v2.y, v0.z); // to avoid float->half conversion - - if (ctx.m_drawTextFlags & eDrawText_UseTransform) - { - v0 = ctx.m_transform * v0; - v2 = ctx.m_transform * v2; - v1 = ctx.m_transform * v1; - v3 = ctx.m_transform * v3; - } - - Vec2 gradientUvMin, gradientUvMax; - GetGradientTextureCoord(gradientUvMin.x, gradientUvMin.y, gradientUvMax.x, gradientUvMax.y); - - // define the frame quad - Vec2 uv(gradientUvMin.x, gradientUvMax.y); - AddQuad(v0, v1, v2, v3, uv, uv, uv, uv, frameColor); - } - } - - // parse the string, ignoring control characters - uint32_t nextCh = 0; - Unicode::CIterator pChar(pStr); - while (uint32_t ch = *pChar) - { - ++pChar; - nextCh = *pChar; - - switch (ch) - { - case '\\': - { - if (*pChar != 'n' || !asciiMultiLine) - { - break; - } - ++pChar; - } - case '\n': - { - charX = baseXY.x + offset.x; - charY += size.y; - continue; - } - break; - case '\r': - { - charX = baseXY.x + offset.x; - continue; - } - break; - case '\t': - { - if (ctx.m_proportional) - { - charX += TabCharCount * size.x * FONT_SPACE_SIZE; - } - else - { - charX += TabCharCount * size.x * ctx.m_widthScale; - } - continue; - } - break; - case '$': - { - if (ctx.m_processSpecialChars) - { - if (*pChar == '$') - { - ++pChar; - } - else if (isdigit(*pChar)) - { - if (!i) - { - int colorIndex = (*pChar) - '0'; - ColorB newColor = ColorTable[colorIndex]; - color.r = newColor.r; - color.g = newColor.g; - color.b = newColor.b; - // Leave alpha at original value! - } - ++pChar; - continue; - } - else if (*pChar == 'O' || *pChar == 'o') - { - if (!i) - { - color = passColor; - } - ++pChar; - continue; - } - } - } - break; - default: - break; - } - - // get texture coordinates - float texCoord[4]; - - int charOffsetX, charOffsetY; // in font texels - int charSizeX, charSizeY; // in font texels - const bool rerenderGlyphs = m_sizeBehavior == SizeBehavior::Rerender; - const Vec2i requestSize = rerenderGlyphs ? ctx.m_requestSize : CCryFont::defaultGlyphSize; - m_pFontTexture->GetTextureCoord(m_pFontTexture->GetCharSlot(ch, requestSize), texCoord, charSizeX, charSizeY, charOffsetX, charOffsetY, requestSize); - - int horizontalAdvance = m_pFontTexture->GetHorizontalAdvance(ch, requestSize); - float advance; - - if (ctx.m_proportional) - { - advance = horizontalAdvance * scaleInfo.scale.x; - } - else - { - advance = size.x * ctx.m_widthScale; - } - - Vec2 kerningOffset(Vec2_Zero); - if (ctx.m_kerningEnabled && nextCh) - { - kerningOffset = m_pFontTexture->GetKerning(ch, nextCh) * scaleInfo.scale.x; - } - - float trackingOffset = 0.0f; - if (nextCh) - { - trackingOffset = ctx.m_tracking; - } - - float px = charX + charOffsetX * scaleInfo.scale.x; // in pixels - float py = charY + charOffsetY * scaleInfo.scale.y; // in pixels - float pr = px + charSizeX * scaleInfo.scale.x; - float pb = py + charSizeY * scaleInfo.scale.y; - - // compute clipping - float newX = px; // in pixels - float newY = py; // in pixels - float newR = pr; // in pixels - float newB = pb; // in pixels - - if (ctx.m_clippingEnabled) - { - float clipX = ctx.m_clipX; - float clipY = ctx.m_clipY; - float clipR = ctx.m_clipX + ctx.m_clipWidth; - float clipB = ctx.m_clipY + ctx.m_clipHeight; - - // clip non visible - if ((px >= clipR) || (py >= clipB) || (pr < clipX) || (pb < clipY)) - { - charX += advance + kerningOffset.x + trackingOffset; - continue; - } - // clip partially visible - else - { - float width = horizontalAdvance * scaleInfo.rcpCellWidth; - if ((width <= 0.0f) || (size.y <= 0.0f)) - { - charX += advance + kerningOffset.x + trackingOffset; - continue; - } - - // clip the image to the scissor rect - newX = max(clipX, px); - newY = max(clipY, py); - newR = min(clipR, pr); - newB = min(clipB, pb); - - float rcpWidth = 1.0f / width; - float rcpHeight = 1.0f / size.y; - - float texW = texCoord[2] - texCoord[0]; - float texH = texCoord[3] - texCoord[1]; - - // clip horizontal - texCoord[0] = texCoord[0] + texW * (newX - px) * rcpWidth; - texCoord[2] = texCoord[2] + texW * (newR - pr) * rcpWidth; - - // clip vertical - texCoord[1] = texCoord[1] + texH * (newY - py) * rcpHeight; - texCoord[3] = texCoord[3] + texH * (newB - pb) * rcpHeight; - } - } - - newX += halfTexelShift; - newY += halfTexelShift; - newR += halfTexelShift; - newB += halfTexelShift; - - //int offset = vbLen * 6; - - Vec3 v0(newX, newY, z); - Vec3 v2(newR, newB, z); - Vec3 v1(v2.x, v0.y, v0.z); // to avoid float->half conversion - Vec3 v3(v0.x, v2.y, v0.z); // to avoid float->half conversion - - Vec2 tc0(texCoord[0], texCoord[1]); - Vec2 tc2(texCoord[2], texCoord[3]); - Vec2 tc1(tc2.x, tc0.y); // to avoid float->half conversion - Vec2 tc3(tc0.x, tc2.y); // to avoid float->half conversion - - uint32 packedColor = 0; - { - ColorB tempColor = color; - tempColor.a = ((uint32) tempColor.a * alphaBlend) >> 8; - packedColor = tempColor.pack_abgr8888(); - - if (!isRGB) - { - packedColor = COLCONV(packedColor); - } - } - - if (ctx.m_drawTextFlags & eDrawText_UseTransform) - { - v0 = ctx.m_transform * v0; - v2 = ctx.m_transform * v2; - v1 = ctx.m_transform * v1; - v3 = ctx.m_transform * v3; - } - - AddQuad(v0, v1, v2, v3, tc0, tc1, tc2, tc3, packedColor); - - charX += advance + kerningOffset.x + trackingOffset; - } - } -} - -CFFont::TextScaleInfoInternal CFFont::CalculateScaleInternal(const STextDrawContext& ctx) const -{ - Vec2 size = GetRestoredFontSize(ctx); // in pixel - - IRenderer* pRenderer = gEnv->pRenderer; - AZ_Assert(pRenderer, "gEnv->pRenderer is NULL"); - - if (ctx.m_sizeIn800x600) - { - pRenderer->ScaleCoord(size.x, size.y); - } - - float rcpCellWidth; - Vec2 scale; - - int fontTextureCellWidth = GetFontTexture()->GetCellWidth(); - int fontTextureCellHeight = GetFontTexture()->GetCellHeight(); - - if (ctx.m_proportional) - { - rcpCellWidth = (1.0f / static_cast(fontTextureCellWidth)) * size.x; - scale = Vec2(rcpCellWidth * ctx.m_widthScale, size.y / static_cast(fontTextureCellHeight)); - } - else - { - rcpCellWidth = size.x / 16.0f; - scale = Vec2(rcpCellWidth * ctx.m_widthScale, size.y * ctx.m_widthScale / 16.0f); - } - - return TextScaleInfoInternal(scale, rcpCellWidth); -} - -size_t CFFont::GetTextLength(const char* pStr, const bool asciiMultiLine) const -{ - size_t len = 0; - - // parse the string, ignoring control characters - const char* pChar = pStr; - while (char ch = *pChar++) - { - if ((ch & 0xC0) == 0x80) - { - continue; // Skip UTF-8 continuation bytes, we count only the first byte of a code-point - } - switch (ch) - { - case '\\': - { - if (*pChar != 'n' || !asciiMultiLine) - { - break; - } - ++pChar; - } - case '\n': - case '\r': - case '\t': - { - continue; - } - break; - case '$': - { - if (*pChar == '$') - { - ++pChar; - } - else if (*pChar) - { - ++pChar; - continue; - } - } - break; - default: - break; - } - ++len; - } - - return len; -} - -void CFFont::WrapText(string& result, float maxWidth, const char* pStr, const STextDrawContext& ctx) -{ - result = pStr; - - if (ctx.m_sizeIn800x600) - { - maxWidth = gEnv->pRenderer->ScaleCoordX(maxWidth); - } - - Vec2 strSize = GetTextSizeUInternal(result.c_str(), true, ctx); - - if (strSize.x <= maxWidth) - { - return; - } - - // Assume a given string has multiple lines of text if it's height is - // greater than the height of its font. - const bool multiLine = strSize.y > GetRestoredFontSize(ctx).y; - - int lastSpace = -1; - const char* pLastSpace = NULL; - float lastSpaceWidth = 0.0f; - - float curCharWidth = 0.0f; - float curLineWidth = 0.0f; - float biggestLineWidth = 0.0f; - float widthSum = 0.0f; - - int curChar = 0; - Unicode::CIterator pChar(result.c_str()); - while (uint32_t ch = *pChar) - { - // Dollar sign escape codes. The following scenarios can happen with dollar signs embedded in a string. - // The following character is... - // 1. ... a digit, 'O' or 'o' which indicates a color code. Both characters a skipped in the width calculation. - // 2. ... another dollar sign. Only 1 dollar sign is skipped in the width calculation. - // 3. ... anything else. The dollar sign is processed in the width calculation. - if (ctx.m_processSpecialChars && ch == '$') - { - ++pChar; - char nextChar = *pChar; - - if (isdigit(nextChar) || nextChar == 'O' || nextChar == 'o') - { - ++pChar; - continue; - } - else if (nextChar != '$') - { - --pChar; - } - } - - // get char width and sum it to the line width - // Note: This is not unicode compatible, since char-width depends on surrounding context (ie, combining diacritics etc) - char codepoint[5]; - Unicode::Convert(codepoint, ch); - curCharWidth = GetTextSizeUInternal(codepoint, true, ctx).x; - - // keep track of spaces - // they are good for splitting the string - if (ch == ' ') - { - lastSpace = curChar; - lastSpaceWidth = curLineWidth + curCharWidth; - pLastSpace = pChar.GetPosition(); - assert(*pLastSpace == ' '); - } - - bool prevCharWasNewline = false; - const bool notFirstChar = pChar.GetPosition() != result.c_str(); - if (*pChar && notFirstChar) - { - const char* pPrevCharStr = pChar.GetPosition() - 1; - prevCharWasNewline = pPrevCharStr[0] == '\n'; - } - - // if line exceed allowed width, split it - if (prevCharWasNewline || (curLineWidth + curCharWidth >= maxWidth && (*pChar))) - { - if (prevCharWasNewline) - { - // Reset the current line width to account for newline - curLineWidth = curCharWidth; - widthSum += curLineWidth; - } - else if ((lastSpace > 0) && ((curChar - lastSpace) < 16) && (curChar - lastSpace >= 0)) // 16 is the default threshold - { - *(char*)pLastSpace = '\n'; // This is safe inside UTF-8 because space is single-byte codepoint - - if (lastSpaceWidth > biggestLineWidth) - { - biggestLineWidth = lastSpaceWidth; - } - - curLineWidth = curLineWidth - lastSpaceWidth + curCharWidth; - widthSum += curLineWidth; - } - else - { - const char* pBuf = pChar.GetPosition(); - size_t bytesProcessed = pBuf - result.c_str(); - result.insert(bytesProcessed, '\n'); // Insert the newline, this invalidates the iterator - pBuf = result.c_str() + bytesProcessed; // In case reallocation occurs, we ensure we are inside the new buffer - assert(*pBuf == '\n'); - pChar.SetPosition(pBuf); // pChar once again points inside the target string, at the current character - assert(*pChar == ch); - ++pChar; - ++curChar; - - if (curLineWidth > biggestLineWidth) - { - biggestLineWidth = curLineWidth; - } - - widthSum += curLineWidth; - curLineWidth = curCharWidth; - } - - // if we don't need any more line breaks, then just stop, but for - // multiple lines we can't assume that there aren't any more - // strings to wrap, so continue - if (strSize.x - widthSum <= maxWidth && !multiLine) - { - break; - } - - lastSpaceWidth = 0; - lastSpace = 0; - } - else - { - curLineWidth += curCharWidth; - } - - ++curChar; - ++pChar; - } -} - -void CFFont::GetMemoryUsage (ICrySizer* pSizer) const -{ - pSizer->AddObject(m_name); - pSizer->AddObject(m_curPath); - pSizer->AddObject(m_pFontTexture); - pSizer->AddObject(m_pFontBuffer, m_fontBufferSize); - pSizer->AddObject(m_effects); - pSizer->AddObject(m_pDrawVB, sizeof(SVF_P3F_C4B_T2F) * MaxDrawVBQuads * 6); -} - -void CFFont::GetGradientTextureCoord(float& minU, float& minV, float& maxU, float& maxV) const -{ - const CTextureSlot* pSlot = m_pFontTexture->GetGradientSlot(); - assert(pSlot); - - float invWidth = 1.0f / (float) m_pFontTexture->GetWidth(); - float invHeight = 1.0f / (float) m_pFontTexture->GetHeight(); - - // deflate by one pixel to avoid bilinear filtering on the borders - minU = pSlot->vTexCoord[0] + invWidth; - minV = pSlot->vTexCoord[1] + invHeight; - maxU = pSlot->vTexCoord[0] + (pSlot->iCharWidth - 1) * invWidth; - maxV = pSlot->vTexCoord[1] + (pSlot->iCharHeight - 1) * invHeight; -} - -unsigned int CFFont::GetEffectId(const char* pEffectName) const -{ - if (pEffectName) - { - for (size_t i = 0, numEffects = m_effects.size(); i < numEffects; ++i) - { - if (!strcmp(m_effects[i].m_name.c_str(), pEffectName)) - { - return i; - } - } - } - - return 0; -} - -unsigned int CFFont::GetNumEffects() const -{ - return m_effects.size(); -} - -const char* CFFont::GetEffectName(unsigned int effectId) const -{ - return (effectId < m_effects.size()) ? m_effects[effectId].m_name.c_str() : nullptr; -} - -Vec2 CFFont::GetMaxEffectOffset(unsigned int effectId) const -{ - Vec2 maxOffset(0.0f, 0.0f); - - if (effectId < m_effects.size()) - { - const SEffect& fx = m_effects[effectId]; - - for (size_t i = 0, numPasses = fx.m_passes.size(); i < numPasses; ++i) - { - const SRenderingPass* pPass = &fx.m_passes[numPasses - i - 1]; - - // gather pass data - Vec2 offset = pPass->m_posOffset; - - if (maxOffset.x < offset.x) - { - maxOffset.x = offset.x; - } - - if (maxOffset.y < offset.y) - { - maxOffset.y = offset.y; - } - } - } - - return maxOffset; -} - -bool CFFont::DoesEffectHaveTransparency(unsigned int effectId) const -{ - const size_t fxSize = m_effects.size(); - const size_t fxIdx = effectId < fxSize ? effectId : 0; - const SEffect& fx = m_effects[fxIdx]; - - for (auto& pass : fx.m_passes) - { - // if the alpha is not 255 then there is transparency - if (pass.m_color.a != 255) - { - return true; - } - } - - return false; -} - -void CFFont::AddCharsToFontTexture(const char* pChars, int glyphSizeX, int glyphSizeY) -{ - AZStd::lock_guard locker(m_fontMutex); - Vec2i glyphSize(glyphSizeX, glyphSizeY); - Prepare(pChars, false, glyphSize); -} - -Vec2 CFFont::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph, const STextDrawContext& ctx) const -{ - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); - return m_pFontTexture->GetKerning(leftGlyph, rightGlyph) * scaleInfo.scale.x; -} - -float CFFont::GetAscender(const STextDrawContext& ctx) const -{ - return (ctx.m_size.y * m_pFontTexture->GetAscenderToHeightRatio()); -} - -float CFFont::GetBaseline(const STextDrawContext& ctx) const -{ - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); - // Calculate baseline the same way as the font renderer which uses the glyph height * size ratio. - // Adding 1 because FontTexture always adds 1 to the char height in GetTextureCoord - return (round(m_pFontTexture->GetCellHeight() * GetSizeRatio()) + 1.0f) * scaleInfo.scale.y; -} - -bool CFFont::InitTexture() -{ - m_texID = gEnv->pRenderer->FontCreateTexture(m_pFontTexture->GetWidth(), m_pFontTexture->GetHeight(), (uint8*)m_pFontTexture->GetBuffer(), eTF_A8, IRenderer::FontCreateTextureGenMipsDefaultValue, m_name.c_str()); - m_textureVersion = 0; - return m_texID >= 0; -} - -bool CFFont::InitCache() -{ - m_pFontTexture->CreateGradientSlot(); - - // precache (not required but for faster printout later) - const char first = ' '; - const char last = '~'; - char buf[last - first + 2]; - char* p = buf; - - // precache all [normal] printable characters to the string (missing ones are updated on demand) - for (int i = first; i <= last; ++i) - { - *p++ = i; - } - *p = 0; - - Prepare(buf, false); - - return true; -} - -CFFont::SEffect* CFFont::AddEffect(const char* pEffectName) -{ - m_effects.push_back(SEffect(pEffectName)); - return &m_effects[m_effects.size() - 1]; -} - -CFFont::SEffect* CFFont::GetDefaultEffect() -{ - return &m_effects[0]; -} - -void CFFont::Prepare(const char* pStr, bool updateTexture, const Vec2i& glyphSize) -{ - const bool rerenderGlyphs = m_sizeBehavior == SizeBehavior::Rerender; - const Vec2i usedGlyphSize = rerenderGlyphs ? glyphSize : CCryFont::defaultGlyphSize; - bool texUpdateNeeded = m_pFontTexture->PreCacheString(pStr, nullptr, m_sizeRatio, usedGlyphSize, m_fontHintParams) == 1 || m_fontTexDirty; - if (updateTexture && texUpdateNeeded && m_texID >= 0) - { - gEnv->pRenderer->FontUpdateTexture(m_texID, 0, 0, m_pFontTexture->GetWidth(), m_pFontTexture->GetHeight(), (unsigned char*)m_pFontTexture->GetBuffer()); - m_fontTexDirty = false; - ++m_textureVersion; - - // Let any listeners know that the font texture has changed - EBUS_EVENT(FontNotificationBus, OnFontTextureUpdated, this); - } - else - { - m_fontTexDirty = texUpdateNeeded; - } -} - -Vec2 CFFont::GetRestoredFontSize(const STextDrawContext& ctx) const -{ - // Calculate the scale that we need to apply to the text size to ensure - // it's on-screen size is the same regardless of the slot scaling needed - // to fit the glyphs of the font within the font texture slots. - float restoringScale = IFFontConstants::defaultSizeRatio / m_sizeRatio; - return Vec2(ctx.m_size.x * restoringScale, ctx.m_size.y * restoringScale); -} - -#endif - diff --git a/Code/CryEngine/CryFont/FFont.h b/Code/CryEngine/CryFont/FFont.h deleted file mode 100644 index c2eddd7b1d..0000000000 --- a/Code/CryEngine/CryFont/FFont.h +++ /dev/null @@ -1,234 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Font class. - - -#ifndef CRYINCLUDE_CRYFONT_FFONT_H -#define CRYINCLUDE_CRYFONT_FFONT_H -#pragma once - - -#if !defined(USE_NULLFONT_ALWAYS) - -#include -#include -#include -#include -#include "CryFont.h" - -#include - -struct ISystem; -class CFontTexture; - - -class CFFont - : public IFFont - , public IFFont_RenderProxy -{ -public: - //! Determines how characters of different sizes should be handled during render. - enum class SizeBehavior - { - Scale, //!< Default behavior; glyphs rendered at different sizes are rendered on scaled geometry - Rerender //!< Similar to Scale, but the glyph in the font texture is re-rendered to match the target - //!< size, as long as the size isn't greater than the maximum glyph/slot resolution as - //!< configured for the font texture in the font XML. - }; - - //! The hinting visual algorithm to be used (when hinting is enabled) - enum class HintStyle - { - Normal, //!< Default hinting behavior provided by font renderer - Light //!< Produces fuzzier glyphs but more accurately tracks glyph shape - }; - - //! Chooses whether hinting info should be obtained from the font, turned off entirely, or automatically generated - enum class HintBehavior - { - Default, //!< Obtain hinting data from font itself - AutoHint, //!< Procedurally derive hinting information from glyph - NoHinting, //!< Disable hinting entirely - }; - - //! Simple struct used to communicate font hinting parameters to font renderer. - struct FontHintParams - { - FontHintParams() : hintStyle(HintStyle::Normal), hintBehavior(HintBehavior::Default) { } - - HintStyle hintStyle; - HintBehavior hintBehavior; - }; - - struct SRenderingPass - { - ColorB m_color; - Vec2 m_posOffset; - int m_blendSrc; - int m_blendDest; - - SRenderingPass() - : m_color(255, 255, 255, 255) - , m_posOffset(0, 0) - , m_blendSrc(GS_BLSRC_SRCALPHA) - , m_blendDest(GS_BLDST_ONEMINUSSRCALPHA) - { - } - - void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {} - }; - - struct SEffect - { - string m_name; - std::vector m_passes; - - SEffect(const char* name) - : m_name(name) - { - assert(name); - } - - SRenderingPass* AddPass() - { - m_passes.push_back(SRenderingPass()); - return &m_passes[m_passes.size() - 1]; - } - - void ClearPasses() - { - m_passes.resize(0); - } - - void GetMemoryUsage(ICrySizer* pSizer) const - { - pSizer->AddObject(m_name); - pSizer->AddObject(m_passes); - } - }; - - typedef std::vector Effects; - typedef Effects::iterator EffectsIt; - -public: - virtual int32 AddRef() override; - virtual int32 Release() override; - virtual bool Load(const char* pFontFilePath, unsigned int width, unsigned int height, unsigned int widthNumSlots, unsigned int heightNumSlots, unsigned int flags, float sizeRatio); - virtual bool Load(const char* pXMLFile); - virtual void Free(); - virtual void DrawString(float x, float y, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - virtual void DrawString(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - virtual Vec2 GetTextSize(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - virtual size_t GetTextLength(const char* pStr, const bool asciiMultiLine) const; - virtual void WrapText(string& result, float maxWidth, const char* pStr, const STextDrawContext& ctx); - virtual void GetMemoryUsage(ICrySizer* pSizer) const; - virtual void GetGradientTextureCoord(float& minU, float& minV, float& maxU, float& maxV) const; - virtual unsigned int GetEffectId(const char* pEffectName) const; - virtual unsigned int GetNumEffects() const; - virtual const char* GetEffectName(unsigned int effectId) const; - virtual Vec2 GetMaxEffectOffset(unsigned int effectId) const; - virtual bool DoesEffectHaveTransparency(unsigned int effectId) const; - virtual void AddCharsToFontTexture(const char* pChars, int glyphSizeX = ICryFont::defaultGlyphSizeX, int glyphSizeY = ICryFont::defaultGlyphSizeY) override; - virtual Vec2 GetKerning(uint32_t leftGlyph, uint32_t rightGlyph, const STextDrawContext& ctx) const override; - virtual float GetAscender(const STextDrawContext& ctx) const override; - virtual float GetBaseline(const STextDrawContext& ctx) const override; - - virtual uint32 GetNumQuadsForText(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - virtual uint32 WriteTextQuadsToBuffers(SVF_P2F_C4B_T2F_F4B* verts, uint16* indices, uint32 maxQuads, float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - virtual int GetFontTextureId(); - virtual uint32 GetFontTextureVersion(); - - virtual float GetSizeRatio() const override { return m_sizeRatio; } - -public: - virtual void RenderCallback(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - -public: - CFFont(ISystem* pSystem, CCryFont* pCryFont, const char* pFontName); - - bool InitTexture(); - bool InitCache(); - - CFontTexture* GetFontTexture() const { return m_pFontTexture; } - const string& GetName() const { return m_name; } - - SEffect* AddEffect(const char* pEffectName); - SEffect* GetDefaultEffect(); - -private: - virtual ~CFFont(); - - void Prepare(const char* pStr, bool updateTexture, const Vec2i& glyphSize = CCryFont::defaultGlyphSize); - void DrawStringUInternal(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - Vec2 GetTextSizeUInternal(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - - using AddFunction = AZStd::function; - using BeginPassFunction = AZStd::function; - - //! This function is used by both RenderCallback and WriteTextQuadsToBuffers - //! To do this is takes two function pointers that implement the appropriate AddQuad and BeginPass behavior - void CreateQuadsForText(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx, - AddFunction AddQuad, BeginPassFunction BeginPass); - - struct TextScaleInfoInternal - { - TextScaleInfoInternal(const Vec2& _scale, float _rcpCellWidth) - : scale(_scale), rcpCellWidth(_rcpCellWidth) { } - - Vec2 scale; - float rcpCellWidth; - }; - - TextScaleInfoInternal CalculateScaleInternal(const STextDrawContext& ctx) const; - - Vec2 GetRestoredFontSize(const STextDrawContext& ctx) const; - -private: - string m_name; - string m_curPath; - - CFontTexture* m_pFontTexture; - - size_t m_fontBufferSize; - unsigned char* m_pFontBuffer; - - int m_texID; - uint32 m_textureVersion; - - ISystem* m_pSystem; - - AZStd::recursive_mutex m_fontMutex; //!< Controls access between main and render threads. It's common for one thread - //!< to add un-cached glyphs to the font texture while another is accessing the - //!< font texture. - - CCryFont* m_pCryFont; - - bool m_fontTexDirty; - - Effects m_effects; - - SVF_P3F_C4B_T2F* m_pDrawVB; - - volatile int32 m_nRefCount; - - bool m_monospacedFont; //!< True if this font is fixed/monospaced, false otherwise (obtained from FreeType) - - float m_sizeRatio = IFFontConstants::defaultSizeRatio; - SizeBehavior m_sizeBehavior = SizeBehavior::Scale; //!< Changes how glyphs rendered at different sizes are rendered. - FontHintParams m_fontHintParams; //!< How the font should be hinted when its loaded and rendered to the font texture -}; - -#endif - -#endif // CRYINCLUDE_CRYFONT_FFONT_H diff --git a/Code/CryEngine/CryFont/FFontXML.cpp b/Code/CryEngine/CryFont/FFontXML.cpp deleted file mode 100644 index 1fdd84994e..0000000000 --- a/Code/CryEngine/CryFont/FFontXML.cpp +++ /dev/null @@ -1,448 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : XML parsing to load a font. - - -#include "CryFont_precompiled.h" - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "FFont.h" -#include "FontTexture.h" -#include -#include - -#if defined(WIN32) || defined(WIN64) -# include -# include -#endif - -////////////////////////////////////////////////////////////////////////// -// Xml parser implementation - -enum -{ - - ELEMENT_UNKNOWN = 0, - ELEMENT_FONT = 1, - ELEMENT_EFFECT = 2, - ELEMENT_EFFECTFILE = 3, - ELEMENT_PASS = 4, - ELEMENT_PASS_COLOR = 5, - ELEMENT_PASS_POSOFFSET = 12, - ELEMENT_PASS_BLEND = 14 -}; - -static inline int GetBlendModeFromString(const string& str, bool dst) -{ - int blend = GS_BLSRC_ONE; - - if (str == "zero") - { - blend = dst ? GS_BLDST_ZERO : GS_BLSRC_ZERO; - } - else if (str == "one") - { - blend = dst ? GS_BLDST_ONE : GS_BLSRC_ONE; - } - else if (str == "srcalpha" || - str == "src_alpha") - { - blend = dst ? GS_BLDST_SRCALPHA : GS_BLSRC_SRCALPHA; - } - else if (str == "invsrcalpha" || - str == "inv_src_alpha") - { - blend = dst ? GS_BLDST_ONEMINUSSRCALPHA : GS_BLSRC_ONEMINUSSRCALPHA; - } - else if (str == "dstalpha" || - str == "dst_alpha") - { - blend = dst ? GS_BLDST_DSTALPHA : GS_BLSRC_DSTALPHA; - } - else if (str == "invdstalpha" || - str == "inv_dst_alpha") - { - blend = dst ? GS_BLDST_ONEMINUSDSTALPHA : GS_BLSRC_ONEMINUSDSTALPHA; - } - else if (str == "dstcolor" || - str == "dst_color") - { - blend = GS_BLSRC_DSTCOL; - } - else if (str == "srccolor" || - str == "src_color") - { - blend = GS_BLDST_SRCCOL; - } - else if (str == "invdstcolor" || - str == "inv_dst_color") - { - blend = GS_BLSRC_ONEMINUSDSTCOL; - } - else if (str == "invsrccolor" || - str == "inv_src_color") - { - blend = GS_BLDST_ONEMINUSSRCCOL; - } - - return blend; -} - -class CXmlFontShader -{ -public: - CXmlFontShader(CFFont* pFont) - { - m_pFont = pFont; - m_nElement = ELEMENT_UNKNOWN; - m_pEffect = NULL; - m_pPass = NULL; - m_FontTexSize.set(0, 0); - - static const int defaultSlotWidthSize = 16; - static const int defaultSlotHeightSize = 8; - m_SlotSizes.set(defaultSlotWidthSize, defaultSlotHeightSize); - - m_FontSmoothAmount = 0; - m_FontSmoothMethod = FONT_SMOOTH_NONE; - } - - ~CXmlFontShader() - { - } - - void ScanXmlNodesRecursively(XmlNodeRef node) - { - if (!node) - { - return; - } - - FoundElement(node->getTag()); - - for (int i = 0, count = node->getNumAttributes(); i < count; ++i) - { - const char* key = ""; - const char* value = ""; - if (node->getAttributeByIndex(i, &key, &value)) - { - FoundAttribute(key, value); - } - } - - for (int i = 0, count = node->getChildCount(); i < count; ++i) - { - XmlNodeRef child = node->getChild(i); - ScanXmlNodesRecursively(child); - } - } - -private: - // notify methods - void FoundElement(const string& name) - { - //MessageBox(NULL, string("[" + name + "]").c_str(), "FoundElement", MB_OK); - // process the previous element - switch (m_nElement) - { - case ELEMENT_FONT: - { - if (!m_FontTexSize.x || !m_FontTexSize.y) - { - m_FontTexSize.set(512, 512); - } - - bool fontLoaded = m_pFont->Load(m_strFontPath.c_str(), m_FontTexSize.x, m_FontTexSize.y, m_SlotSizes.x, m_SlotSizes.y, TTFFLAG_CREATE(m_FontSmoothMethod, m_FontSmoothAmount), m_SizeRatio); -#if defined(WIN32) || defined(WIN64) - if (!fontLoaded) - { - TCHAR sysFontPath[MAX_PATH]; - if (SUCCEEDED(SHGetFolderPath(0, CSIDL_FONTS, 0, SHGFP_TYPE_DEFAULT, sysFontPath))) - { - const char* pFontPath = m_strFontPath.c_str(); - const char* pFontName = CryStringUtils::FindFileNameInPath(pFontPath); - - string newFontPath(sysFontPath); - newFontPath += "/"; - newFontPath += pFontName; - m_pFont->Load(newFontPath, m_FontTexSize.x, m_FontTexSize.y, m_SlotSizes.x, m_SlotSizes.y, TTFFLAG_CREATE(m_FontSmoothMethod, m_FontSmoothAmount), m_SizeRatio); - } - } -#endif - } - break; - - default: - break; - } - - // Translate the m_nElement name to a define - if (name == "font") - { - m_nElement = ELEMENT_FONT; - } - else if (name == "effect") - { - m_nElement = ELEMENT_EFFECT; - } - else if (name == "effectfile") - { - m_nElement = ELEMENT_EFFECTFILE; - } - else if (name == "pass") - { - m_pPass = NULL; - m_nElement = ELEMENT_PASS; - if (m_pEffect) - { - m_pPass = m_pEffect->AddPass(); - } - } - else if (name == "color") - { - m_nElement = ELEMENT_PASS_COLOR; - } - else if (name == "pos" || - name == "offset") - { - m_nElement = ELEMENT_PASS_POSOFFSET; - } - else if (name == "blend" || - name == "blending") - { - m_nElement = ELEMENT_PASS_BLEND; - } - else - { - m_nElement = ELEMENT_UNKNOWN; - } - } - - void FoundAttribute(const string& name, const string& value) - { - //MessageBox(NULL, string(name + "\n" + value).c_str(), "FoundAttribute", MB_OK); - switch (m_nElement) - { - case ELEMENT_FONT: - if (name == "path") - { - m_strFontPath = value; - } - else if (name == "w") - { - m_FontTexSize.x = (long)atof(value.c_str()); - } - else if (name == "h") - { - m_FontTexSize.y = (long)atof(value.c_str()); - } - else if (name == "widthslots") - { - m_SlotSizes.x = (int)atoi(value.c_str()); - } - else if (name == "heightslots") - { - m_SlotSizes.y = (int)atoi(value.c_str()); - } - else if (name == "sizeratio") - { - m_SizeRatio = static_cast(atof(value.c_str())); - } - else if (name == "smooth") - { - if (value == "blur") - { - m_FontSmoothMethod = FONT_SMOOTH_BLUR; - } - else if (value == "supersample") - { - m_FontSmoothMethod = FONT_SMOOTH_SUPERSAMPLE; - } - else if (value == "none") - { - m_FontSmoothMethod = FONT_SMOOTH_NONE; - } - } - else if (name == "smooth_amount") - { - m_FontSmoothAmount = (long)atof(value.c_str()); - } - break; - - case ELEMENT_EFFECT: - if (name == "name") - { - if (value == "default") - { - m_pEffect = m_pFont->GetDefaultEffect(); - m_pEffect->ClearPasses(); - } - else - { - m_pEffect = m_pFont->AddEffect(value.c_str()); - } - } - break; - - case ELEMENT_EFFECTFILE: - if (name == "path") - { - m_strFontEffectPath = value; - } - break; - - case ELEMENT_PASS_COLOR: - if (!m_pPass) - { - break; - } - if (name == "r") - { - m_pPass->m_color.r = (uint8)((float)atof(value.c_str()) * 255.0f); - } - else if (name == "g") - { - m_pPass->m_color.g = (uint8)((float)atof(value.c_str()) * 255.0f); - } - else if (name == "b") - { - m_pPass->m_color.b = (uint8)((float)atof(value.c_str()) * 255.0f); - } - else if (name == "a") - { - m_pPass->m_color.a = (uint8)((float)atof(value.c_str()) * 255.0f); - } - break; - - case ELEMENT_PASS_POSOFFSET: - if (!m_pPass) - { - break; - } - if (name == "x") - { - m_pPass->m_posOffset.x = (float)atoi(value.c_str()); - } - else if (name == "y") - { - m_pPass->m_posOffset.y = (float)atoi(value.c_str()); - } - break; - - case ELEMENT_PASS_BLEND: - if (!m_pPass) - { - break; - } - if (name == "src") - { - m_pPass->m_blendSrc = GetBlendModeFromString(value, false); - } - else if (name == "dst") - { - m_pPass->m_blendDest = GetBlendModeFromString(value, true); - } - else if (name == "type") - { - if (value == "modulate") - { - m_pPass->m_blendSrc = GS_BLSRC_SRCALPHA; - m_pPass->m_blendDest = GS_BLDST_ONEMINUSSRCALPHA; - } - else if (value == "additive") - { - m_pPass->m_blendSrc = GS_BLSRC_SRCALPHA; - m_pPass->m_blendDest = GS_BLDST_ONE; - } - } - break; - - default: - case ELEMENT_UNKNOWN: - break; - } - } - -public: - CFFont* m_pFont; - - unsigned long m_nElement; - - CFFont::SEffect* m_pEffect; - CFFont::SRenderingPass* m_pPass; - - string m_strFontPath; - string m_strFontEffectPath; - vector2l m_FontTexSize; - Vec2i m_SlotSizes; - float m_SizeRatio = IFFontConstants::defaultSizeRatio; - - int m_FontSmoothMethod; - int m_FontSmoothAmount; -}; - -////////////////////////////////////////////////////////////////////////// -// Main loading function -bool CFFont::Load(const char* pXMLFile) -{ - m_curPath = ""; - if (pXMLFile) - { - m_curPath = PathUtil::GetPath(pXMLFile); - } - - XmlNodeRef root = GetISystem()->LoadXmlFromFile(pXMLFile); - if (!root) - { - return false; - } - - CXmlFontShader xmlfs(this); - xmlfs.ScanXmlNodesRecursively(root); - - // if this was not a valid font XML file then return false - if (!m_pFontTexture || !m_pFontBuffer) - { - return false; - } - - // if there was a font effect file then parse that for effects - if (!xmlfs.m_strFontEffectPath.empty()) - { - XmlNodeRef fontEffectRoot = GetISystem()->LoadXmlFromFile(xmlfs.m_strFontEffectPath.c_str()); - if (!fontEffectRoot) - { - AZ_Warning("Font", false, "Error parsing font file %s, 'effectfile' pathname %s could not be found.", - pXMLFile, xmlfs.m_strFontEffectPath.c_str()); - return false; - } - - if (m_effects.size() > 1 || (m_effects.size() == 1 && (m_effects[0].m_name != "default" || m_effects[0].m_passes.size() > 1))) - { - AZ_Warning("Font", false, "Error parsing font file %s, 'effectfile' and 'effect' cannot both be used in the same font file.", - pXMLFile); - m_effects.clear(); - } - - // parse the font effects file, adding to this font object - CXmlFontShader xmlfsEffect(this); - xmlfsEffect.ScanXmlNodesRecursively(fontEffectRoot); - } - - return true; -} - -#endif - diff --git a/Code/CryEngine/CryFont/FontRenderer.cpp b/Code/CryEngine/CryFont/FontRenderer.cpp deleted file mode 100644 index 2cf160896b..0000000000 --- a/Code/CryEngine/CryFont/FontRenderer.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// -// Purpose: -// - Render a glyph outline into a bitmap using FreeType 2 - -#include "CryFont_precompiled.h" - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "FontRenderer.h" - -#include -#include -#include - -#include - -// Sizes are defined in in 26.6 fixed float format (TT_F26Dot6), where -// 1 unit is 1/64 of a pixel. -static const int fractionalPixelUnits = 64; - -namespace -{ - FT_Int32 GetLoadFlags(CFFont::HintBehavior hintBehavior) - { - switch (hintBehavior) - { - case CFFont::HintBehavior::NoHinting: - { - return FT_LOAD_NO_HINTING; - break; - } - case CFFont::HintBehavior::AutoHint: - { - return FT_LOAD_FORCE_AUTOHINT; - break; - } - } - return FT_LOAD_DEFAULT; - } - - FT_Int32 GetLoadTarget(CFFont::HintStyle hintStyle) - { - if (hintStyle == CFFont::HintStyle::Light) - { - return FT_LOAD_TARGET_LIGHT; - } - - return FT_LOAD_TARGET_NORMAL; - } - - FT_Render_Mode GetRenderMode(CFFont::HintStyle hintStyle) - { - // We use the hint style to drive the render mode also. These should - // usually be correlated with each other for best results, even though - // they could technically be different. - if (hintStyle == CFFont::HintStyle::Light) - { - return FT_RENDER_MODE_LIGHT; - } - - return FT_RENDER_MODE_NORMAL; - } -} - -//------------------------------------------------------------------------------------------------- -CFontRenderer::CFontRenderer() - : m_pLibrary(0) - , m_pFace(0) - , m_pGlyph(0) - , m_fSizeRatio(IFFontConstants::defaultSizeRatio) - , m_pEncoding(FONT_ENCODING_UNICODE) - , m_iGlyphBitmapWidth(0) - , m_iGlyphBitmapHeight(0) -{ -} - -//------------------------------------------------------------------------------------------------- -CFontRenderer::~CFontRenderer() -{ - FT_Done_Face(m_pFace); - ; - FT_Done_FreeType(m_pLibrary); - m_pFace = NULL; - m_pLibrary = NULL; -} - -//------------------------------------------------------------------------------------------------- -int CFontRenderer::LoadFromFile(const string& szFileName) -{ - int iError = FT_Init_FreeType(&m_pLibrary); - - if (iError) - { - return 0; - } - - if (m_pFace) - { - FT_Done_Face(m_pFace); - m_pFace = 0; - } - - iError = FT_New_Face(m_pLibrary, szFileName.c_str(), 0, &m_pFace); - - if (iError) - { - return 0; - } - - SetEncoding(FONT_ENCODING_UNICODE); - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontRenderer::LoadFromMemory(unsigned char* pBuffer, int iBufferSize) -{ - int iError = FT_Init_FreeType(&m_pLibrary); - - if (iError) - { - return 0; - } - - if (m_pFace) - { - FT_Done_Face(m_pFace); - m_pFace = 0; - } - iError = FT_New_Memory_Face(m_pLibrary, pBuffer, iBufferSize, 0, &m_pFace); - - if (iError) - { - return 0; - } - - SetEncoding(FONT_ENCODING_UNICODE); - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontRenderer::Release() -{ - FT_Done_Face(m_pFace); - ; - FT_Done_FreeType(m_pLibrary); - m_pFace = NULL; - m_pLibrary = NULL; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontRenderer::SetGlyphBitmapSize(int iWidth, int iHeight, float sizeRatio) -{ - m_iGlyphBitmapWidth = iWidth; - m_iGlyphBitmapHeight = iHeight; - - // Assign the given scale for texture slots as long as its positive - m_fSizeRatio = sizeRatio > 0.0f ? sizeRatio : m_fSizeRatio; - - FT_Set_Pixel_Sizes(m_pFace, (int)(m_iGlyphBitmapWidth * m_fSizeRatio), (int)(m_iGlyphBitmapHeight * m_fSizeRatio)); - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontRenderer::GetGlyphBitmapSize(int* pWidth, int* pHeight) -{ - if (pWidth) - { - *pWidth = m_iGlyphBitmapWidth; - } - - if (pHeight) - { - *pHeight = m_iGlyphBitmapHeight; - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontRenderer::SetEncoding(FT_Encoding pEncoding) -{ - if (FT_Select_Charmap(m_pFace, pEncoding)) - { - return 0; - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -int CFontRenderer::GetGlyph(CGlyphBitmap* pGlyphBitmap, int* iHoriAdvance, uint8* iGlyphWidth, uint8* iGlyphHeight, AZ::s32& iCharOffsetX, AZ::s32& iCharOffsetY, int iX, int iY, int iCharCode, const CFFont::FontHintParams& fontHintParams) -{ - FT_Int32 loadFlags = GetLoadFlags(fontHintParams.hintBehavior); - loadFlags |= GetLoadTarget(fontHintParams.hintStyle); - - int iError = FT_Load_Char(m_pFace, iCharCode, loadFlags); - - if (iError) - { - return 0; - } - - FT_Render_Mode renderMode = GetRenderMode(fontHintParams.hintStyle); - - m_pGlyph = m_pFace->glyph; - - iError = FT_Render_Glyph(m_pGlyph, renderMode); - - if (iError) - { - return 0; - } - - if (iHoriAdvance) - { - *iHoriAdvance = m_pGlyph->metrics.horiAdvance / fractionalPixelUnits; - } - - if (iGlyphWidth) - { - *iGlyphWidth = m_pGlyph->bitmap.width; - } - - if (iGlyphHeight) - { - *iGlyphHeight = m_pGlyph->bitmap.rows; - } - - unsigned char* pBuffer = pGlyphBitmap->GetBuffer(); - AZ_Assert(pBuffer, "CGlyphBitmap: bad buffer"); - - uint32 dwGlyphWidth = pGlyphBitmap->GetWidth(); - iCharOffsetX = m_pGlyph->bitmap_left; - iCharOffsetY = (static_cast(round(m_iGlyphBitmapHeight * m_fSizeRatio)) - m_pGlyph->bitmap_top); - - const int textureSlotBufferWidth = pGlyphBitmap->GetWidth(); - const int textureSlotBufferHeight = pGlyphBitmap->GetHeight(); - - // might happen if font characters are too big or cache dimenstions in font.xml is too small "" - const bool charWidthFits = iX + m_pGlyph->bitmap.width <= textureSlotBufferWidth; - const bool charHeightFits = iY + m_pGlyph->bitmap.rows <= textureSlotBufferHeight; - const bool charFitsInSlot = charWidthFits && charHeightFits; - AZ_Error("Font", charFitsInSlot, "Character code %d doesn't fit in font texture; check 'sizeRatio' attribute in font XML or adjust this character's sizing in the font.", iCharCode); - - // Since we might be re-rendering/overwriting a glyph that already exists - // in the font texture, clear the contents of this particular slot so no - // artifacts of the previous glyph remain. - pGlyphBitmap->Clear(); - - // Restrict iteration to smallest of either the texture slot or glyph - // bitmap buffer ranges - const int bufferMaxIterWidth = AZStd::GetMin(textureSlotBufferWidth, m_pGlyph->bitmap.width); - const int bufferMaxIterHeight = AZStd::GetMin(textureSlotBufferHeight, m_pGlyph->bitmap.rows); - - for (int i = 0; i < bufferMaxIterHeight; i++) - { - int iNewY = i + iY; - - for (int j = 0; j < bufferMaxIterWidth; j++) - { - unsigned char cColor = m_pGlyph->bitmap.buffer[(i * m_pGlyph->bitmap.width) + j]; - int iOffset = iNewY * dwGlyphWidth + iX + j; - - if (iOffset >= (int)dwGlyphWidth * m_iGlyphBitmapHeight) - { - continue; - } - - pBuffer[iOffset] = cColor; - // pBuffer[iOffset] = cColor/2+32; // debug - visualize character in a block - } - } - - return 1; -} - -int CFontRenderer::GetGlyphScaled([[maybe_unused]] CGlyphBitmap* pGlyphBitmap, [[maybe_unused]] int* iGlyphWidth, [[maybe_unused]] int* iGlyphHeight, [[maybe_unused]] int iX, [[maybe_unused]] int iY, [[maybe_unused]] float fScaleX, [[maybe_unused]] float fScaleY, [[maybe_unused]] int iCharCode) -{ - return 1; -} - -Vec2 CFontRenderer::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph) -{ - FT_Vector kerningOffsets; - kerningOffsets.x = kerningOffsets.y = 0; - - if (FT_HAS_KERNING(m_pFace)) - { - const FT_UInt leftGlyphIndex = FT_Get_Char_Index(m_pFace, leftGlyph); - const FT_UInt rightGlyphIndex = FT_Get_Char_Index(m_pFace, rightGlyph); - - [[maybe_unused]] FT_Error ftError = FT_Get_Kerning(m_pFace, leftGlyphIndex, rightGlyphIndex, FT_KERNING_DEFAULT, &kerningOffsets); - -#if !defined(_RELEASE) - if (0 != ftError) - { - string warnMsg; - warnMsg.Format("FT_Get_Kerning returned %d", ftError); - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, warnMsg.c_str()); - } -#endif - } - - return Vec2(azlossy_cast(kerningOffsets.x / fractionalPixelUnits), azlossy_cast(kerningOffsets.y / fractionalPixelUnits)); -} - -float CFontRenderer::GetAscenderToHeightRatio() -{ - return (static_cast(m_pFace->ascender) / static_cast(m_pFace->height)); -} - -//------------------------------------------------------------------------------------------------- -/* -int CFontRenderer::FT_GetIndex(int iCharCode) -{ -if (iCharCode < 256) -{ -int iIndex = 0; -int iUnicode; - -// try unicode -for (int i = 0; i < m_pFace->num_charmaps; i++) -{ -if ((m_pFace->charmaps[i]->platform_id == 3) && (m_pFace->charmaps[i]->encoding_id == 1)) -{ -iUnicode = i; - -FT_Set_Charmap(m_pFace, m_pFace->charmaps[i]); - -iIndex = FT_Get_Char_Index(m_pFace, iCharCode); - -// not unicode, try ascii -if (iIndex == 0) -{ -for (int i = 0; i < m_pFace->num_charmaps; i++) -{ -if ((m_pFace->charmaps[i]->platform_id == 0) && (m_pFace->charmaps[i]->encoding_id == 0)) -{ -FT_Set_Charmap(m_pFace, m_pFace->charmaps[i]); - -iIndex = FT_Get_Char_Index(m_pFace, iCharCode); - -// not ascii either, reuse unicode default "missing char" -if (iIndex == 0) -{ -FT_Set_Charmap(m_pFace, m_pFace->charmaps[iUnicode]); - -return FT_Get_Char_Index(m_pFace, iCharCode); -} -} -} -} - -return iIndex; -} -} - -return 0; -} -else -{ -for (int i = 0; i < m_pFace->num_charmaps; i++) -{ -if ((m_pFace->charmaps[i]->platform_id == 3) && (m_pFace->charmaps[i]->encoding_id == 1)) -{ -FT_Set_Charmap(m_pFace, m_pFace->charmaps[i]); - -return FT_Get_Char_Index(m_pFace, iCharCode); -} -} - -return 0; -} - -return 0; -} -*/ - -#endif // #if !defined(USE_NULLFONT_ALWAYS) diff --git a/Code/CryEngine/CryFont/FontRenderer.h b/Code/CryEngine/CryFont/FontRenderer.h deleted file mode 100644 index aca26a1e04..0000000000 --- a/Code/CryEngine/CryFont/FontRenderer.h +++ /dev/null @@ -1,113 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Render a glyph outline into a bitmap using FreeType 2 - -#if !defined(USE_NULLFONT_ALWAYS) - -#ifndef CRYINCLUDE_CRYFONT_FONTRENDERER_H -#define CRYINCLUDE_CRYFONT_FONTRENDERER_H -#pragma once - - - -#include "GlyphBitmap.h" -#include "FFont.h" -#include -#pragma push_macro("generic") -#define generic GenericFromFreeTypeLibrary -#include -#undef generic -#pragma pop_macro("generic") - - -// Corresponds to the Unicode character set. This value covers all versions of the Unicode repertoire, -// including ASCII and Latin-1. Most fonts include a Unicode charmap, but not all of them. -#define FONT_ENCODING_UNICODE (FT_ENCODING_UNICODE) - -// Corresponds to the Microsoft Symbol encoding, used to encode mathematical symbols in the 32..255 character code range. -// For more information, see `http://www.ceviz.net/symbol.htm'. -#define FONT_ENCODING_SYMBOL (FT_ENCODING_MS_SYMBOL) - -// Corresponds to Microsoft's Japanese SJIS encoding. -// More info at `http://langsupport.japanreference.com/encoding.shtml'. See note on multi-byte encodings below. -#define FONT_ENCODING_SJIS (FT_ENCODING_MS_SJIS) - -// Corresponds to the encoding system for Simplified Chinese, as used in China. Only found in some TrueType fonts. -#define FONT_ENCODING_GB2312 (FT_ENCODING_MS_GB2312) - -// Corresponds to the encoding system for Traditional Chinese, as used in Taiwan and Hong Kong. Only found in some TrueType fonts. -#define FONT_ENCODING_BIG5 (FT_ENCODING_MS_BIG5) - -// Corresponds to the Korean encoding system known as Wansung. -// This is a Microsoft encoding that is only found in some TrueType fonts. -// For more information, see `http://www.microsoft.com/typography/unicode/949.txt'. -#define FONT_ENCODING_WANSUNG (FT_ENCODING_MS_WANSUNG) - -// The Korean standard character set (KS C-5601-1992), which corresponds to Windows code page 1361. -// This character set includes all possible Hangeul character combinations. Only found on some rare TrueType fonts. -#define FONT_ENCODING_JOHAB (FT_ENCODING_MS_JOHAB) - - - -//------------------------------------------------------------------------------------ -class CFontRenderer -{ -public: - - CFontRenderer(); - ~CFontRenderer(); - - int LoadFromFile(const string& szFileName); - int LoadFromMemory(unsigned char* pBuffer, int iBufferSize); - int Release(); - - int SetGlyphBitmapSize(int iWidth, int iHeight, float sizeRatio); - int GetGlyphBitmapSize(int* pWidth, int* pHeight); - - int SetSizeRatio(float fSizeRatio) { m_fSizeRatio = fSizeRatio; return 1; }; - float GetSizeRatio() { return m_fSizeRatio; }; - - int SetEncoding(FT_Encoding pEncoding); - FT_Encoding GetEncoding() { return m_pEncoding; }; - - //! Populates the given pGlyphBitmap's buffer from the FreeType bitmap buffer - //! \param iCharCode Used as a character index to retrieve the FreeType glyph and it's associated bitmap buffer for the character - //! \param pGlyphBitmap The FreeType glyph buffer is essentially copied into this CGlyphBitmap buffer - int GetGlyph(CGlyphBitmap* pGlyphBitmap, int* iHoriAdvance, uint8* iGlyphWidth, uint8* iGlyphHeight, AZ::s32& iCharOffsetX, AZ::s32& iCharOffsetY, int iX, int iY, int iCharCode, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams()); - int GetGlyphScaled(CGlyphBitmap* pGlyphBitmap, int* iGlyphWidth, int* iGlyphHeight, int iX, int iY, float fScaleX, float fScaleY, int iCharCode); - - void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {} - - bool GetMonospaced() const { return FT_IS_FIXED_WIDTH(m_pFace) != 0; } - - Vec2 GetKerning(uint32_t leftGlyph, uint32_t rightGlyph); - - float GetAscenderToHeightRatio(); - -private: - - FT_Library m_pLibrary; - FT_Face m_pFace; - FT_GlyphSlot m_pGlyph; - float m_fSizeRatio; - - FT_Encoding m_pEncoding; - - int m_iGlyphBitmapWidth; - int m_iGlyphBitmapHeight; -}; - -#endif // CRYINCLUDE_CRYFONT_FONTRENDERER_H - -#endif // #if !defined(USE_NULLFONT_ALWAYS) diff --git a/Code/CryEngine/CryFont/FontTexture.cpp b/Code/CryEngine/CryFont/FontTexture.cpp deleted file mode 100644 index 8db7484d59..0000000000 --- a/Code/CryEngine/CryFont/FontTexture.cpp +++ /dev/null @@ -1,633 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Purpose: -// - Create and update a texture with the most recently used glyphs - -#include "CryFont_precompiled.h" - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "FontTexture.h" -#include "UnicodeIterator.h" -#include - -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#undef GetCharWidth -#endif - -//------------------------------------------------------------------------------------------------- -CFontTexture::CFontTexture() - : m_wSlotUsage(1) - , m_iWidth(0) - , m_iHeight(0) - , m_fInvWidth(0.0f) - , m_fInvHeight(0.0f) - , m_iCellWidth(0) - , m_iCellHeight(0) - , m_fTextureCellWidth(0) - , m_fTextureCellHeight(0) - , m_iWidthCellCount(0) - , m_iHeightCellCount(0) - , m_nTextureSlotCount(0) - , m_pBuffer(0) - , m_iSmoothMethod(FONT_SMOOTH_NONE) - , m_iSmoothAmount(FONT_SMOOTH_AMOUNT_NONE) -{ -} - -//------------------------------------------------------------------------------------------------- -CFontTexture::~CFontTexture() -{ - Release(); -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::CreateFromFile(const string& szFileName, int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCellCount, int iHeightCellCount) -{ - if (!m_pGlyphCache.LoadFontFromFile(szFileName)) - { - Release(); - - return 0; - } - - if (!Create(iWidth, iHeight, iSmoothMethod, iSmoothAmount, iWidthCellCount, iHeightCellCount)) - { - return 0; - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::CreateFromMemory(unsigned char* pFileData, int iDataSize, int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCellCount, int iHeightCellCount, float sizeRatio) -{ - if (!m_pGlyphCache.LoadFontFromMemory(pFileData, iDataSize)) - { - Release(); - - return 0; - } - - if (!Create(iWidth, iHeight, iSmoothMethod, iSmoothAmount, iWidthCellCount, iHeightCellCount, sizeRatio)) - { - return 0; - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::Create(int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCellCount, int iHeightCellCount, float sizeRatio) -{ - m_pBuffer = new FONT_TEXTURE_TYPE[iWidth * iHeight]; - if (!m_pBuffer) - { - return 0; - } - - memset(m_pBuffer, 0, iWidth * iHeight * sizeof(FONT_TEXTURE_TYPE)); - - if (!(iWidthCellCount * iHeightCellCount)) - { - return 0; - } - - m_iWidth = iWidth; - m_iHeight = iHeight; - m_fInvWidth = 1.0f / (float)iWidth; - m_fInvHeight = 1.0f / (float)iHeight; - - m_iWidthCellCount = iWidthCellCount; - m_iHeightCellCount = iHeightCellCount; - m_nTextureSlotCount = m_iWidthCellCount * m_iHeightCellCount; - - m_iSmoothMethod = iSmoothMethod; - m_iSmoothAmount = iSmoothAmount; - - m_iCellWidth = m_iWidth / m_iWidthCellCount; - m_iCellHeight = m_iHeight / m_iHeightCellCount; - - m_fTextureCellWidth = m_iCellWidth * m_fInvWidth; - m_fTextureCellHeight = m_iCellHeight * m_fInvHeight; - - if (!m_pGlyphCache.Create(FONT_GLYPH_CACHE_SIZE, m_iCellWidth, m_iCellHeight, iSmoothMethod, iSmoothAmount, sizeRatio)) - { - Release(); - - return 0; - } - - if (!CreateSlotList(m_nTextureSlotCount)) - { - Release(); - - return 0; - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::Release() -{ - delete[] m_pBuffer; - m_pBuffer = 0; - - ReleaseSlotList(); - - m_pSlotTable.clear(); - - m_pGlyphCache.Release(); - - m_iWidthCellCount = 0; - m_iHeightCellCount = 0; - m_nTextureSlotCount = 0; - - m_iWidth = 0; - m_iHeight = 0; - m_fInvWidth = 0.0f; - m_fInvHeight = 0.0f; - - m_iCellWidth = 0; - m_iCellHeight = 0; - - m_iSmoothMethod = 0; - m_iSmoothAmount = 0; - - m_fTextureCellWidth = 0.0f; - m_fTextureCellHeight = 0.0f; - - m_wSlotUsage = 1; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -uint32 CFontTexture::GetSlotChar(int iSlot) const -{ - return m_pSlotList[iSlot]->cCurrentChar; -} - -//------------------------------------------------------------------------------------------------- -CTextureSlot* CFontTexture::GetCharSlot(uint32 cChar, const Vec2i& glyphSize) -{ - CryFont::FontTexture::CTextureSlotKey slotKey = GetTextureSlotKey(cChar, glyphSize); - CTextureSlotTableItor pItor = m_pSlotTable.find(slotKey); - - if (pItor != m_pSlotTable.end()) - { - return pItor->second; - } - - return 0; -} - -//------------------------------------------------------------------------------------------------- -CTextureSlot* CFontTexture::GetLRUSlot() -{ - uint16 wMaxSlotAge = 0; - CTextureSlot* pLRUSlot = 0; - CTextureSlot* pSlot; - - CTextureSlotListItor pItor = m_pSlotList.begin(); - - while (pItor != m_pSlotList.end()) - { - pSlot = *pItor; - - if (pSlot->wSlotUsage == 0) - { - return pSlot; - } - else - { - uint16 slotAge = m_wSlotUsage - pSlot->wSlotUsage; - if (slotAge > wMaxSlotAge) - { - pLRUSlot = pSlot; - wMaxSlotAge = slotAge; - } - } - - ++pItor; - } - - return pLRUSlot; -} - -//------------------------------------------------------------------------------------------------- -CTextureSlot* CFontTexture::GetMRUSlot() -{ - uint16 wMinSlotAge = 0xFFFF; - CTextureSlot* pMRUSlot = 0; - CTextureSlot* pSlot; - - CTextureSlotListItor pItor = m_pSlotList.begin(); - - while (pItor != m_pSlotList.end()) - { - pSlot = *pItor; - - if (pSlot->wSlotUsage != 0) - { - uint16 slotAge = m_wSlotUsage - pSlot->wSlotUsage; - if (slotAge > wMinSlotAge) - { - pMRUSlot = pSlot; - wMinSlotAge = slotAge; - } - } - - ++pItor; - } - - return pMRUSlot; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::PreCacheString(const char* szString, int* pUpdated, float sizeRatio, const Vec2i& glyphSize, const CFFont::FontHintParams& fontHintParams) -{ - Vec2i clampedGlyphSize = ClampGlyphSize(glyphSize, m_iCellWidth, m_iCellHeight); - - uint16 wSlotUsage = m_wSlotUsage++; - int iUpdated = 0; - - uint32 cChar; - for (Unicode::CIterator it(szString); *it; ++it) - { - cChar = *it; - CTextureSlot* pSlot = GetCharSlot(cChar, clampedGlyphSize); - - if (!pSlot) - { - pSlot = GetLRUSlot(); - - if (!pSlot) - { - return 0; - } - - if (!UpdateSlot(pSlot->iTextureSlot, wSlotUsage, cChar, sizeRatio, clampedGlyphSize, fontHintParams)) - { - return 0; - } - - ++iUpdated; - } - else - { - pSlot->wSlotUsage = wSlotUsage; - } - } - - if (pUpdated) - { - *pUpdated = iUpdated; - } - - if (iUpdated) - { - return 1; - } - - return 2; -} - -//------------------------------------------------------------------------------------------------- -void CFontTexture::GetTextureCoord(CTextureSlot* pSlot, float texCoords[4], - int& iCharSizeX, int& iCharSizeY, int& iCharOffsetX, int& iCharOffsetY, - const Vec2i& glyphSize) const -{ - if (!pSlot) - { - return; // expected behavior - } - - // Re-rendered glyphs are stored at smaller sizes than glyphs rendered at - // the (maximum) font texture slot resolution. We scale the returned width - // and height of the (actual) rendered glyph sizes so its transparent to - // callers that the glyph is actually smaller (from being re-rendered). - const float requestSizeWidthScale = AZ::GetMin(1.0f, GetRequestSizeWidthScale(glyphSize)); - const float requestSizeHeightScale = AZ::GetMin(1.0f, GetRequestSizeHeightScale(glyphSize)); - const float invRequestSizeWidthScale = 1.0f / requestSizeWidthScale; - const float invRequestSizeHeightScale = 1.0f / requestSizeHeightScale; - - // The inverse scale grows as the glyph size decreases. Once the glyph size - // reaches the font texture's max slot dimensions, we cap width/height scale - // since the text draw context will apply normal (as opposed to re-rendered) - // scaling. - int iChWidth = static_cast(pSlot->iCharWidth * invRequestSizeWidthScale); - int iChHeight = static_cast(pSlot->iCharHeight * invRequestSizeHeightScale); - - float slotCoord0 = pSlot->vTexCoord[0]; - float slotCoord1 = pSlot->vTexCoord[1]; - texCoords[0] = slotCoord0 - m_fInvWidth; // extra pixel for nicer bilinear filter - texCoords[1] = slotCoord1 - m_fInvHeight; // extra pixel for nicer bilinear filter - - // UV coordinates also must be scaled relative to the re-rendered glyph size - // as well. Width scale must be capped at 1.0f since glyph can't grow - // beyond the slot's resolution. - texCoords[2] = slotCoord0 + (((float)iChWidth * m_fInvWidth) * requestSizeWidthScale); - texCoords[3] = slotCoord1 + (((float)iChHeight * m_fInvHeight) * requestSizeHeightScale); - - iCharSizeX = iChWidth + 1; // extra pixel for nicer bilinear filter - iCharSizeY = iChHeight + 1; // extra pixel for nicer bilinear filter - - // Offsets are scaled accordingly when the rendered glyph size is smaller - // than the glyph/slot dimensions, but otherwise we expect the text draw - // context to apply scaling beyond that. - iCharOffsetX = static_cast(pSlot->iCharOffsetX * invRequestSizeWidthScale); - iCharOffsetY = static_cast(pSlot->iCharOffsetY * invRequestSizeHeightScale); -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::GetCharacterWidth(uint32 cChar) const -{ - CTextureSlotTableItorConst pItor = m_pSlotTable.find(GetTextureSlotKey(cChar)); - - if (pItor == m_pSlotTable.end()) - { - return 0; - } - - const CTextureSlot& rSlot = *pItor->second; - - // For proportional fonts, add one pixel of spacing for aesthetic reasons - int proportionalOffset = GetMonospaced() ? 0 : 1; - - return rSlot.iCharWidth + proportionalOffset; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::GetHorizontalAdvance(uint32 cChar, const Vec2i& glyphSize) const -{ - CTextureSlotTableItorConst pItor = m_pSlotTable.find(GetTextureSlotKey(cChar, glyphSize)); - - if (pItor == m_pSlotTable.end()) - { - return 0; - } - - const CTextureSlot& rSlot = *pItor->second; - - // Re-rendered glyphs are stored at smaller sizes than glyphs rendered at - // the (maximum) font texture slot resolution. We scale the returned width - // and height of the (actual) rendered glyph sizes so its transparent to - // callers that the glyph is actually smaller (from being re-rendered). - const float requestSizeWidthScale = GetRequestSizeWidthScale(glyphSize); - const float invRequestSizeWidthScale = 1.0f / requestSizeWidthScale; - - // Only multiply by 1.0f when glyphsize is greater than cell width because we assume that callers - // will use the font draw text context to scale the value appropriately. - return static_cast(rSlot.iHoriAdvance * AZ::GetMax(1.0f, invRequestSizeWidthScale)); -} - -//------------------------------------------------------------------------------------------------- -/* -int CFontTexture::GetCharHeightByChar(wchar_t cChar) -{ -CTextureSlotTableItor pItor = m_pSlotTable.find(cChar); - -if (pItor != m_pSlotTable.end()) -{ -return pItor->second->iCharHeight; -} - -return 0; -} -*/ - -//------------------------------------------------------------------------------------------------- -int CFontTexture::WriteToFile([[maybe_unused]] const string& szFileName) -{ -#ifdef WIN32 - AZ::IO::FileIOStream outputFile(szFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary); - - if (!outputFile.IsOpen()) - { - return 0; - } - - BITMAPFILEHEADER pHeader; - BITMAPINFOHEADER pInfoHeader; - - memset(&pHeader, 0, sizeof(BITMAPFILEHEADER)); - memset(&pInfoHeader, 0, sizeof(BITMAPINFOHEADER)); - - pHeader.bfType = 0x4D42; - pHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + m_iWidth * m_iHeight * 3; - pHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); - - pInfoHeader.biSize = sizeof(BITMAPINFOHEADER); - pInfoHeader.biWidth = m_iWidth; - pInfoHeader.biHeight = m_iHeight; - pInfoHeader.biPlanes = 1; - pInfoHeader.biBitCount = 24; - pInfoHeader.biCompression = 0; - pInfoHeader.biSizeImage = m_iWidth * m_iHeight * 3; - - outputFile.Write(sizeof(BITMAPFILEHEADER), &pHeader); - outputFile.Write(sizeof(BITMAPINFOHEADER), &pInfoHeader); - - unsigned char cRGB[3]; - - for (int i = m_iHeight - 1; i >= 0; i--) - { - for (int j = 0; j < m_iWidth; j++) - { - cRGB[0] = m_pBuffer[(i * m_iWidth) + j]; - cRGB[1] = *cRGB; - - cRGB[2] = *cRGB; - - outputFile.Write(3, cRGB); - } - } - -#endif - return 1; -} - -//------------------------------------------------------------------------------------------------- -Vec2 CFontTexture::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph) -{ - return m_pGlyphCache.GetKerning(leftGlyph, rightGlyph); -} - -//------------------------------------------------------------------------------------------------- -float CFontTexture::GetAscenderToHeightRatio() -{ - return m_pGlyphCache.GetAscenderToHeightRatio(); -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::CreateSlotList(int iListSize) -{ - int y, x; - - for (int i = 0; i < iListSize; i++) - { - CTextureSlot* pTextureSlot = new CTextureSlot; - - if (!pTextureSlot) - { - return 0; - } - - pTextureSlot->iTextureSlot = i; - pTextureSlot->Reset(); - - y = i / m_iWidthCellCount; - x = i % m_iWidthCellCount; - - pTextureSlot->vTexCoord[0] = (float)(x * m_fTextureCellWidth) + (0.5f / (float)m_iWidth); - pTextureSlot->vTexCoord[1] = (float)(y * m_fTextureCellHeight) + (0.5f / (float)m_iHeight); - - m_pSlotList.push_back(pTextureSlot); - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::ReleaseSlotList() -{ - CTextureSlotListItor pItor = m_pSlotList.begin(); - - while (pItor != m_pSlotList.end()) - { - delete (*pItor); - - pItor = m_pSlotList.erase(pItor); - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::UpdateSlot(int iSlot, uint16 wSlotUsage, uint32 cChar, float sizeRatio, const Vec2i& glyphSize, const CFFont::FontHintParams& fontHintParams) -{ - CTextureSlot* pSlot = m_pSlotList[iSlot]; - - if (!pSlot) - { - return 0; - } - - CTextureSlotTableItor pItor = m_pSlotTable.find(GetTextureSlotKey(pSlot->cCurrentChar, pSlot->glyphSize)); - - if (pItor != m_pSlotTable.end()) - { - m_pSlotTable.erase(pItor); - } - m_pSlotTable.insert(AZStd::pair(GetTextureSlotKey(cChar, glyphSize), pSlot)); - pSlot->glyphSize = glyphSize; - pSlot->wSlotUsage = wSlotUsage; - pSlot->cCurrentChar = cChar; - - int iWidth = 0; - int iHeight = 0; - - // blit the char glyph into the texture - int x = pSlot->iTextureSlot % m_iWidthCellCount; - int y = pSlot->iTextureSlot / m_iWidthCellCount; - - CGlyphBitmap* pGlyphBitmap; - - if (glyphSize.x > 0 && glyphSize.y > 0) - { - m_pGlyphCache.SetGlyphBitmapSize(glyphSize.x, glyphSize.y, sizeRatio); - } - - if (!m_pGlyphCache.GetGlyph(&pGlyphBitmap, &pSlot->iHoriAdvance, &iWidth, &iHeight, pSlot->iCharOffsetX, pSlot->iCharOffsetY, cChar, glyphSize, fontHintParams)) - { - return 0; - } - - pSlot->iCharWidth = iWidth; - pSlot->iCharHeight = iHeight; - - // Add a pixel along width and height to avoid artifacts being rendered - // from a previous glyph in this slot due to bilinear filtering. The source - // glyph bitmap buffer is presumed to be cleared prior to FreeType rendering - // to the bitmap. - const int blitWidth = AZ::GetMin(iWidth + 1, m_iCellWidth); - const int blitHeight = AZ::GetMin(iHeight + 1, m_iCellHeight); - - pGlyphBitmap->BlitTo8(m_pBuffer, 0, 0, - blitWidth, blitHeight, x * m_iCellWidth, y * m_iCellHeight, m_iWidth); - - return 1; -} - -//------------------------------------------------------------------------------------------------- -void CFontTexture::CreateGradientSlot() -{ - CTextureSlot* pSlot = GetGradientSlot(); - assert(pSlot->cCurrentChar == (uint32)~0); // 0 needs to be unused spot - - pSlot->Reset(); - pSlot->iCharWidth = m_iCellWidth - 2; - pSlot->iCharHeight = m_iCellHeight - 2; - pSlot->SetNotReusable(); - - int x = pSlot->iTextureSlot % m_iWidthCellCount; - int y = pSlot->iTextureSlot / m_iWidthCellCount; - - assert(sizeof(*m_pBuffer) == sizeof(uint8)); - uint8* pBuffer = &m_pBuffer[x * m_iCellWidth + y * m_iCellHeight * m_iWidth]; - - for (uint32 dwY = 0; dwY < pSlot->iCharHeight; ++dwY) - { - for (uint32 dwX = 0; dwX < pSlot->iCharWidth; ++dwX) - { - pBuffer[dwX + dwY * m_iWidth] = dwY * 255 / (pSlot->iCharHeight - 1); - } - } -} - -//------------------------------------------------------------------------------------------------- -CTextureSlot* CFontTexture::GetGradientSlot() -{ - return m_pSlotList[0]; -} - -//------------------------------------------------------------------------------------------------- -CryFont::FontTexture::CTextureSlotKey CFontTexture::GetTextureSlotKey(uint32 cChar, const Vec2i& glyphSize) const -{ - const Vec2i clampedGlyphSize(ClampGlyphSize(glyphSize, m_iCellWidth, m_iCellHeight)); - return CryFont::FontTexture::CTextureSlotKey(clampedGlyphSize, cChar); -} - -Vec2i CFontTexture::ClampGlyphSize(const Vec2i& glyphSize, int cellWidth, int cellHeight) -{ - const Vec2i maxCellDimensions(cellWidth, cellHeight); - Vec2i clampedGlyphSize(glyphSize); - - const bool hasZeroDimension = glyphSize.x == 0 || glyphSize.y == 0; - const bool isDefaultSize = glyphSize == CCryFont::defaultGlyphSize; - const bool exceedsDimensions = glyphSize.x > cellWidth || glyphSize.y > cellHeight; - const bool useMaxCellDimension = hasZeroDimension || isDefaultSize || exceedsDimensions; - if (useMaxCellDimension) - { - clampedGlyphSize = maxCellDimensions; - } - - return clampedGlyphSize; -} - -#endif // #if !defined(USE_NULLFONT_ALWAYS) diff --git a/Code/CryEngine/CryFont/FontTexture.h b/Code/CryEngine/CryFont/FontTexture.h deleted file mode 100644 index 45d0403f47..0000000000 --- a/Code/CryEngine/CryFont/FontTexture.h +++ /dev/null @@ -1,301 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_CRYFONT_FONTTEXTURE_H -#define CRYINCLUDE_CRYFONT_FONTTEXTURE_H -#pragma once - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "GlyphCache.h" -#include "GlyphBitmap.h" -#include "CryFont.h" -#include "FFont.h" - -typedef uint8 FONT_TEXTURE_TYPE; - -// the number of slots in the glyph cache -// each slot ocupies ((glyph_bitmap_width * glyph_bitmap_height) + 24) bytes -#define FONT_GLYPH_CACHE_SIZE (1) - -// the glyph spacing in font texels between characters in proportional font mode (more correct would be to take the value in the character) -#define FONT_GLYPH_PROP_SPACING (1) - -// the size of a rendered space, this value gets multiplied by the default characted width -#define FONT_SPACE_SIZE (0.5f) - -// don't draw this char (used to avoid drawing color codes) -#define FONT_NOT_DRAWABLE_CHAR (0xffff) - -// smoothing methods -#define FONT_SMOOTH_NONE 0 -#define FONT_SMOOTH_BLUR 1 -#define FONT_SMOOTH_SUPERSAMPLE 2 - -// smoothing amounts -#define FONT_SMOOTH_AMOUNT_NONE 0 -#define FONT_SMOOTH_AMOUNT_2X 1 -#define FONT_SMOOTH_AMOUNT_4X 2 - -//! Stores glyph meta-data read from the font (FreeType). -//! -//! \sa CCacheSlot -typedef struct CTextureSlot -{ - Vec2i glyphSize = CCryFont::defaultGlyphSize; //!< Size of the rendered glyph stored in the font texture - uint16 wSlotUsage; //!< For LRU strategy, 0xffff is never released - uint32 cCurrentChar; //!< ~0 if not used for characters - int iTextureSlot; - int iHoriAdvance; //!< Advance width. See FT_Glyph_Metrics::horiAdvance. - float vTexCoord[2]; //!< Character position in the texture (not yet half texel corrected) - uint8 iCharWidth; //!< Glyph width (in pixel) - uint8 iCharHeight; //!< Glyph height (in pixel) - AZ::s32 iCharOffsetX; //!< Glyph's left-side bearing (in pixels). See FT_GlyphSlotRec::bitmap_left. - AZ::s32 iCharOffsetY; //!< Glyph's top bearing (in pixels). See FT_GlyphSlotRec::bitmap_top. - - void Reset() - { - wSlotUsage = 0; - cCurrentChar = ~0; - iHoriAdvance = 0; - iCharWidth = 0; - iCharHeight = 0; - iCharOffsetX = 0; - iCharOffsetY = 0; - } - - void SetNotReusable() - { - wSlotUsage = 0xffff; - } - - void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {} -} CTextureSlot; - - -typedef std::vector CTextureSlotList; -typedef std::vector::iterator CTextureSlotListItor; - -namespace CryFont -{ - namespace FontTexture - { - //! Height and width pair for glyph size mapping - typedef Vec2i CGlyphSizeType; - - //! Pair for mapping a height and width size to a UTF32 character/glyph - typedef AZStd::pair CTextureSlotKey; - - //! Hasher for texture slot table keys (glyphsize-char code pair) - //! - //! Instead of creating our own custom hash, the types are broken down to their - //! native types (ints) and passed to existing hashes that handle those types. - struct HashTextureSlotTableKey - { - typedef CTextureSlotKey ArgumentType; - typedef AZStd::size_t ResultType; - typedef AZStd::pair Int32Pair; - typedef AZStd::pair Int32PairU32Pair; - ResultType operator()(const ArgumentType& value) const - { - // Utiliize existing hash function for pairs of ints - AZStd::hash pairHash; - return pairHash(Int32PairU32Pair(Int32Pair(value.first.x, value.first.y), value.second)); - } - }; - } -} - -//! Maps size-speicifc UTF32 glyphs to their corresponding texture slots -typedef AZStd::unordered_map CTextureSlotTable; - -typedef CTextureSlotTable::iterator CTextureSlotTableItor; -typedef CTextureSlotTable::const_iterator CTextureSlotTableItorConst; - -#ifdef WIN64 -#undef GetCharWidth -#undef GetCharHeight -#endif - -//! Stores the glyphs of a font within a single texture. -//! -//! The texture resolution is configurable, as is the number of slots within -//! the texture. -//! -//! A texture slot contains a single glyph within the font and are uniform -//! size throughout the font texture (each slot occupies the same size -//! regardless of the size of a glyph being stored, so a '.' occupies the -//! same amount of space as a 'W', for example). -//! -//! Font glyph buffers are read from FreeType and copied into the texture. -//! -//! \sa CTextureSlot, CFontRenderer -class CFontTexture -{ -public: - CFontTexture(); - ~CFontTexture(); - - int CreateFromFile(const string& szFileName, int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCharCount = 16, int iHeightCharCount = 16); - - //! Default texture slot width/height is 16x8 slots, allowing for 128 glyphs to be stored in the font texture. This was - //! previously 16x16, allowing 256 glyphs to be stored. For reference, there are 95 printable ASCII characters, so by - //! reducing the number of slots, the height of the font texture can be halved (for some nice memory savings). We may - //! want to make this configurable in the font XML (especially for languages with a large number of printable chars). - int CreateFromMemory(unsigned char* pFileData, int iDataSize, int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCharCount, int iHeightCharCount, float sizeRatio); - - int Create(int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCharCount = 16, int iHeightCharCount = 16, float sizeRatio = IFFontConstants::defaultSizeRatio); - int Release(); - - int SetEncoding(FT_Encoding pEncoding) { return m_pGlyphCache.SetEncoding(pEncoding); } - FT_Encoding GetEncoding() { return m_pGlyphCache.GetEncoding(); } - - int GetCellWidth() { return m_iCellWidth; } - int GetCellHeight() { return m_iCellHeight; } - - int GetWidth() { return m_iWidth; } - int GetHeight() { return m_iHeight; } - - int GetWidthCellCount() { return m_iWidthCellCount; } - int GetHeightCellCount() { return m_iHeightCellCount; } - - float GetTextureCellWidth() { return m_fTextureCellWidth; } - float GetTextureCellHeight() { return m_fTextureCellHeight; } - - FONT_TEXTURE_TYPE* GetBuffer() { return m_pBuffer; } - - uint32 GetSlotChar(int iSlot) const; - CTextureSlot* GetCharSlot(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize); - CTextureSlot* GetGradientSlot(); - - CTextureSlot* GetLRUSlot(); - CTextureSlot* GetMRUSlot(); - - //! Returns 1 if texture updated, returns 2 if texture not updated, returns 0 on error - //! \param szString A string of glyphs (UTF8) to added to the font texture (if they don't already exist in the font texture) - //! \param pUpdated is the number of slots updated - //! \param sizeRatio A sizing scale that gets applied to all glyphs sizes before they are stored in the font texture. - //! \param glyphSize The resolution to render the glyphs in szString at. - //! \param glyphFlags Controls hinting behavior for glyphs rendered to the font texture. - int PreCacheString(const char* szString, int* pUpdated = 0, float sizeRatio = IFFontConstants::defaultSizeRatio, const Vec2i& glyphSize = CCryFont::defaultGlyphSize, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams()); - // Arguments: - // pSlot - function does nothing if this pointer is 0 - void GetTextureCoord(CTextureSlot * pSlot, float texCoords[4], int& iCharSizeX, int& iCharSizeY, int& iCharOffsetX, int& iCharOffsetY, const Vec2i& glyphSize = CCryFont::defaultGlyphSize) const; - int GetCharacterWidth(uint32 cChar) const; - //! Gets the horizontal advance for the given glyph/char. - //! \param cChar The glyph (UTF32) to get the horizontal advance for. - //! \param glyphSize The rendered size of the glyph to get the advance for (the same glyph could be stored in the font texture at multiple sizes). - int GetHorizontalAdvance(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize) const; - // int GetCharHeightByChar(wchar_t cChar); - - // useful for special feature rendering interleaved with fonts (e.g. box behind the text) - void CreateGradientSlot(); - - int WriteToFile(const string& szFileName); - - void GetMemoryUsage(ICrySizer* pSizer) const - { - pSizer->AddObject(this, sizeof(*this)); - pSizer->AddObject(m_pGlyphCache); - pSizer->AddObject(m_pSlotList); - //pSizer->AddContainer(m_pSlotTable); - pSizer->AddObject(m_pBuffer, m_iWidth * m_iHeight * sizeof(FONT_TEXTURE_TYPE)); - } - - bool GetMonospaced() const { return m_pGlyphCache.GetMonospaced(); } - - Vec2 GetKerning(uint32_t leftGlyph, uint32_t rightGlyph); - - float GetAscenderToHeightRatio(); - -public: // --------------------------------------------------------------- - - //! Clamps the given glyph size to the given max cell width and height dimensions. - static Vec2i ClampGlyphSize(const Vec2i& glyphSize, int cellWidth, int cellHeight); - -private: // --------------------------------------------------------------- - - int CreateSlotList(int iListSize); - int ReleaseSlotList(); - - //! Updates the given font texture slot with the given glyph (UTF8) with the given parameters. If the glyph doesn't - //! exist in the font texture at the given size, then the glyph will be rendered to the font texture with the given - //! parameters. - //! \param iSlot Index of the texture slot to update within the slot list. - //! \param wSlotUsage Used for LRU strategy to determine how many times a glyph is referenced for retention within the font texture (before eviction). - //! \param cChar UTF32 glyph to store within the slot. - //! \param sizeRatio A sizing scale that should be applied to the glyph before being stored within the font texture. - //! \param glyphSize The size of the glyph to be rendered at within the font texture. - //! \param glyphFlags Specifies hinting behavior that should be applied to the glyph when rendered to the font texture. - int UpdateSlot(int iSlot, uint16 wSlotUsage, uint32 cChar, float sizeRatio, const Vec2i& glyphSize = CCryFont::defaultGlyphSize, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams()); - - CryFont::FontTexture::CTextureSlotKey GetTextureSlotKey(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize) const; - - //! Calculates scaling info that should be applied when the rendered glyph size doesn't match the maximum glyph slot resolution. - //! - //! Glyphs can be re-rendered to glyph slots at smaller resolutions for pixel-perfect resolution (rather than applying a scale - //! to glyphs rendered at larger sizes). These scaling values allow clients of the font texture to use the glyphs without regard - //! to whether the glyphs have been re-rendered or not. - float GetRequestSizeWidthScale(const Vec2i& glyphSize) const - { - const int cellWidth = m_iCellWidth == 0 ? 1 : m_iCellWidth; - const float invCellWidth = 1.0f / cellWidth; - return glyphSize.x > 0 ? glyphSize.x * invCellWidth : 1.0f; - } - - //! Calculates scaling info that should be applied when the rendered glyph size doesn't match the maximum glyph slot resolution. - //! - //! Glyphs can be re-rendered to glyph slots at smaller resolutions for pixel-perfect resolution (rather than applying a scale - //! to glyphs rendered at larger sizes). These scaling values allow clients of the font texture to use the glyphs without regard - //! to whether the glyphs have been re-rendered or not. - float GetRequestSizeHeightScale(const Vec2i& glyphSize) const - { - const int cellHeight = m_iCellHeight == 0 ? 1 : m_iCellHeight; - const float invCellHeight = 1.0f / cellHeight; - return glyphSize.y > 0 ? glyphSize.y * invCellHeight : 1.0f; - } - - // -------------------------------- - - int m_iWidth; // whole texture cache width - int m_iHeight; // whole texture cache height - - float m_fInvWidth; - float m_fInvHeight; - - int m_iCellWidth; - int m_iCellHeight; - - float m_fTextureCellWidth; - float m_fTextureCellHeight; - - int m_iWidthCellCount; - int m_iHeightCellCount; - - int m_nTextureSlotCount; - - int m_iSmoothMethod; - int m_iSmoothAmount; - - CGlyphCache m_pGlyphCache; - CTextureSlotList m_pSlotList; - CTextureSlotTable m_pSlotTable; - - FONT_TEXTURE_TYPE* m_pBuffer; // [y*iWidth * x] x=0..iWidth-1, y=0..iHeight-1 - - uint16 m_wSlotUsage; -}; - -#endif // #if !defined(USE_NULLFONT_ALWAYS) - -#endif // CRYINCLUDE_CRYFONT_FONTTEXTURE_H diff --git a/Code/CryEngine/CryFont/GlyphBitmap.cpp b/Code/CryEngine/CryFont/GlyphBitmap.cpp deleted file mode 100644 index 8ae893c317..0000000000 --- a/Code/CryEngine/CryFont/GlyphBitmap.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Purpose: -// - Hold a glyph bitmap and blit it to the main texture - -#include "CryFont_precompiled.h" -#include "GlyphBitmap.h" -#include - - -//------------------------------------------------------------------------------------------------- -CGlyphBitmap::CGlyphBitmap() - : m_iWidth(0) - , m_iHeight(0) - , m_pBuffer(0) -{ -} - -//------------------------------------------------------------------------------------------------- -CGlyphBitmap::~CGlyphBitmap() -{ - Release(); -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::Create(int iWidth, int iHeight) -{ - Release(); - - m_pBuffer = new unsigned char[iWidth * iHeight]; - - if (!m_pBuffer) - { - return 0; - } - - m_iWidth = iWidth; - m_iHeight = iHeight; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::Release() -{ - if (m_pBuffer) - { - delete[] m_pBuffer; - } - m_pBuffer = 0; - m_iWidth = m_iHeight = 0; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::Blur(int iIterations) -{ - int cSum; - int yOffset; - int yupOffset; - int ydownOffset; - - for (int i = 0; i < iIterations; i++) - { - for (int y = 0; y < m_iHeight; y++) - { - yOffset = y * m_iWidth; - - if (y - 1 >= 0) - { - yupOffset = (y - 1) * m_iWidth; - } - else - { - yupOffset = (y) * m_iWidth; - } - - if (y + 1 < m_iHeight) - { - ydownOffset = (y + 1) * m_iWidth; - } - else - { - ydownOffset = (y) * m_iWidth; - } - - for (int x = 0; x < m_iWidth; x++) - { - cSum = m_pBuffer[yupOffset + x] + m_pBuffer[ydownOffset + x]; - - if (x - 1 >= 0) - { - cSum += m_pBuffer[yOffset + x - 1]; - } - else - { - cSum += m_pBuffer[yOffset + x]; - } - - if (x + 1 < m_iWidth) - { - cSum += m_pBuffer[yOffset + x + 1]; - } - else - { - cSum += m_pBuffer[yOffset + x]; - } - - m_pBuffer[yOffset + x] = cSum >> 2; - } - } - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::Scale(float fScaleX, float fScaleY) -{ - int iNewWidth = (int)(m_iWidth * fScaleX); - int iNewHeight = (int)(m_iHeight * fScaleY); - - unsigned char* pNewBuffer = new unsigned char[iNewWidth * iNewHeight]; - - if (!pNewBuffer) - { - return 0; - } - - float xFactor = m_iWidth / (float)iNewWidth; - float yFactor = m_iHeight / (float)iNewHeight; - - float xFractioned, yFractioned, xFraction, yFraction, oneMinusX, oneMinusY, fR0, fR1; - int xCeil, yCeil, xFloor, yFloor, yNewOffset; - - unsigned char c0, c1, c2, c3; - - for (int y = 0; y < iNewHeight; ++y) - { - yFractioned = y * yFactor; - yFloor = (int)floor_tpl(yFractioned); - yCeil = yFloor + 1; - - if (yCeil >= m_iHeight) - { - yCeil = yFloor; - } - - yFraction = yFractioned - yFloor; - oneMinusY = 1.0f - yFraction; - - yNewOffset = y * iNewWidth; - - for (int x = 0; x < iNewWidth; ++x) - { - xFractioned = x * xFactor; - xFloor = (int)floor_tpl(xFractioned); - xCeil = xFloor + 1; - - if (xCeil >= m_iWidth) - { - xCeil = xFloor; - } - - xFraction = xFractioned - xFloor; - oneMinusX = 1.0f - xFraction; - - c0 = m_pBuffer[yFloor * m_iWidth + xFloor]; - c1 = m_pBuffer[yFloor * m_iWidth + xCeil]; - c2 = m_pBuffer[yCeil * m_iWidth + xFloor]; - c3 = m_pBuffer[yCeil * m_iWidth + xCeil]; - - fR0 = (oneMinusX * c0 + xFraction * c1); - fR1 = (oneMinusX * c2 + xFraction * c3); - - pNewBuffer[yNewOffset + x] = (unsigned char)((oneMinusY * fR0) + (yFraction * fR1)); - } - } - - m_iWidth = iNewWidth; - m_iHeight = iNewHeight; - - delete[] m_pBuffer; - m_pBuffer = pNewBuffer; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::Clear() -{ - memset(m_pBuffer, 0, m_iWidth * m_iHeight); - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::BlitTo8(unsigned char* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth) -{ - int ySrcOffset, yDestOffset; - - for (int y = 0; y < iSrcHeight; y++) - { - ySrcOffset = (iSrcY + y) * m_iWidth; - yDestOffset = (iDestY + y) * iDestWidth; - - for (int x = 0; x < iSrcWidth; x++) - { - pBuffer[yDestOffset + iDestX + x] = m_pBuffer[ySrcOffset + iSrcX + x]; - } - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::BlitTo32(unsigned int* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth) -{ - int ySrcOffset, yDestOffset; - char cColor; - - for (int y = 0; y < iSrcHeight; y++) - { - ySrcOffset = (iSrcY + y) * m_iWidth; - yDestOffset = (iDestY + y) * iDestWidth; - - for (int x = 0; x < iSrcWidth; x++) - { - cColor = m_pBuffer[ySrcOffset + iSrcX + x]; - - pBuffer[yDestOffset + iDestX + x] = (cColor << 24) | (255 << 16) | (255 << 8) | 255; - } - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::BlitScaledTo8(unsigned char* pBuffer, [[maybe_unused]] int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, [[maybe_unused]] int iDestY, int iDestWidth, int iDestHeight, int iDestBufferWidth) -{ - int iNewWidth = (int)iDestWidth; - int iNewHeight = (int)iDestHeight; - - unsigned char* pNewBuffer = pBuffer; - - float xFactor = iSrcWidth / (float)iNewWidth; - float yFactor = iSrcHeight / (float)iNewHeight; - - float xFractioned, yFractioned, xFraction, yFraction, oneMinusX, oneMinusY, fR0, fR1; - int xCeil, yCeil, xFloor, yFloor, yNewOffset; - - unsigned char c0, c1, c2, c3; - - for (int y = 0; y < iNewHeight; ++y) - { - yFractioned = y * yFactor; - yFloor = (int)floor_tpl(yFractioned); - yCeil = yFloor + 1; - - yFraction = yFractioned - yFloor; - oneMinusY = 1.0f - yFraction; - - yNewOffset = y * iDestBufferWidth; - - yFloor += iSrcY; - yCeil += iSrcY; - - if (yCeil >= m_iHeight) - { - yCeil = yFloor; - } - - for (int x = 0; x < iNewWidth; ++x) - { - xFractioned = x * xFactor; - xFloor = (int)floor_tpl(xFractioned); - xCeil = xFloor + 1; - - xFraction = xFractioned - xFloor; - oneMinusX = 1.0f - xFraction; - - xFloor += iSrcY; - xCeil += iSrcY; - - if (xCeil >= m_iWidth) - { - xCeil = xFloor; - } - - c0 = m_pBuffer[yFloor * m_iWidth + xFloor]; - c1 = m_pBuffer[yFloor * m_iWidth + xCeil]; - c2 = m_pBuffer[yCeil * m_iWidth + xFloor]; - c3 = m_pBuffer[yCeil * m_iWidth + xCeil]; - - fR0 = (oneMinusX * c0 + xFraction * c1); - fR1 = (oneMinusX * c2 + xFraction * c3); - - pNewBuffer[yNewOffset + x + iDestX] = (unsigned char)((oneMinusY * fR0) + (yFraction * fR1)); - } - } - - return 1; -} - - -#if defined(__GNUC__) -#if __GNUC__ >= 4 && __GNUC__MINOR__ < 7 -#pragma GCC diagnostic ignored "-Woverflow" -#endif -#endif -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::BlitScaledTo32(unsigned char* pBuffer, [[maybe_unused]] int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, [[maybe_unused]] int iDestY, int iDestWidth, int iDestHeight, int iDestBufferWidth) -{ - int iNewWidth = (int)iDestWidth; - int iNewHeight = (int)iDestHeight; - - unsigned char* pNewBuffer = pBuffer; - - float xFactor = iSrcWidth / (float)iNewWidth; - float yFactor = iSrcHeight / (float)iNewHeight; - - float xFractioned, yFractioned, xFraction, yFraction, oneMinusX, oneMinusY, fR0, fR1; - int xCeil, yCeil, xFloor, yFloor, yNewOffset; - - unsigned char c0, c1, c2, c3, cColor; - - for (int y = 0; y < iNewHeight; ++y) - { - yFractioned = y * yFactor; - yFloor = (int)floor_tpl(yFractioned); - yCeil = yFloor + 1; - - yFraction = yFractioned - yFloor; - oneMinusY = 1.0f - yFraction; - - yNewOffset = y * iDestBufferWidth; - - yFloor += iSrcY; - yCeil += iSrcY; - - if (yCeil >= m_iHeight) - { - yCeil = yFloor; - } - - for (int x = 0; x < iNewWidth; ++x) - { - xFractioned = x * xFactor; - xFloor = (int)floor_tpl(xFractioned); - xCeil = xFloor + 1; - - xFraction = xFractioned - xFloor; - oneMinusX = 1.0f - xFraction; - - xFloor += iSrcY; - xCeil += iSrcY; - - if (xCeil >= m_iWidth) - { - xCeil = xFloor; - } - - c0 = m_pBuffer[yFloor * m_iWidth + xFloor]; - c1 = m_pBuffer[yFloor * m_iWidth + xCeil]; - c2 = m_pBuffer[yCeil * m_iWidth + xFloor]; - c3 = m_pBuffer[yCeil * m_iWidth + xCeil]; - - fR0 = (oneMinusX * c0 + xFraction * c1); - fR1 = (oneMinusX * c2 + xFraction * c3); - - cColor = (unsigned char)((oneMinusY * fR0) + (yFraction * fR1)); - - pNewBuffer[yNewOffset + x + iDestX] = 0xffffff | (cColor << 24); - } - } - - return 1; -} -#if defined(__GNUC__) -#if __GNUC__ >= 4 && __GNUC__MINOR__ < 7 -#pragma GCC diagnostic error "-Woverflow" -#endif -#endif -//------------------------------------------------------------------------------------------------- diff --git a/Code/CryEngine/CryFont/GlyphBitmap.h b/Code/CryEngine/CryFont/GlyphBitmap.h deleted file mode 100644 index 3d04a36cf7..0000000000 --- a/Code/CryEngine/CryFont/GlyphBitmap.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Purpose : Hold a glyph bitmap and blit it to the main texture - -#ifndef CRYINCLUDE_CRYFONT_GLYPHBITMAP_H -#define CRYINCLUDE_CRYFONT_GLYPHBITMAP_H - -#pragma once - - -class CGlyphBitmap -{ -public: - CGlyphBitmap(); - ~CGlyphBitmap(); - - int Create(int iWidth, int iHeight); - int Release(); - - unsigned char* GetBuffer() { return m_pBuffer; }; - - int Blur(int iIterations); - int Scale(float fScaleX, float fScaleY); - - int Clear(); - - int BlitTo8(unsigned char* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth); - int BlitTo32(unsigned int* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth); - - int BlitScaledTo8(unsigned char* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth, int iDestHeight, int iDestBufferWidth); - int BlitScaledTo32(unsigned char* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth, int iDestHeight, int iDestBufferWidth); - - int GetWidth() { return m_iWidth; } - int GetHeight() { return m_iHeight; } - - void GetMemoryUsage(ICrySizer* pSizer) const - { - pSizer->AddObject(m_pBuffer, m_iWidth * m_iHeight); - } - -private: - - unsigned char* m_pBuffer; - int m_iWidth; - int m_iHeight; -}; - -#endif // CRYINCLUDE_CRYFONT_GLYPHBITMAP_H diff --git a/Code/CryEngine/CryFont/GlyphCache.cpp b/Code/CryEngine/CryFont/GlyphCache.cpp deleted file mode 100644 index 96949009df..0000000000 --- a/Code/CryEngine/CryFont/GlyphCache.cpp +++ /dev/null @@ -1,433 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Purpose: -// - Manage and cache glyphs, retrieving them from the renderer as needed - -#include "CryFont_precompiled.h" - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "GlyphCache.h" -#include "FontTexture.h" - - - -//------------------------------------------------------------------------------------------------- -CGlyphCache::CGlyphCache() - : m_dwUsage(1) - , m_iGlyphBitmapWidth(0) - , m_iGlyphBitmapHeight(0) - , m_pScaleBitmap(0) -{ - m_pCacheTable.clear(); - m_pSlotList.clear(); -} - -//------------------------------------------------------------------------------------------------- -CGlyphCache::~CGlyphCache() -{ -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::Create(int iCacheSize, int iGlyphBitmapWidth, int iGlyphBitmapHeight, int iSmoothMethod, int iSmoothAmount, float sizeRatio) -{ - m_iSmoothMethod = iSmoothMethod; - m_iSmoothAmount = iSmoothAmount; - - m_iGlyphBitmapWidth = iGlyphBitmapWidth; - m_iGlyphBitmapHeight = iGlyphBitmapHeight; - - - if (!CreateSlotList(iCacheSize)) - { - ReleaseSlotList(); - - return 0; - } - - int iScaledGlyphWidth = 0; - int iScaledGlyphHeight = 0; - - switch (m_iSmoothMethod) - { - case FONT_SMOOTH_SUPERSAMPLE: - { - switch (m_iSmoothAmount) - { - case FONT_SMOOTH_AMOUNT_2X: - iScaledGlyphWidth = m_iGlyphBitmapWidth << 1; - iScaledGlyphHeight = m_iGlyphBitmapHeight << 1; - break; - case FONT_SMOOTH_AMOUNT_4X: - iScaledGlyphWidth = m_iGlyphBitmapWidth << 2; - iScaledGlyphHeight = m_iGlyphBitmapHeight << 2; - break; - } - } - break; - } - - if (iScaledGlyphWidth) - { - m_pScaleBitmap = new CGlyphBitmap; - - if (!m_pScaleBitmap) - { - Release(); - - return 0; - } - - if (!m_pScaleBitmap->Create(iScaledGlyphWidth, iScaledGlyphHeight)) - { - Release(); - - return 0; - } - - m_pFontRenderer.SetGlyphBitmapSize(iScaledGlyphWidth, iScaledGlyphHeight, sizeRatio); - } - else - { - m_pFontRenderer.SetGlyphBitmapSize(m_iGlyphBitmapWidth, m_iGlyphBitmapHeight, sizeRatio); - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::Release() -{ - ReleaseSlotList(); - - m_pCacheTable.clear(); - - if (m_pScaleBitmap) - { - m_pScaleBitmap->Release(); - - delete m_pScaleBitmap; - - m_pScaleBitmap = 0; - } - - m_iGlyphBitmapWidth = 0; - m_iGlyphBitmapHeight = 0; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::LoadFontFromFile(const string& szFileName) -{ - return m_pFontRenderer.LoadFromFile(szFileName); -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::LoadFontFromMemory(unsigned char* pFileBuffer, int iDataSize) -{ - return m_pFontRenderer.LoadFromMemory(pFileBuffer, iDataSize); -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::ReleaseFont() -{ - m_pFontRenderer.Release(); - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::GetGlyphBitmapSize(int* pWidth, int* pHeight) -{ - if (pWidth) - { - *pWidth = m_iGlyphBitmapWidth; - } - - if (pHeight) - { - *pHeight = m_iGlyphBitmapWidth; - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -void CGlyphCache::SetGlyphBitmapSize(int width, int height, float sizeRatio) -{ - m_pFontRenderer.SetGlyphBitmapSize(width, height, sizeRatio); -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::PreCacheGlyph(uint32 cChar, const Vec2i& glyphSize, const CFFont::FontHintParams& fontHintParams) -{ - CCacheTable::iterator pItor = m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize)); - - if (pItor != m_pCacheTable.end()) - { - pItor->second->dwUsage = m_dwUsage; - - return 1; - } - - CCacheSlot* pSlot = GetLRUSlot(); - - if (!pSlot) - { - return 0; - } - - if (pSlot->dwUsage > 0) - { - UnCacheGlyph(pSlot->cCurrentChar, pSlot->glyphSize); - } - - if (m_pScaleBitmap) - { - int iOffsetMult = 1; - - switch (m_iSmoothAmount) - { - case FONT_SMOOTH_AMOUNT_2X: - iOffsetMult = 2; - break; - case FONT_SMOOTH_AMOUNT_4X: - iOffsetMult = 4; - break; - } - - m_pScaleBitmap->Clear(); - - if (!m_pFontRenderer.GetGlyph(m_pScaleBitmap, &pSlot->iHoriAdvance, &pSlot->iCharWidth, &pSlot->iCharHeight, pSlot->iCharOffsetX, pSlot->iCharOffsetY, 0, 0, cChar, fontHintParams)) - { - return 0; - } - - pSlot->iCharWidth >>= iOffsetMult >> 1; - pSlot->iCharHeight >>= iOffsetMult >> 1; - - m_pScaleBitmap->BlitScaledTo8(pSlot->pGlyphBitmap.GetBuffer(), 0, 0, m_pScaleBitmap->GetWidth(), m_pScaleBitmap->GetHeight(), 0, 0, pSlot->pGlyphBitmap.GetWidth(), pSlot->pGlyphBitmap.GetHeight(), pSlot->pGlyphBitmap.GetWidth()); - } - else - { - if (!m_pFontRenderer.GetGlyph(&pSlot->pGlyphBitmap, &pSlot->iHoriAdvance, &pSlot->iCharWidth, &pSlot->iCharHeight, pSlot->iCharOffsetX, pSlot->iCharOffsetY, 0, 0, cChar, fontHintParams)) - { - return 0; - } - } - - if (m_iSmoothMethod == FONT_SMOOTH_BLUR) - { - pSlot->pGlyphBitmap.Blur(m_iSmoothAmount); - } - - pSlot->dwUsage = m_dwUsage; - pSlot->cCurrentChar = cChar; - pSlot->glyphSize = glyphSize; - - m_pCacheTable.insert(AZStd::pair(GetCacheSlotKey(cChar, glyphSize), pSlot)); - - return 1; -} - -int CGlyphCache::UnCacheGlyph(uint32 cChar, const Vec2i& glyphSize) -{ - CCacheTable::iterator pItor = m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize)); - - if (pItor != m_pCacheTable.end()) - { - CCacheSlot* pSlot = pItor->second; - - pSlot->Reset(); - - m_pCacheTable.erase(pItor); - - return 1; - } - - return 0; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::GlyphCached(uint32 cChar, const Vec2i& glyphSize) -{ - return (m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize)) != m_pCacheTable.end()); -} - -//------------------------------------------------------------------------------------------------- -CCacheSlot* CGlyphCache::GetLRUSlot() -{ - unsigned int dwMinUsage = 0xffffffff; - CCacheSlot* pLRUSlot = 0; - CCacheSlot* pSlot; - - CCacheSlotListItor pItor = m_pSlotList.begin(); - - while (pItor != m_pSlotList.end()) - { - pSlot = *pItor; - - if (pSlot->dwUsage == 0) - { - return pSlot; - } - else - { - if (pSlot->dwUsage < dwMinUsage) - { - pLRUSlot = pSlot; - dwMinUsage = pSlot->dwUsage; - } - } - - pItor++; - } - - return pLRUSlot; -} - -//------------------------------------------------------------------------------------------------- -CCacheSlot* CGlyphCache::GetMRUSlot() -{ - unsigned int dwMaxUsage = 0; - CCacheSlot* pMRUSlot = 0; - CCacheSlot* pSlot; - - CCacheSlotListItor pItor = m_pSlotList.begin(); - - while (pItor != m_pSlotList.end()) - { - pSlot = *pItor; - - if (pSlot->dwUsage != 0) - { - if (pSlot->dwUsage > dwMaxUsage) - { - pMRUSlot = pSlot; - dwMaxUsage = pSlot->dwUsage; - } - } - - pItor++; - } - - return pMRUSlot; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::GetGlyph(CGlyphBitmap** pGlyph, int* piHoriAdvance, int* piWidth, int* piHeight, AZ::s32& iCharOffsetX, AZ::s32& iCharOffsetY, uint32 cChar, const Vec2i& glyphSize, const CFFont::FontHintParams& fontHintParams) -{ - CCacheTable::iterator pItor = m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize)); - - if (pItor == m_pCacheTable.end()) - { - if (!PreCacheGlyph(cChar, glyphSize, fontHintParams)) - { - return 0; - } - } - - pItor = m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize)); - - pItor->second->dwUsage = m_dwUsage++; - (*pGlyph) = &pItor->second->pGlyphBitmap; - - if (piHoriAdvance) - { - *piHoriAdvance = pItor->second->iHoriAdvance; - } - - if (piWidth) - { - *piWidth = pItor->second->iCharWidth; - } - - if (piHeight) - { - *piHeight = pItor->second->iCharHeight; - } - - iCharOffsetX = pItor->second->iCharOffsetX; - iCharOffsetY = pItor->second->iCharOffsetY; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -Vec2 CGlyphCache::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph) -{ - return m_pFontRenderer.GetKerning(leftGlyph, rightGlyph); -} - -//------------------------------------------------------------------------------------------------- -float CGlyphCache::GetAscenderToHeightRatio() -{ - return m_pFontRenderer.GetAscenderToHeightRatio(); -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::CreateSlotList(int iListSize) -{ - for (int i = 0; i < iListSize; i++) - { - CCacheSlot* pCacheSlot = new CCacheSlot; - - if (!pCacheSlot) - { - return 0; - } - - if (!pCacheSlot->pGlyphBitmap.Create(m_iGlyphBitmapWidth, m_iGlyphBitmapHeight)) - { - delete pCacheSlot; - - return 0; - } - - pCacheSlot->Reset(); - - pCacheSlot->iCacheSlot = i; - - m_pSlotList.push_back(pCacheSlot); - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::ReleaseSlotList() -{ - CCacheSlotListItor pItor = m_pSlotList.begin(); - - while (pItor != m_pSlotList.end()) - { - (*pItor)->pGlyphBitmap.Release(); - - delete (*pItor); - - pItor = m_pSlotList.erase(pItor); - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -CryFont::GlyphCache::CCacheTableKey CGlyphCache::GetCacheSlotKey(uint32 cChar, const Vec2i& glyphSize) const -{ - const Vec2i clampedGlyphSize = CFontTexture::ClampGlyphSize(glyphSize, m_iGlyphBitmapWidth, m_iGlyphBitmapHeight); - return CryFont::GlyphCache::CCacheTableKey(clampedGlyphSize, cChar); -} - -#endif // #if !defined(USE_NULLFONT_ALWAYS) diff --git a/Code/CryEngine/CryFont/GlyphCache.h b/Code/CryEngine/CryFont/GlyphCache.h deleted file mode 100644 index c0cc1db555..0000000000 --- a/Code/CryEngine/CryFont/GlyphCache.h +++ /dev/null @@ -1,200 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. -// Purpose: -// - Manage and cache glyphs, retrieving them from the renderer as needed - -#ifndef CRYINCLUDE_CRYFONT_GLYPHCACHE_H -#define CRYINCLUDE_CRYFONT_GLYPHCACHE_H -#pragma once - -#if !defined(USE_NULLFONT_ALWAYS) - -#include -#include "GlyphBitmap.h" -#include "FontRenderer.h" -#include "CryFont.h" -#include - -//! Glyph cache slots store the bitmap buffer and glyph metadata from FreeType. -//! -//! This bitmap buffer is eventually copied to a CFontTexture texture buffer. -//! A glyph cache slot bitmap buffer only holds a single glyph, whereas the -//! CFontTexture stores multiple glyphs in a grid (row/col) format. -typedef struct CCacheSlot -{ - Vec2i glyphSize = CCryFont::defaultGlyphSize; //!< The render resolution of the glyph in the glyph bitmap - unsigned int dwUsage; - int iCacheSlot; - int iHoriAdvance; //!< Advance width. See FT_Glyph_Metrics::horiAdvance. - uint32 cCurrentChar; - - uint8 iCharWidth; //!< Glyph width (in pixel) - uint8 iCharHeight; //!< Glyph height (in pixel) - AZ::s32 iCharOffsetX; //!< Glyph's left-side bearing (in pixels). See FT_GlyphSlotRec::bitmap_left. - AZ::s32 iCharOffsetY; //!< Glyph's top bearing (in pixels). See FT_GlyphSlotRec::bitmap_top. - - CGlyphBitmap pGlyphBitmap; //!< Contains a buffer storing a copy of the glyph from FreeType - - void Reset() - { - dwUsage = 0; - cCurrentChar = ~0; - - iCharWidth = 0; - iCharHeight = 0; - iCharOffsetX = 0; - iCharOffsetY = 0; - - pGlyphBitmap.Clear(); - } - - void GetMemoryUsage(ICrySizer* pSizer) const - { - pSizer->AddObject(this, sizeof(*this)); - pSizer->AddObject(pGlyphBitmap); - } -} CCacheSlot; - -namespace CryFont -{ - namespace GlyphCache - { - //! Height and width pair for glyph size mapping - typedef Vec2i CCacheTableGlyphSizeType; - - //! Pair for mapping a height and width size to a UTF32 character/glyph - typedef AZStd::pair CCacheTableKey; - - //! Hasher for glyph cache table keys (glyphsize-char code pair) - //! - //! Instead of creating our own custom hash, the types are broken down to their - //! native types (ints) and passed to existing hashes that handle those types. - struct HashGlyphCacheTableKey - { - typedef CCacheTableKey ArgumentType; - typedef AZStd::size_t ResultType; - typedef AZStd::pair Int32Pair; - typedef AZStd::pair Int32PairU32Pair; - ResultType operator()(const ArgumentType& value) const - { - AZStd::hash pairHash; - return pairHash(Int32PairU32Pair(Int32Pair(value.first.x, value.first.y), value.second)); - } - }; - } -} - -//! Maps size-speicifc UTF32 glyphs to their corresponding cache slots -typedef AZStd::unordered_map CCacheTable; - -typedef std::vector CCacheSlotList; -typedef std::vector::iterator CCacheSlotListItor; - - -#ifdef WIN64 -#undef GetCharWidth -#undef GetCharHeight -#endif - -//! The glyph cache maps UTF32 codepoints to their corresponding FreeType data. -//! -//! This cache is used to associate font glyph info (read from FreeType) with -//! UTF32 codepoints. Ultimately the glyph info will be read into a font texture -//! (CFontTexture) to avoid future FreeType lookups. -//! -//! If a CFontTexture is missing a glyph that is currently stored in the glyph -//! cache, the cached data can be returned instead of having to be rendered from -//! FreeType again. -//! -//! \sa CFontTexture -class CGlyphCache -{ -public: - CGlyphCache(); - ~CGlyphCache(); - - int Create(int iCacheSize, int iGlyphBitmapWidth, int iGlyphBitmapHeight, int iSmoothMethod, int iSmoothAmount, float sizeRatio); - int Release(); - - int LoadFontFromFile(const string& szFileName); - int LoadFontFromMemory(unsigned char* pFileBuffer, int iDataSize); - int ReleaseFont(); - - int SetEncoding(FT_Encoding pEncoding) { return m_pFontRenderer.SetEncoding(pEncoding); }; - FT_Encoding GetEncoding() { return m_pFontRenderer.GetEncoding(); }; - - int GetGlyphBitmapSize(int* pWidth, int* pHeight); - void SetGlyphBitmapSize(int width, int height, float sizeRatio); - - int PreCacheGlyph(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams()); - int UnCacheGlyph(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize); - int GlyphCached(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize); - - CCacheSlot* GetLRUSlot(); - CCacheSlot* GetMRUSlot(); - - //! Obtains glyph information for the given UTF32 codepoint. - //! This information is obtained from a CCacheSlot that corresponds to - //! the given codepoint. If the codepoint doesn't exist within the cache - //! table (m_pCacheTable), then the information is obtain from FreeType - //! directly via CFontRenderer. - //! - //! Ultimately the glyph bitmap is copied into a font texture - //! (CFontTexture). Once the glyph is copied into the font texture then - //! the font texture is referenced directly rather than relying on the - //! glyph cache or FreeType. - //! - //! \sa CFontRenderer::GetGlyph, CFontTexture::UpdateSlot - int GetGlyph(CGlyphBitmap** pGlyph, int* piHoriAdvance, int* piWidth, int* piHeight, AZ::s32& iCharOffsetX, AZ::s32& iCharOffsetY, uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams()); - - void GetMemoryUsage(ICrySizer* pSizer) const - { - pSizer->AddObject(m_pSlotList); - //pSizer->AddContainer(m_pCacheTable); - pSizer->AddObject(m_pScaleBitmap); - pSizer->AddObject(m_pFontRenderer); - } - - bool GetMonospaced() const { return m_pFontRenderer.GetMonospaced(); } - - Vec2 GetKerning(uint32_t leftGlyph, uint32_t rightGlyph); - - float GetAscenderToHeightRatio(); - -private: - - //! Returns a key for the cache table where the given char is mapped at the given size. - CryFont::GlyphCache::CCacheTableKey GetCacheSlotKey(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize) const; - - int CreateSlotList(int iListSize); - int ReleaseSlotList(); - - CCacheSlotList m_pSlotList; - CCacheTable m_pCacheTable; - - int m_iGlyphBitmapWidth; - int m_iGlyphBitmapHeight; - - int m_iSmoothMethod; - int m_iSmoothAmount; - - CGlyphBitmap* m_pScaleBitmap; - - CFontRenderer m_pFontRenderer; - - unsigned int m_dwUsage; -}; - -#endif // #if !defined(USE_NULLFONT_ALWAYS) - -#endif // CRYINCLUDE_CRYFONT_GLYPHCACHE_H diff --git a/Code/CryEngine/CryFont/ICryFont.cpp b/Code/CryEngine/CryFont/ICryFont.cpp deleted file mode 100644 index dfbaf65335..0000000000 --- a/Code/CryEngine/CryFont/ICryFont.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Create the font interface. - - -#include "CryFont_precompiled.h" - -#include -#include -#include - -#include "CryFont.h" -#if defined(USE_NULLFONT) -#include "NullFont.h" -#endif - -////////////////////////////////////////////////////////////////////////// -struct CSystemEventListner_Font - : public ISystemEventListener -{ -public: - virtual void OnSystemEvent(ESystemEvent event, [[maybe_unused]] UINT_PTR wparam, [[maybe_unused]] UINT_PTR lparam) - { - switch (event) - { - case ESYSTEM_EVENT_LEVEL_POST_UNLOAD: - { - STLALLOCATOR_CLEANUP; - break; - } - } - } -}; -static CSystemEventListner_Font g_system_event_listener_font; - -/////////////////////////////////////////////// -extern "C" ICryFont * CreateCryFontInterface(ISystem * pSystem) -{ - ModuleInitISystem(pSystem, "CryFont"); - - if (gEnv->IsDedicated()) - { -#if defined(USE_NULLFONT) - return new CCryNullFont(); -#else - // The NULL font implementation must be present for all platforms - // supporting running as a pure dedicated server. - pSystem->GetILog()->LogError("Missing NULL font implementation for dedicated server"); - return NULL; -#endif - } - else - { -#if defined(USE_NULLFONT) && defined(USE_NULLFONT_ALWAYS) - return new CCryNullFont(); -#else - pSystem->GetISystemEventDispatcher()->RegisterListener(&g_system_event_listener_font); - return new CCryFont(pSystem); -#endif - } -} - -////////////////////////////////////////////////////////////////////////// -class CEngineModule_CryFont - : public IEngineModule -{ - CRYINTERFACE_SIMPLE(IEngineModule) - CRYGENERATE_SINGLETONCLASS(CEngineModule_CryFont, "EngineModule_CryFont", 0x6758643f43214957, 0x9b920d898d31f434) - - ////////////////////////////////////////////////////////////////////////// - virtual const char* GetName() const { - return "CryFont"; - }; - virtual const char* GetCategory() const { return "CryEngine"; }; - - ////////////////////////////////////////////////////////////////////////// - virtual bool Initialize(SSystemGlobalEnvironment& env, [[maybe_unused]] const SSystemInitParams& initParams) - { - ISystem* pSystem = env.pSystem; - env.pCryFont = CreateCryFontInterface(pSystem); - return env.pCryFont != 0; - } -}; - -CRYREGISTER_SINGLETON_CLASS(CEngineModule_CryFont) - -CEngineModule_CryFont::CEngineModule_CryFont() -{ -}; - -CEngineModule_CryFont::~CEngineModule_CryFont() -{ -}; diff --git a/Code/CryEngine/CryFont/NullFont.h b/Code/CryEngine/CryFont/NullFont.h deleted file mode 100644 index 94fceeb9b0..0000000000 --- a/Code/CryEngine/CryFont/NullFont.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Dummy font implementation (dedicated server) - - -#ifndef CRYINCLUDE_CRYFONT_NULLFONT_H -#define CRYINCLUDE_CRYFONT_NULLFONT_H -#pragma once - - -#if defined(USE_NULLFONT) - -#include - -class CNullFont - : public IFFont -{ -public: - CNullFont() {} - virtual ~CNullFont() {} - - virtual int32 AddRef() { return 0; }; - virtual int32 Release() { return 0; }; - - virtual bool Load([[maybe_unused]] const char* pFontFilePath, [[maybe_unused]] unsigned int width, [[maybe_unused]] unsigned int height, [[maybe_unused]] unsigned int widthNumSlots, [[maybe_unused]] unsigned int heightNumSlots, [[maybe_unused]] unsigned int flags, [[maybe_unused]] float sizeRatio) { return true; } - virtual bool Load([[maybe_unused]] const char* pXMLFile) { return true; } - virtual void Free() {} - - virtual void DrawString([[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) {} - virtual void DrawString([[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] float z, [[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) {} - - virtual void DrawStringW([[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] const wchar_t* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) {} - virtual void DrawStringW([[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] float z, [[maybe_unused]] const wchar_t* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) {} - - virtual Vec2 GetTextSize([[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) { return Vec2(0.0f, 0.0f); } - virtual Vec2 GetTextSizeW([[maybe_unused]] const wchar_t* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) { return Vec2(0.0f, 0.0f); } - - virtual size_t GetTextLength([[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine) const { return 0; } - virtual size_t GetTextLengthW([[maybe_unused]] const wchar_t* pStr, [[maybe_unused]] const bool asciiMultiLine) const { return 0; } - - virtual void WrapText(string& result, [[maybe_unused]] float maxWidth, const char* pStr, [[maybe_unused]] const STextDrawContext& ctx) { result = pStr; } - virtual void WrapTextW(wstring& result, [[maybe_unused]] float maxWidth, const wchar_t* pStr, [[maybe_unused]] const STextDrawContext& ctx) { result = pStr; } - - virtual void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {} - - virtual void GetGradientTextureCoord([[maybe_unused]] float& minU, [[maybe_unused]] float& minV, [[maybe_unused]] float& maxU, [[maybe_unused]] float& maxV) const {} - - virtual unsigned int GetEffectId([[maybe_unused]] const char* pEffectName) const { return 0; } - virtual unsigned int GetNumEffects() const { return 0; } - virtual const char* GetEffectName([[maybe_unused]] unsigned int effectId) const { return nullptr; } - virtual Vec2 GetMaxEffectOffset([[maybe_unused]] unsigned int effectId) const { return Vec2(); } - virtual bool DoesEffectHaveTransparency([[maybe_unused]] unsigned int effectId) const { return false; } - - virtual void AddCharsToFontTexture([[maybe_unused]] const char* pChars, [[maybe_unused]] int glyphSizeX, [[maybe_unused]] int glyphSizeY) override {} - virtual Vec2 GetKerning([[maybe_unused]] uint32_t leftGlyph, [[maybe_unused]] uint32_t rightGlyph, [[maybe_unused]] const STextDrawContext& ctx) const override { return Vec2(); } - virtual float GetAscender([[maybe_unused]] const STextDrawContext& ctx) const override { return 0.0f; } - virtual float GetBaseline([[maybe_unused]] const STextDrawContext& ctx) const override { return 0.0f; } - virtual float GetSizeRatio() const override { return IFFontConstants::defaultSizeRatio; } - virtual uint32 GetNumQuadsForText([[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) { return 0; } - virtual uint32 WriteTextQuadsToBuffers([[maybe_unused]] SVF_P2F_C4B_T2F_F4B* verts, [[maybe_unused]] uint16* indices, [[maybe_unused]] uint32 maxQuads, [[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] float z, [[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) { return 0; } - virtual int GetFontTextureId() { return -1; } - virtual uint32 GetFontTextureVersion() { return 0; } -}; - -class CCryNullFont - : public ICryFont -{ -public: - virtual void Release() {} - virtual IFFont* NewFont([[maybe_unused]] const char* pFontName) { return &ms_nullFont; } - virtual IFFont* GetFont([[maybe_unused]] const char* pFontName) const { return &ms_nullFont; } - virtual FontFamilyPtr LoadFontFamily([[maybe_unused]] const char* pFontFamilyName) override { CRY_ASSERT(false); return nullptr; } - virtual FontFamilyPtr GetFontFamily([[maybe_unused]] const char* pFontFamilyName) override { CRY_ASSERT(false); return nullptr; } - virtual void AddCharsToFontTextures(FontFamilyPtr pFontFamily, [[maybe_unused]] const char* pChars, [[maybe_unused]] int glyphSizeX, [[maybe_unused]] int glyphSizeY) override {}; - virtual void SetRendererProperties([[maybe_unused]] IRenderer* pRenderer) {} - virtual void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {} - virtual string GetLoadedFontNames() const { return ""; } - virtual void OnLanguageChanged() override { } - virtual void ReloadAllFonts() override { } - -private: - static CNullFont ms_nullFont; -}; - -#endif // USE_NULLFONT - -#endif // CRYINCLUDE_CRYFONT_NULLFONT_H diff --git a/Code/CryEngine/CryFont/Platform/Linux/platform_linux.cmake b/Code/CryEngine/CryFont/Platform/Linux/platform_linux.cmake deleted file mode 100644 index bafe20e506..0000000000 --- a/Code/CryEngine/CryFont/Platform/Linux/platform_linux.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -# Platform specific cmake file for configuring target compiler/link properties -# based on the active platform -# NOTE: functions in cmake are global, therefore adding functions to this file -# is being avoided to prevent overriding functions declared in other targets platfrom -# specific cmake files diff --git a/Code/CryEngine/CryFont/cryfont_files.cmake b/Code/CryEngine/CryFont/cryfont_files.cmake deleted file mode 100644 index f46a5b5b44..0000000000 --- a/Code/CryEngine/CryFont/cryfont_files.cmake +++ /dev/null @@ -1,33 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(FILES - CryFont.cpp - FFont.cpp - FFontXML.cpp - FontRenderer.cpp - FontTexture.cpp - GlyphBitmap.cpp - GlyphCache.cpp - ICryFont.cpp - NullFont.cpp - CryFont.h - FBitmap.h - FFont.h - FontRenderer.h - FontTexture.h - GlyphBitmap.h - GlyphCache.h - NullFont.h - resource.h - CryFont_precompiled.h - CryFont_precompiled.cpp -) diff --git a/Code/CryEngine/CryFont/resource.h b/Code/CryEngine/CryFont/resource.h deleted file mode 100644 index ed88839421..0000000000 --- a/Code/CryEngine/CryFont/resource.h +++ /dev/null @@ -1,25 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#define VS_VERSION_INFO 1 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/Code/CryEngine/CrySystem/CMakeLists.txt b/Code/CryEngine/CrySystem/CMakeLists.txt index e7816cc1cd..1a5593e5d8 100644 --- a/Code/CryEngine/CrySystem/CMakeLists.txt +++ b/Code/CryEngine/CrySystem/CMakeLists.txt @@ -90,8 +90,6 @@ ly_add_target( AZ::AzCore Legacy::CryCommon Legacy::CryCommon.EngineSettings.Static - RUNTIME_DEPENDENCIES - Legacy::CryFont ) ################################################################################ diff --git a/Code/CryEngine/CrySystem/CPUDetect.cpp b/Code/CryEngine/CrySystem/CPUDetect.cpp index 9af68a1854..6d924a1514 100644 --- a/Code/CryEngine/CrySystem/CPUDetect.cpp +++ b/Code/CryEngine/CrySystem/CPUDetect.cpp @@ -52,11 +52,7 @@ # define cpuid(op, eax, ebx, ecx, edx) __asm__("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (op) : "cc"); #endif -#if defined(AZ_MONOLITHIC_BUILD) -extern int g_CpuFlags; -#else int g_CpuFlags; -#endif struct SAutoMaxPriority { diff --git a/Code/CryEngine/CrySystem/System.h b/Code/CryEngine/CrySystem/System.h index 47fdb362e9..e4fcc82552 100644 --- a/Code/CryEngine/CrySystem/System.h +++ b/Code/CryEngine/CrySystem/System.h @@ -676,17 +676,11 @@ private: //! @name Initialization routines //@{ bool InitConsole(); - bool InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInitParams& initParams); - - bool InitFont(const SSystemInitParams& initParams); bool InitFileSystem(); bool InitFileSystem_LoadEngineFolders(const SSystemInitParams& initParams); bool InitStreamEngine(); - bool Init3DEngine(const SSystemInitParams& initParams); bool InitAudioSystem(const SSystemInitParams& initParams); bool InitShine(const SSystemInitParams& initParams); - bool OpenRenderLibrary(int type, const SSystemInitParams& initParams); - bool OpenRenderLibrary(const char* t_rend, const SSystemInitParams& initParams); //@} @@ -738,9 +732,6 @@ private: bool GetWinGameFolder(char* szMyDocumentsPath, int maxPathSize); #endif - //! \brief Initializes the given IFFont member variable with the given name (internal use only). - bool LoadFontInternal(IFFont*& font, const string& fontName); - public: void EnableFloatExceptions(int type); diff --git a/Code/CryEngine/CrySystem/SystemInit.cpp b/Code/CryEngine/CrySystem/SystemInit.cpp index fcbf0b8215..d293f9ca80 100644 --- a/Code/CryEngine/CrySystem/SystemInit.cpp +++ b/Code/CryEngine/CrySystem/SystemInit.cpp @@ -43,8 +43,6 @@ #include #include -#include "CryFontBus.h" - #include #include @@ -247,24 +245,6 @@ CUNIXConsole* pUnixConsole; #define LOCALIZATION_TRANSLATIONS_LIST_FILE_NAME "Libs/Localization/localization.xml" -#define LOAD_LEGACY_RENDERER_FOR_EDITOR false // If you set this to true you must also set 'ed_useAtomNativeViewport' to false (see /Code/Sandbox/Editor/ViewManager.cpp) -#define LOAD_LEGACY_RENDERER_FOR_LAUNCHER false - -////////////////////////////////////////////////////////////////////////// -// Where possible, these are defaults used to initialize cvars -// System.cfg can then be used to override them -// This includes the Game DLL, although it is loaded elsewhere - -#define DLL_FONT "CryFont" -#define DLL_3DENGINE "Cry3DEngine" -#define DLL_RENDERER_DX9 "CryRenderD3D9" -#define DLL_RENDERER_DX11 "CryRenderD3D11" -#define DLL_RENDERER_DX12 "CryRenderD3D12" -#define DLL_RENDERER_METAL "CryRenderMetal" -#define DLL_RENDERER_GL "CryRenderGL" -#define DLL_RENDERER_NULL "CryRenderNULL" -#define DLL_SHINE "LyShine" - ////////////////////////////////////////////////////////////////////////// #if defined(WIN32) || defined(LINUX) || defined(APPLE) # define DLL_MODULE_INIT_ISYSTEM "ModuleInitISystem" @@ -1079,58 +1059,6 @@ void CSystem::ShutdownModuleLibraries() #endif // !defined(AZ_MONOLITHIC_BUILD) } -////////////////////////////////////////////////////////////////////////// -bool CSystem::OpenRenderLibrary([[maybe_unused]] const char* t_rend, const SSystemInitParams& initParams) -{ - LOADING_TIME_PROFILE_SECTION(GetISystem()); - -#if defined(AZ_RESTRICTED_PLATFORM) -#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_6 -#include AZ_RESTRICTED_FILE(SystemInit_cpp) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - - if (gEnv->IsDedicated()) - { - return OpenRenderLibrary(R_NULL_RENDERER, initParams); - } - - if (AZ::Interface::Get()) - { - return OpenRenderLibrary(R_DX11_RENDERER, initParams); - } - else if (azstricmp(t_rend, "DX9") == 0) - { - return OpenRenderLibrary(R_DX9_RENDERER, initParams); - } - else if (azstricmp(t_rend, "DX11") == 0) - { - return OpenRenderLibrary(R_DX11_RENDERER, initParams); - } - else if (azstricmp(t_rend, "DX12") == 0) - { - return OpenRenderLibrary(R_DX12_RENDERER, initParams); - } - else if (azstricmp(t_rend, "GL") == 0) - { - return OpenRenderLibrary(R_GL_RENDERER, initParams); - } - else if (azstricmp(t_rend, "METAL") == 0) - { - return OpenRenderLibrary(R_METAL_RENDERER, initParams); - } - else if (azstricmp(t_rend, "NULL") == 0) - { - return OpenRenderLibrary(R_NULL_RENDERER, initParams); - } - - AZ_Assert(false, "Unknown renderer type: %s", t_rend); - return false; -#endif -} - ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// @@ -1220,126 +1148,6 @@ wstring GetErrorStringUnsupportedGPU(const char* gpuName, unsigned int gpuVendor } #endif -bool CSystem::OpenRenderLibrary(int type, const SSystemInitParams& initParams) -{ - LOADING_TIME_PROFILE_SECTION; -#if defined(WIN32) || defined(WIN64) - if (!gEnv->IsDedicated()) - { - unsigned int gpuVendorId = 0, gpuDeviceId = 0, totVidMem = 0; - char gpuName[256]; - Win32SysInspect::DXFeatureLevel featureLevel = Win32SysInspect::DXFL_Undefined; - Win32SysInspect::GetGPUInfo(gpuName, sizeof(gpuName), gpuVendorId, gpuDeviceId, totVidMem, featureLevel); - - if (m_env.IsEditor()) - { -#if defined(EXTERNAL_CRASH_REPORTING) - CrashHandler::CrashHandlerBase::AddAnnotation("dx.feature.level", Win32SysInspect::GetFeatureLevelAsString(featureLevel)); - CrashHandler::CrashHandlerBase::AddAnnotation("gpu.name", gpuName); - CrashHandler::CrashHandlerBase::AddAnnotation("gpu.vendorId", std::to_string(gpuVendorId)); - CrashHandler::CrashHandlerBase::AddAnnotation("gpu.deviceId", std::to_string(gpuDeviceId)); - CrashHandler::CrashHandlerBase::AddAnnotation("gpu.memory", std::to_string(totVidMem)); -#endif - } - else - { - if (featureLevel < Win32SysInspect::DXFL_11_0) - { - const char logMsgFmt[] ("Unsupported GPU configuration!\n- %s (vendor = 0x%.4x, device = 0x%.4x)\n- Dedicated video memory: %d MB\n- Feature level: %s\n"); - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, logMsgFmt, gpuName, gpuVendorId, gpuDeviceId, totVidMem >> 20, GetFeatureLevelAsString(featureLevel)); - -#if !defined(_RELEASE) - const bool allowPrompts = m_env.pSystem->GetICmdLine()->FindArg(eCLAT_Pre, "noprompt") == 0; -#else - const bool allowPrompts = true; -#endif // !defined(_RELEASE) - if (allowPrompts) - { - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Asking user if they wish to continue..."); - const int mbRes = MessageBoxW(0, GetErrorStringUnsupportedGPU(gpuName, gpuVendorId, gpuDeviceId).c_str(), L"Open 3D Engine", MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2 | MB_DEFAULT_DESKTOP_ONLY); - if (mbRes == IDCANCEL) - { - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "User chose to cancel startup due to unsupported GPU."); - return false; - } - } - else - { -#if !defined(_RELEASE) - const bool obeyGPUCheck = m_env.pSystem->GetICmdLine()->FindArg(eCLAT_Pre, "anygpu") == 0; -#else - const bool obeyGPUCheck = true; -#endif // !defined(_RELEASE) - if (obeyGPUCheck) - { - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "No prompts allowed and unsupported GPU check active. Treating unsupported GPU as error and exiting."); - return false; - } - } - - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "User chose to continue despite unsupported GPU!"); - } - } - } -#endif -#if defined(AZ_RESTRICTED_PLATFORM) -#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_7 -#include AZ_RESTRICTED_FILE(SystemInit_cpp) -#endif - - if (gEnv->IsDedicated()) - { - type = R_NULL_RENDERER; - } - const char* libname = ""; - if (AZ::Interface::Get()) - { - libname = DLL_RENDERER_NULL; - } - else if (type == R_DX9_RENDERER) - { - libname = DLL_RENDERER_DX9; - } - else if (type == R_DX11_RENDERER) - { - libname = DLL_RENDERER_DX11; - } - else if (type == R_DX12_RENDERER) - { - libname = DLL_RENDERER_DX12; - } - else if (type == R_NULL_RENDERER) - { - libname = DLL_RENDERER_NULL; - } - else if (type == R_GL_RENDERER) - { - libname = DLL_RENDERER_GL; - } - else if (type == R_METAL_RENDERER) - { - libname = DLL_RENDERER_METAL; - } - else - { - AZ_Assert(false, "Renderer did not initialize correctly; no valid renderer specified."); - return false; - } - - if (!InitializeEngineModule(libname, "EngineModule_CryRenderer", initParams)) - { - return false; - } - - if (!m_env.pRenderer) - { - AZ_Assert(false, "Renderer did not initialize correctly; it could not be found in the system environment."); - return false; - } - - return true; -} - ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// bool CSystem::InitConsole() @@ -1391,123 +1199,6 @@ ICVar* CSystem::attachVariable (const char* szVarName, int* pContainer, const ch return pVar; } -///////////////////////////////////////////////////////////////////////////////// -bool CSystem::InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInitParams& initParams) -{ - LOADING_TIME_PROFILE_SECTION(GetISystem()); - - if (m_pUserCallback) - { - m_pUserCallback->OnInitProgress("Initializing Renderer..."); - } - - if (m_bEditor) - { - m_env.pConsole->GetCVar("r_Width"); - - // save current screen width/height/bpp, so they can be restored on shutdown - m_iWidth = m_env.pConsole->GetCVar("r_Width")->GetIVal(); - m_iHeight = m_env.pConsole->GetCVar("r_Height")->GetIVal(); - m_iColorBits = m_env.pConsole->GetCVar("r_ColorBits")->GetIVal(); - } - - if (!OpenRenderLibrary(m_rDriver->GetString(), initParams)) - { - return false; - } - -#if defined(AZ_PLATFORM_IOS) || defined(AZ_PLATFORM_ANDROID) - if (m_rWidthAndHeightAsFractionOfScreenSize->GetFlags() & VF_WASINCONFIG) - { - int displayWidth = 0; - int displayHeight = 0; - if (GetPrimaryPhysicalDisplayDimensions(displayWidth, displayHeight)) - { - // Ideally we would probably want to clamp this at the source, - // but I don't believe cvars support specifying a valid range. - float scaleFactor = 1.0f; - - if(IsTablet()) - { - scaleFactor = AZ::GetClamp(m_rTabletWidthAndHeightAsFractionOfScreenSize->GetFVal(), 0.1f, 1.0f); - } - else - { - scaleFactor = AZ::GetClamp(m_rWidthAndHeightAsFractionOfScreenSize->GetFVal(), 0.1f, 1.0f); - } - - displayWidth *= scaleFactor; - displayHeight *= scaleFactor; - - const int maxWidth = m_rMaxWidth->GetIVal(); - if (maxWidth > 0 && maxWidth < displayWidth) - { - const float widthScaleFactor = static_cast(maxWidth) / static_cast(displayWidth); - displayWidth *= widthScaleFactor; - displayHeight *= widthScaleFactor; - } - - const int maxHeight = m_rMaxHeight->GetIVal(); - if (maxHeight > 0 && maxHeight < displayHeight) - { - const float heightScaleFactor = static_cast(maxHeight) / static_cast(displayHeight); - displayWidth *= heightScaleFactor; - displayHeight *= heightScaleFactor; - } - - m_rWidth->Set(displayWidth); - m_rHeight->Set(displayHeight); - } - } -#endif // defined(AZ_PLATFORM_IOS) || defined(AZ_PLATFORM_ANDROID) - - if (m_env.pRenderer) - { - // This is crucial as textures suffix are hard coded to context and we need to initialize - // the texture semantics to look it up. - m_env.pRenderer->InitTexturesSemantics(); - -#ifdef WIN32 - SCustomRenderInitArgs args; - args.appStartedFromMediaCenter = strstr(initParams.szSystemCmdLine, "ReLaunchMediaCenter") != 0; - - m_hWnd = m_env.pRenderer->Init(0, 0, m_rWidth->GetIVal(), m_rHeight->GetIVal(), m_rColorBits->GetIVal(), m_rDepthBits->GetIVal(), m_rStencilBits->GetIVal(), m_rFullscreen->GetIVal() ? true : false, initParams.bEditor, hinst, hwnd, false, &args, initParams.bShaderCacheGen); - //Timur, Not very clean code, we need to push new hwnd value to the system init params, so other modules can used when initializing. - (const_cast(&initParams))->hWnd = m_hWnd; - - - bool retVal = (initParams.bShaderCacheGen || m_hWnd != 0); - AZ_Assert(retVal, "Renderer failed to initialize correctly."); - return retVal; -#else // WIN32 - WIN_HWND h = m_env.pRenderer->Init(0, 0, m_rWidth->GetIVal(), m_rHeight->GetIVal(), m_rColorBits->GetIVal(), m_rDepthBits->GetIVal(), m_rStencilBits->GetIVal(), m_rFullscreen->GetIVal() ? true : false, initParams.bEditor, hinst, hwnd, false, nullptr, initParams.bShaderCacheGen); - -#if (defined(LINUX) && !defined(AZ_PLATFORM_ANDROID)) - return true; -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(AZ_RESTRICTED_PLATFORM) -#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_8 -#include AZ_RESTRICTED_FILE(SystemInit_cpp) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - bool retVal = (initParams.bShaderCacheGen || h != 0); - if (retVal) - { - return true; - } - - AZ_Assert(false, "Renderer failed to initialize correctly."); - return false; -#endif -#endif - } - return true; -} - - - ///////////////////////////////////////////////////////////////////////////////// bool CSystem::InitFileSystem() { @@ -1662,68 +1353,6 @@ bool CSystem::InitStreamEngine() return true; } -///////////////////////////////////////////////////////////////////////////////// -bool CSystem::InitFont(const SSystemInitParams& initParams) -{ - LOADING_TIME_PROFILE_SECTION(GetISystem()); - - bool fontInited = false; - AZ::CryFontCreationRequestBus::BroadcastResult(fontInited, &AZ::CryFontCreationRequests::CreateCryFont, m_env, initParams); - if (!fontInited && !InitializeEngineModule(DLL_FONT, "EngineModule_CryFont", initParams)) - { - return false; - } - - if (!m_env.pCryFont) - { - AZ_Assert(false, "Font System did not initialize correctly; it could not be found in the system environment"); - return false; - } - - if (gEnv->IsDedicated()) - { - return true; - } - - if (!LoadFontInternal(m_pIFont, "default")) - { - return false; - } - - if (!LoadFontInternal(m_pIFontUi, "default-ui")) - { - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CSystem::Init3DEngine(const SSystemInitParams& initParams) -{ - LOADING_TIME_PROFILE_SECTION(GetISystem()); - - if (!InitializeEngineModule(DLL_3DENGINE, "EngineModule_Cry3DEngine", initParams)) - { - return false; - } - - if (!m_env.p3DEngine) - { - AZ_Assert(false, "3D Engine did not initialize correctly; it could not be found in the system environment"); - return false; - } - - if (!m_env.p3DEngine->Init()) - { - return false; - } - m_pProcess = m_env.p3DEngine; - m_pProcess->SetFlags(PROC_3DENGINE); - - return true; -} - ////////////////////////////////////////////////////////////////////////// bool CSystem::InitAudioSystem(const SSystemInitParams& initParams) { @@ -2785,42 +2414,6 @@ AZ_POP_DISABLE_WARNING } InlineInitializationProcessing("CSystem::Init InitLocalizations"); - ////////////////////////////////////////////////////////////////////////// - // RENDERER - ////////////////////////////////////////////////////////////////////////// - const bool loadLegacyRenderer = gEnv->IsEditor() ? - LOAD_LEGACY_RENDERER_FOR_EDITOR : - LOAD_LEGACY_RENDERER_FOR_LAUNCHER; - if (loadLegacyRenderer && !startupParams.bSkipRenderer) - { - AZ_Assert(CryMemory::IsHeapValid(), "CryMemory must be valid before initializing renderer."); - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Renderer initialization"); - - if (!InitRenderer(m_hInst, m_hWnd, startupParams)) - { - return false; - } - AZ_Assert(CryMemory::IsHeapValid(), "CryMemory must be valid after initializing renderer."); - if (m_env.pRenderer) - { - bool bMultiGPUEnabled = false; - m_env.pRenderer->EF_Query(EFQ_MultiGPUEnabled, bMultiGPUEnabled); - if (bMultiGPUEnabled) - { - LoadConfiguration("mgpu.cfg"); - } - } - - InlineInitializationProcessing("CSystem::Init InitRenderer"); - - if (m_env.pCryFont) - { - m_env.pCryFont->SetRendererProperties(m_env.pRenderer); - } - - AZ_Assert(m_env.pRenderer || startupParams.bSkipRenderer, "The renderer did not initialize correctly."); - } - #if !defined(AZ_RELEASE_BUILD) && defined(AZ_PLATFORM_ANDROID) m_thermalInfoHandler = AZStd::make_unique(); #endif @@ -2928,24 +2521,10 @@ AZ_POP_DISABLE_WARNING } } - ////////////////////////////////////////////////////////////////////////// - // FONT - ////////////////////////////////////////////////////////////////////////// - if (!startupParams.bSkipFont) - { - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Font initialization"); - if (!InitFont(startupParams)) - { - return false; - } - } - InlineInitializationProcessing("CSystem::Init InitFonts"); - - // The last update to the loading screen message was 'Initializing CryFont...' // Compiling the default system textures can be the lengthiest portion of // editor initialization, so it is useful to inform users that they are waiting on - // the necessary default textures to compile, and that they are not waiting on CryFont. + // the necessary default textures to compile. if (m_pUserCallback) { m_pUserCallback->OnInitProgress("First time asset processing - may take a minute..."); @@ -3040,28 +2619,6 @@ AZ_POP_DISABLE_WARNING return false; } - ////////////////////////////////////////////////////////////////////////// - // Init 3d engine - ////////////////////////////////////////////////////////////////////////// - if (loadLegacyRenderer && !startupParams.bSkipRenderer && !startupParams.bShaderCacheGen) - { - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Initializing 3D Engine"); - INDENT_LOG_DURING_SCOPE(); - - if (!Init3DEngine(startupParams)) - { - return false; - } - - // try flush to keep renderer busy - if (m_env.pRenderer) - { - m_env.pRenderer->TryFlush(); - } - - InlineInitializationProcessing("CSystem::Init Init3DEngine"); - } - ////////////////////////////////////////////////////////////////////////// // SERVICE NETWORK ////////////////////////////////////////////////////////////////////////// @@ -4223,24 +3780,3 @@ void CSystem::SetAssertVisible(bool bAssertVisble) { m_bIsAsserting = bAssertVisble; } - -bool CSystem::LoadFontInternal(IFFont*& font, const string& fontName) -{ - font = m_env.pCryFont->NewFont(fontName); - if (!font) - { - AZ_Assert(false, "Could not instantiate the default font."); - return false; - } - - ////////////////////////////////////////////////////////////////////////// - string szFontPath = "Fonts/" + fontName + ".font"; - - if (!font->Load(szFontPath.c_str())) - { - AZ_Error(AZ_TRACE_SYSTEM_WINDOW, false, "Could not load font: %s. Make sure the program is running from the correct working directory.", szFontPath.c_str()); - return false; - } - - return true; -} diff --git a/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl b/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl index b0c1a18b08..360ab93436 100644 --- a/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl +++ b/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl @@ -51,7 +51,7 @@ namespace AzFramework } template - bool Scene::UnsetSubsystem(const T& system) + bool Scene::UnsetSubsystem([[maybe_unused]] const T& system) { const AZ::TypeId& targetType = azrtti_typeid(); const size_t systemKeysCount = m_systemKeys.size(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Thumbnails/FolderThumbnail.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Thumbnails/FolderThumbnail.cpp index 78681f3b4b..71bac86c0a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Thumbnails/FolderThumbnail.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Thumbnails/FolderThumbnail.cpp @@ -10,8 +10,8 @@ * */ +#include #include -#include #include #include #include @@ -50,8 +50,8 @@ namespace AzToolsFramework ////////////////////////////////////////////////////////////////////////// // FolderThumbnail ////////////////////////////////////////////////////////////////////////// - static constexpr const char* FolderIconPath = "Icons/AssetBrowser/Folder_16.svg"; - static constexpr const char* GemIconPath = "Icons/AssetBrowser/GemFolder_16.svg"; + static constexpr const char* FolderIconPath = "Assets/Editor/Icons/AssetBrowser/Folder_16.svg"; + static constexpr const char* GemIconPath = "Assets/Editor/Icons/AssetBrowser/GemFolder_16.svg"; FolderThumbnail::FolderThumbnail(SharedThumbnailKey key) : Thumbnail(key) @@ -62,13 +62,8 @@ namespace AzToolsFramework auto folderKey = azrtti_cast(m_key.data()); AZ_Assert(folderKey, "Incorrect key type, excpected FolderThumbnailKey"); - const char* engineRoot = nullptr; - AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot); - AZ_Assert(engineRoot, "Engine Root not initialized"); const char* folderIcon = folderKey->IsGem() ? GemIconPath : FolderIconPath; - AZStd::string absoluteIconPath; - AZ::StringFunc::Path::Join(engineRoot, folderIcon, absoluteIconPath); - + auto absoluteIconPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / folderIcon; m_pixmap.load(absoluteIconPath.c_str()); m_state = m_pixmap.isNull() ? State::Failed : State::Ready; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 3f660bb73b..2570367049 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -770,8 +770,8 @@ namespace AzToolsFramework return false; } - Template& sourceTemplate = sourceTemplateReference->get(); #if defined(AZ_ENABLE_TRACING) + Template& sourceTemplate = sourceTemplateReference->get(); Template& targetTemplate = targetTemplateReference->get(); #endif diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/LoadingThumbnail.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/LoadingThumbnail.cpp index fb9d156b20..c29a9e4c6b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/LoadingThumbnail.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/LoadingThumbnail.cpp @@ -10,7 +10,7 @@ * */ -#include +#include #include #include @@ -23,18 +23,14 @@ namespace AzToolsFramework ////////////////////////////////////////////////////////////////////////// // LoadingThumbnail ////////////////////////////////////////////////////////////////////////// - static const char* LoadingIconPath = "Icons/AssetBrowser/in_progress.gif"; + static constexpr const char* LoadingIconPath = "Assets/Editor/Icons/AssetBrowser/in_progress.gif"; LoadingThumbnail::LoadingThumbnail() : Thumbnail(MAKE_TKEY(ThumbnailKey)) , m_angle(0) { - const char* engineRoot = nullptr; - AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot); - AZ_Assert(engineRoot, "Engine Root not initialized"); - AZStd::string iconPath; - AZ::StringFunc::Path::Join(engineRoot, LoadingIconPath, iconPath); - m_loadingMovie.setFileName(iconPath.c_str()); + auto absoluteIconPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / LoadingIconPath; + m_loadingMovie.setFileName(absoluteIconPath.c_str()); m_loadingMovie.setCacheMode(QMovie::CacheMode::CacheAll); m_loadingMovie.setScaledSize(QSize(LoadingThumbnailSize, LoadingThumbnailSize)); m_loadingMovie.start(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/MissingThumbnail.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/MissingThumbnail.cpp index 270a5b113f..39af7d9293 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/MissingThumbnail.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/MissingThumbnail.cpp @@ -10,18 +10,21 @@ * */ +#include +#include #include namespace AzToolsFramework { namespace Thumbnailer { - static const char* MISSING_ICON_PATH = "Icons/AssetBrowser/Default_16.svg"; + static constexpr const char* MissingIconPath = "Assets/Editor/Icons/AssetBrowser/Default_16.svg"; MissingThumbnail::MissingThumbnail() : Thumbnail(MAKE_TKEY(ThumbnailKey)) { - m_pixmap.load(MISSING_ICON_PATH); + auto absoluteIconPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / MissingIconPath; + m_pixmap.load(absoluteIconPath.c_str()); m_state = m_pixmap.isNull() ? State::Failed : State::Ready; } diff --git a/Code/LauncherUnified/StaticModules.in b/Code/LauncherUnified/StaticModules.in index 629973bdf4..03b22b076a 100644 --- a/Code/LauncherUnified/StaticModules.in +++ b/Code/LauncherUnified/StaticModules.in @@ -20,15 +20,6 @@ #include -#define DECLARE_CRYREGISTER_SINGLETON_CLASS(implclassname) \ - void* Get##implclassname##Factory(); - -DECLARE_CRYREGISTER_SINGLETON_CLASS(CEngineModule_Cry3DEngine) -DECLARE_CRYREGISTER_SINGLETON_CLASS(CEngineModule_CryFont) -DECLARE_CRYREGISTER_SINGLETON_CLASS(CEngineModule_CryRenderer) - -#undef DECLARE_CRYREGISTER_SINGLETON_CLASS - namespace AZ { class Module; @@ -39,14 +30,6 @@ ${extern_module_declarations} extern "C" void CreateStaticModules(AZStd::vector& modulesOut) { ${module_invocations} - // Call methods to avoid symbol striping -#define NON_STRIPPING_CALL(Module) \ - AZ_UNUSED(Get##Module##Factory()) - - NON_STRIPPING_CALL(CEngineModule_Cry3DEngine); - NON_STRIPPING_CALL(CEngineModule_CryFont); - NON_STRIPPING_CALL(CEngineModule_CryRenderer); -#undef NON_STRIPPING_CALL } #endif // AZ_MONOLITHIC_BUILD diff --git a/Code/LauncherUnified/launcher_generator.cmake b/Code/LauncherUnified/launcher_generator.cmake index 08ddd538fc..28429729e1 100644 --- a/Code/LauncherUnified/launcher_generator.cmake +++ b/Code/LauncherUnified/launcher_generator.cmake @@ -66,7 +66,6 @@ foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJEC set(game_build_dependencies ${game_gem_dependencies} Legacy::CrySystem - Legacy::CryFont ) if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) @@ -95,7 +94,6 @@ foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJEC set(server_build_dependencies ${game_gem_dependencies} Legacy::CrySystem - Legacy::CryFont ) endif() @@ -103,7 +101,6 @@ foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJEC set(game_runtime_dependencies Legacy::CrySystem - Legacy::CryFont ) endif() diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp index b777bb6930..c21aff046e 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp @@ -36,7 +36,6 @@ void RegisterReflectedVarHandlers() EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LocalStringPropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LightAnimationPropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew UserPopupWidgetHandler()); - EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LensFlareHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew ColorCurveHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew FloatCurveHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew MotionPropertyWidgetHandler()); diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp index bce244e06b..89bb66b08a 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp @@ -25,7 +25,6 @@ // Editor #include "GenericSelectItemDialog.h" #include "QtViewPaneManager.h" -#include "LensFlareEditor/LensFlareEditor.h" UserPropertyEditor::UserPropertyEditor(QWidget *pParent /*= nullptr*/) @@ -147,79 +146,6 @@ bool UserPopupWidgetHandler::ReadValuesIntoGUI(size_t index, UserPropertyEditor* #include -LensFlarePropertyWidget::LensFlarePropertyWidget(QWidget *pParent /*= nullptr*/) - :QWidget(pParent) -{ - m_valueEdit = new QLineEdit; - - QToolButton *mainButton = new QToolButton; - mainButton->setText("D"); - connect(mainButton, &QToolButton::clicked, this, &LensFlarePropertyWidget::OnEditClicked); - connect(m_valueEdit, &QLineEdit::editingFinished, m_valueEdit, [this] () {emit ValueChanged(m_valueEdit->text());}); - - QHBoxLayout *mainLayout = new QHBoxLayout(this); - mainLayout->addWidget(m_valueEdit, 1); - mainLayout->addWidget(mainButton); - mainLayout->setContentsMargins(1, 1, 1, 1); -} - -void LensFlarePropertyWidget::SetValue(const QString &value) -{ - m_valueEdit->setText(value); -} - -QString LensFlarePropertyWidget::GetValue() const -{ - return m_valueEdit->text(); -} - -void LensFlarePropertyWidget::OnEditClicked() -{ - const QtViewPane *lensFlarePane = GetIEditor()->OpenView(CLensFlareEditor::s_pLensFlareEditorClassName); - if (!lensFlarePane) - return; - - CLensFlareEditor *editor = FindViewPane(QtUtil::ToQString(CLensFlareEditor::s_pLensFlareEditorClassName)); - if (editor) - QTimer::singleShot(0, editor, SLOT(OnUpdateTreeCtrl())); -} - -QWidget* LensFlareHandler::CreateGUI(QWidget *pParent) -{ - LensFlarePropertyWidget* newCtrl = aznew LensFlarePropertyWidget(pParent); - connect(newCtrl, &LensFlarePropertyWidget::ValueChanged, newCtrl, [newCtrl]() - { - EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl); - }); - - return newCtrl; -} - -void LensFlareHandler::ConsumeAttribute(LensFlarePropertyWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) -{ - Q_UNUSED(GUI); Q_UNUSED(attrib); Q_UNUSED(attrValue); Q_UNUSED(debugName); -} - -void LensFlareHandler::WriteGUIValuesIntoProperty(size_t index, LensFlarePropertyWidget* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) -{ - Q_UNUSED(index); - Q_UNUSED(node); - CReflectedVarGenericProperty val = instance; - val.m_value = GUI->GetValue().toUtf8().data(); - instance = static_cast(val); -} - -bool LensFlareHandler::ReadValuesIntoGUI(size_t index, LensFlarePropertyWidget* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) -{ - Q_UNUSED(index); - Q_UNUSED(node); - CReflectedVarGenericProperty val = instance; - GUI->SetValue(val.m_value.c_str()); - return false; -} - - - QWidget* FloatCurveHandler::CreateGUI(QWidget *pParent) { CSplineCtrl *cSpline = new CSplineCtrl(pParent); diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.h b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.h index 00fb8e5f98..7ddbf6a338 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.h +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.h @@ -70,39 +70,6 @@ public: }; - -class LensFlarePropertyWidget : public QWidget -{ - Q_OBJECT -public: - AZ_CLASS_ALLOCATOR(LensFlarePropertyWidget, AZ::SystemAllocator, 0); - LensFlarePropertyWidget(QWidget *pParent = nullptr); - - void SetValue(const QString &value); - QString GetValue() const; - - void OnEditClicked(); - -signals: - void ValueChanged(const QString &value); - -private: - QLineEdit *m_valueEdit; -}; - -class LensFlareHandler : public QObject, public AzToolsFramework::PropertyHandler < CReflectedVarGenericProperty, LensFlarePropertyWidget> -{ -public: - AZ_CLASS_ALLOCATOR(LensFlareHandler, AZ::SystemAllocator, 0); - bool IsDefaultHandler() const override { return false; } - QWidget* CreateGUI(QWidget *pParent) override; - - AZ::u32 GetHandlerName(void) const override { return AZ_CRC("ePropertyFlare", 0x5ce803df); } - void ConsumeAttribute(LensFlarePropertyWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override; - void WriteGUIValuesIntoProperty(size_t index, LensFlarePropertyWidget* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override; - bool ReadValuesIntoGUI(size_t index, LensFlarePropertyWidget* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override; -}; - class FloatCurveHandler : public QObject, public AzToolsFramework::PropertyHandler < CReflectedVarSpline, CSplineCtrl> { public: diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp index b759b46ceb..055fc26a15 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp @@ -279,7 +279,6 @@ void ReflectedPropertyItem::SetVariable(IVariable *var) case ePropertyLocalString: case ePropertyLightAnimation: case ePropertyParticleName: - case ePropertyFlare: m_reflectedVarAdapter = new ReflectedVarGenericPropertyAdapter(desc.m_type); break; case ePropertyTexture: diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp index e0f7f29524..a805c07a2f 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp @@ -308,8 +308,6 @@ AZ::u32 CReflectedVarGenericProperty::handler() return AZ_CRC("ePropertyLightAnimation", 0x277097da); case ePropertyParticleName: return AZ_CRC("ePropertyParticleName", 0xf44c7133); - case ePropertyFlare: - return AZ_CRC("ePropertyFlare", 0x5ce803df); default: AZ_Assert(false, "No property handlers defined for the property type"); return AZ_CRC("Default", 0xe35e00df); diff --git a/Code/Sandbox/Editor/CryEditDoc.cpp b/Code/Sandbox/Editor/CryEditDoc.cpp index 8819c8b382..41c49ab026 100644 --- a/Code/Sandbox/Editor/CryEditDoc.cpp +++ b/Code/Sandbox/Editor/CryEditDoc.cpp @@ -52,7 +52,6 @@ #include "ActionManager.h" #include "Include/IObjectManager.h" #include "Material/MaterialManager.h" -#include "LensFlareEditor/LensFlareManager.h" #include "ErrorReportDialog.h" #include "SurfaceTypeValidator.h" #include "ShaderCache.h" @@ -360,8 +359,6 @@ void CCryEditDoc::Save(TDocMultiArchive& arrXmlAr) SerializeMissions(arrXmlAr, currentMissionName, false); //! Serialize material manager. GetIEditor()->GetMaterialManager()->Serialize((*arrXmlAr[DMAS_GENERAL]).root, (*arrXmlAr[DMAS_GENERAL]).bLoading); - //! Serialize LensFlare manager. - GetIEditor()->GetLensFlareManager()->Serialize((*arrXmlAr[DMAS_GENERAL]).root, (*arrXmlAr[DMAS_GENERAL]).bLoading); SerializeShaderCache((*arrXmlAr[DMAS_GENERAL_NAMED_DATA])); SerializeNameSelection((*arrXmlAr[DMAS_GENERAL])); @@ -524,14 +521,6 @@ void CCryEditDoc::Load(TDocMultiArchive& arrXmlAr, const QString& szFilename) GetIEditor()->GetMaterialManager()->Serialize((*arrXmlAr[DMAS_GENERAL]).root, (*arrXmlAr[DMAS_GENERAL]).bLoading); } - ////////////////////////////////////////////////////////////////////////// - // Load LensFlares. - ////////////////////////////////////////////////////////////////////////// - { - CAutoLogTime logtime("Load Flares"); - GetIEditor()->GetLensFlareManager()->Serialize((*arrXmlAr[DMAS_GENERAL]).root, (*arrXmlAr[DMAS_GENERAL]).bLoading); - } - ////////////////////////////////////////////////////////////////////////// // Load View Settings ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/DatabaseFrameWnd.cpp b/Code/Sandbox/Editor/DatabaseFrameWnd.cpp deleted file mode 100644 index 89843c8247..0000000000 --- a/Code/Sandbox/Editor/DatabaseFrameWnd.cpp +++ /dev/null @@ -1,1491 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "DatabaseFrameWnd.h" - -// Qt -#include -#include -#include -#include - -// AzToolsFramework -#include - -// Editor -#include "BaseLibraryManager.h" -#include "BaseLibraryItem.h" -#include "StringDlg.h" -#include "QtViewPaneManager.h" -#include "Undo/Undo.h" - -#include "ui_DatabaseFrameWnd.h" - - -class CUndoSelectLibraryUndo - : public IUndoObject -{ -public: - CUndoSelectLibraryUndo(const QString& libraryName, const QString& wndClssName) - { - m_LibraryName = libraryName; - m_WndClassName = wndClssName; - } - ~CUndoSelectLibraryUndo(){} - -protected: - int GetSize() - { - return sizeof(*this); - } - QString GetDescription() { return "Select database library."; }; - void Undo(bool bUndo) - { - SelectLibrary(bUndo); - } - void Redo() - { - SelectLibrary(true); - } - -private: - - void SelectLibrary(bool bUndo) - { - CDatabaseFrameWnd* pDatabaseEditor = FindViewPane(m_WndClassName); - if (!pDatabaseEditor) - { - return; - } - - QString libraryNameForUndo(m_LibraryName); - if (bUndo) - { - m_LibraryName = pDatabaseEditor->GetSelectedLibraryName(); - } - pDatabaseEditor->SelectLibrary(libraryNameForUndo); - } - - QString m_LibraryName; - QString m_WndClassName; -}; - -static const int LIBRARY_CB_WIDTH(150); - -CDatabaseFrameWnd::CDatabaseFrameWnd(CBaseLibraryManager* pItemManager, QWidget* pParent) - : AzQtComponents::DockMainWindow(pParent) - , m_pItemManager(pItemManager) - , ui(new Ui::DatabaseFrameWnd) - , m_initialized(false) - , m_pLibraryItemTreeModel(nullptr) -{ - ui->setupUi(this); - m_sortRecursionType = SORT_RECURSION_FULL; - m_pLibrary = NULL; - m_bLibsLoaded = false; - m_pCurrentItem = NULL; - - GetIEditor()->RegisterNotifyListener(this); - GetIEditor()->GetUndoManager()->AddListener(this); - - m_pLibraryListComboBox = new QComboBox; - m_pLibraryListComboBox->setFixedSize(LIBRARY_CB_WIDTH, 16); - ui->m_toolBar->insertWidget(ui->m_toolBar->actions()[4], m_pLibraryListComboBox); - connect(m_pLibraryListComboBox, static_cast(&QComboBox::currentIndexChanged), this, &CDatabaseFrameWnd::OnChangedLibrary); - - m_pLibraryListModel = new LibraryListModel(m_pItemManager, this); - m_pLibraryListComboBox->setModel(m_pLibraryListModel); - - connect(ui->actionDBAddLib, &QAction::triggered, this, &CDatabaseFrameWnd::OnAddLibrary); - connect(ui->actionDBDelLib, &QAction::triggered, this, &CDatabaseFrameWnd::OnRemoveLibrary); - connect(ui->actionDBRemove, &QAction::triggered, this, &CDatabaseFrameWnd::OnRemoveItem); - connect(ui->actionDBSave, &QAction::triggered, this, &CDatabaseFrameWnd::OnSave); - connect(ui->actionDBLoadLib, &QAction::triggered, this, &CDatabaseFrameWnd::OnLoadLibrary); - connect(ui->actionDBReload, &QAction::triggered, this, &CDatabaseFrameWnd::OnReloadLib); - connect(ui->actionDBReloadLib, &QAction::triggered, this, &CDatabaseFrameWnd::OnReloadLib); - connect(ui->actionDBCopy, &QAction::triggered, this, &CDatabaseFrameWnd::OnCopy); - connect(ui->actionDBPaste, &QAction::triggered, this, &CDatabaseFrameWnd::OnPaste); - connect(ui->actionDBClone, &QAction::triggered, this, &CDatabaseFrameWnd::OnClone); - connect(ui->actionUndo, &QAction::triggered, this, &CDatabaseFrameWnd::OnUndo); - connect(ui->actionRedo, &QAction::triggered, this, &CDatabaseFrameWnd::OnRedo); -} - -CDatabaseFrameWnd::~CDatabaseFrameWnd() -{ - // Block Signals to prevent changes in the m_pLibraryListComboBox - // from triggering OnChangedLibrary on teardown. - m_pLibraryListComboBox->blockSignals(true); - - m_pLibraryListModel->clear(); - - GetIEditor()->UnregisterNotifyListener(this); - GetIEditor()->GetUndoManager()->RemoveListener(this); -} - -void CDatabaseFrameWnd::InitTreeCtrl() -{ - QTreeView* treeView = GetTreeCtrl(); - - connect(treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &CDatabaseFrameWnd::OnSelChangedItemTree); - treeView->installEventFilter(this); -} - -void CDatabaseFrameWnd::ReloadLibs() -{ - if (!m_pItemManager) - { - return; - } - - SelectItem(0); - - m_pLibraryListModel->Reload(); - - if (m_pLibraryListComboBox) - { - SelectLibrary(m_pLibraryListComboBox->itemData(0, Qt::UserRole).value()); - } - - m_bLibsLoaded = true; -} - -void CDatabaseFrameWnd::ReloadItems() -{ - SelectItem(0); - m_selectedGroup = ""; - m_pCurrentItem = 0; - m_cpoSelectedLibraryItems.clear(); - if (m_pItemManager) - { - m_pItemManager->SetSelectedItem(0); - } - ReleasePreviewControl(); - - if (m_pLibrary && m_pLibraryItemTreeModel) - { - m_pLibraryItemTreeModel->Reload(m_pLibrary); - GetTreeCtrl()->expandAll(); - } -} - -void CDatabaseFrameWnd::SelectLibrary(const QString& library, bool bForceSelect) -{ - QWaitCursor wait; - if (GetSelectedLibraryName() != library || bForceSelect) - { - if (CUndo::IsRecording()) - { - CUndo::Record(new CUndoSelectLibraryUndo(GetSelectedLibraryName(), GetClassName())); - } - - SelectItem(0); - m_pLibrary = FindLibrary(library); - ReloadItems(); - } - if (m_pLibraryListComboBox) - { - m_pLibraryListComboBox->setCurrentIndex(GetComboBoxIndex(m_pLibrary)); - } -} - -void CDatabaseFrameWnd::SelectLibrary(CBaseLibrary* pItem, bool bForceSelect) -{ - QWaitCursor wait; - if (m_pLibrary != pItem || bForceSelect) - { - if (CUndo::IsRecording() && m_pLibrary) - { - CUndo::Record(new CUndoSelectLibraryUndo(GetSelectedLibraryName(), GetClassName())); - } - - SelectItem(0); - m_pLibrary = pItem; - ReloadItems(); - } - if (m_pLibraryListComboBox) - { - m_pLibraryListComboBox->setCurrentIndex(GetComboBoxIndex(pItem)); - } -} - -void CDatabaseFrameWnd::SelectItem(CBaseLibraryItem* item, bool bForceReload) -{ - if (item == m_pCurrentItem && !bForceReload) - { - return; - } - - QModelIndex index = m_pLibraryItemTreeModel->index(item); - if (index.isValid()) - { - GetTreeCtrl()->expand(index.parent()); - GetTreeCtrl()->setCurrentIndex(index); - } - else - { - GetTreeCtrl()->selectionModel()->clearCurrentIndex(); - } -} - -CBaseLibrary* CDatabaseFrameWnd::FindLibrary(const QString& libraryName) -{ - return (CBaseLibrary*)m_pItemManager->FindLibrary(libraryName); -} - -int CDatabaseFrameWnd::GetComboBoxIndex(CBaseLibrary* pLibrary) -{ - return m_pLibraryListComboBox->findData(QVariant::fromValue(pLibrary)); -} - -CBaseLibrary* CDatabaseFrameWnd::NewLibrary(const QString& libraryName) -{ - return (CBaseLibrary*)m_pItemManager->AddLibrary(libraryName, false); -} - -void CDatabaseFrameWnd::DeleteLibrary(CBaseLibrary* pLibrary) -{ - m_pItemManager->DeleteLibrary(pLibrary->GetName()); -} - -void CDatabaseFrameWnd::DeleteItem(CBaseLibraryItem* pItem) -{ - m_pItemManager->DeleteItem(pItem); -} - -void CDatabaseFrameWnd::OnAddLibrary() -{ - StringDlg dlg(tr("New Library Name"), this); - CUndo undo(tr("Add Database Library").toUtf8()); - if (dlg.exec() == QDialog::Accepted) - { - if (!dlg.GetString().isEmpty()) - { - SelectItem(0); - // Make new library. - QString library = dlg.GetString(); - NewLibrary(library); - ReloadLibs(); - SelectLibrary(library); - GetIEditor()->SetModifiedFlag(); - } - } -} - -void CDatabaseFrameWnd::OnRemoveLibrary() -{ - QString library = GetSelectedLibraryName(); - if (library.isEmpty()) - { - return; - } - if (m_pLibrary->IsModified()) - { - QString ask = tr("Save changes to the library %1?").arg(library); - if (QMessageBox::question(this, tr("Editor"), ask) == QMessageBox::Yes) - { - OnSave(); - } - } - QString ask = tr("When removing library All items contained in this library will be deleted.\r\nAre you sure you want to remove libarary %1?\r\n(Note: Library file will not be deleted from the disk)").arg(library); - if (QMessageBox::question(this, tr("Editor"), ask) == QMessageBox::Yes) - { - SelectItem(0); - DeleteLibrary(m_pLibrary); - m_pLibrary = 0; - ReleasePreviewControl(); - ReloadLibs(); - GetIEditor()->SetModifiedFlag(); - } -} - -void CDatabaseFrameWnd::OnAddItem() -{ -} - -void CDatabaseFrameWnd::OnRemoveItem() -{ - // When we have no set of selected items, it may be the case that we are - // dealing with old fashioned selection. If such is the case, let's deal - // with it using the old code system, which should be deprecated. - if (m_cpoSelectedLibraryItems.empty()) - { - if (m_pCurrentItem) - { - // Remove prototype from prototype manager and library. - QString str = tr("Delete %1?").arg(m_pCurrentItem->GetName()); - if (QMessageBox::question(this, tr("Delete Confirmation"), str) == QMessageBox::Yes) - { - CUndo undo(tr("Remove library item").toUtf8()); - TSmartPtr pCurrent = m_pCurrentItem; - DeleteItem(pCurrent); - m_pLibraryItemTreeModel->Remove(m_pCurrentItem); - GetIEditor()->SetModifiedFlag(); - SelectItem(0); - } - } - } - else // This is to be used when deleting multiple items... - { - QString strMessageString = tr("Delete the following items:\n"); - int nItemCount(0); - std::set::iterator itCurrentIterator; - std::set::iterator itEnd; - - itEnd = m_cpoSelectedLibraryItems.end(); - itCurrentIterator = m_cpoSelectedLibraryItems.begin(); - // For now, we have a maximum limit of 7 items per messagebox... - for (nItemCount = 0; nItemCount < 7; ++nItemCount, itCurrentIterator++) - { - if (itCurrentIterator == itEnd) - { - // As there were less than 7 items selected, we got to put them all - // into the formated string for the messagebox. - break; - } - strMessageString += QStringLiteral("%1\n").arg((*itCurrentIterator)->GetName()); - } - if (itCurrentIterator != itEnd) - { - strMessageString += QStringLiteral("..."); - } - - if (QMessageBox::question(this, tr("Delete Confirmation"), strMessageString) == QMessageBox::Yes) - { - for (itCurrentIterator = m_cpoSelectedLibraryItems.begin(); itCurrentIterator != itEnd; itCurrentIterator++) - { - CBaseLibraryItem* pCurrent = *itCurrentIterator; - DeleteItem(pCurrent); - m_pLibraryItemTreeModel->Remove(pCurrent); - } - m_cpoSelectedLibraryItems.clear(); - GetIEditor()->SetModifiedFlag(); - SelectItem(0); - } - } -} - -void CDatabaseFrameWnd::OnRenameItem() -{ - if (m_pCurrentItem) - { - StringGroupDlg dlg; - dlg.SetGroup(m_pCurrentItem->GetGroupName()); - dlg.SetString(m_pCurrentItem->GetShortName()); - if (dlg.exec() == QDialog::Accepted) - { - static bool warn = true; - if (warn) - { - warn = false; - QMessageBox::warning(this, tr("Warning"), tr("Levels referencing this archetype will need to be exported.")); - } - - CUndo undo(tr("Rename library item").toUtf8()); - TSmartPtr curItem = m_pCurrentItem; - SetItemName(curItem, dlg.GetGroup(), dlg.GetString()); - ReloadItems(); - SelectItem(curItem, true); - curItem->SetModified(); - //m_pCurrentItem->Update(); - } - GetIEditor()->SetModifiedFlag(); - } -} - -void CDatabaseFrameWnd::OnChangedLibrary() -{ - CBaseLibrary* pBaseLibrary = NULL; - if (m_pLibraryListComboBox) - { - pBaseLibrary = m_pLibraryListComboBox->currentData(Qt::UserRole).value(); - } - - if (pBaseLibrary && pBaseLibrary != m_pLibrary) - { - CUndo undo("Change database library"); - SelectLibrary(pBaseLibrary); - } -} - -void CDatabaseFrameWnd::OnExportLibrary() -{ - if (!m_pLibrary) - { - return; - } - - QString filename; - if (CFileUtil::SelectSaveFile("Library XML Files (*.xml)", "xml", (Path::GetEditingGameDataFolder() + "/Materials").c_str(), filename)) - { - XmlNodeRef libNode = XmlHelpers::CreateXmlNode("MaterialLibrary"); - m_pLibrary->Serialize(libNode, false); - XmlHelpers::SaveXmlNode(GetIEditor()->GetFileUtil(), libNode, filename.toStdString().c_str()); - } -} - -void CDatabaseFrameWnd::OnSave() -{ - if (m_bLibsLoaded) - { - m_pLibrary->SetModified(true); - m_pItemManager->SaveAllLibs(); - m_pLibrary->SetModified(false); - } -} - -void CDatabaseFrameWnd::OnReloadLib() -{ - if (!m_pLibrary) - { - return; - } - - QString libname = m_pLibrary->GetName(); - QString file = m_pLibrary->GetFilename(); - - //If the file we want to reload does not exist (and isn't the level library), we can't reload it - //Just display a warning to the user and stop the reload process - if (!CFileUtil::Exists(file, false) && !m_pLibrary->IsLevelLibrary()) - { - QString str = tr("Layer %1 does not exist on disk yet. Have you ever saved it?\nReloading layer is not possible!"). - arg(libname); - if (QMessageBox::information(this, tr("Editor"), str)) - { - return; - } - } - - if (m_pLibrary->IsModified()) - { - QString str = tr("Layer %1 was modified.\nReloading layer will discard all modifications to this library!"). - arg(libname); - if (QMessageBox::question(this, tr("Editor"), str) != QMessageBox::Yes) - { - return; - } - } - - //Don't try to delete/load level library from disk. - //It's managed by the level and there doesn't seem to be a way to "reload" it - if (!m_pLibrary->IsLevelLibrary()) - { - m_pItemManager->DeleteLibrary(libname); - m_pItemManager->LoadLibrary(file, true); - } - - ReloadLibs(); - SelectLibrary(libname); -} - -void CDatabaseFrameWnd::OnLoadLibrary() -{ - assert(m_pItemManager); - CUndo undo(tr("Load Database Library").toUtf8()); - LoadLibrary(); -} - -void CDatabaseFrameWnd::LoadLibrary() -{ - AssetSelectionModel selection = GetAssetSelectionModel(); - - AzToolsFramework::EditorRequests::Bus::Broadcast( - &AzToolsFramework::EditorRequests::BrowseForAssets, - selection); - if (selection.IsValid()) - { - GetIEditor()->SuspendUndo(); - IDataBaseLibrary* matLib = m_pItemManager->LoadLibrary(Path::FullPathToGamePath( - selection.GetResult()->GetFullPath().c_str()).c_str()); - GetIEditor()->ResumeUndo(); - ReloadLibs(); - if (matLib) - { - SelectLibrary((CBaseLibrary*)matLib); - } - } -} - -bool CDatabaseFrameWnd::SetItemName(CBaseLibraryItem* item, const QString& groupName, const QString& itemName) -{ - assert(item); - // Make prototype name. - QString name; - if (!groupName.isEmpty()) - { - name = groupName + "."; - } - name += itemName; - QString fullName = name; - if (item->GetLibrary()) - { - fullName = item->GetLibrary()->GetName() + "." + name; - } - IDataBaseItem* pOtherItem = m_pItemManager->FindItemByName(fullName); - if (pOtherItem && pOtherItem != item) - { - // Ensure uniqness of name. - Warning("Duplicate Item Name %s", name.toUtf8().data()); - return false; - } - else - { - item->SetName(name); - } - return true; -} - -void CDatabaseFrameWnd::OnSelChangedItemTree(const QModelIndex& index) -{ - CBaseLibraryItem* item = index.data(Qt::UserRole).value(); - - if (item) - { - if (item->GetLibrary() != m_pLibrary && item->GetLibrary()) - { - SelectLibrary((CBaseLibrary*)item->GetLibrary()); - } - } - - m_pCurrentItem = item; - - if (item) - { - m_selectedGroup = item->GetGroupName(); - } - else - { - m_selectedGroup = ""; - } - - m_pItemManager->SetSelectedItem(item); -} - -bool CDatabaseFrameWnd::eventFilter(QObject* watched, QEvent* event) -{ - if (event->type() != QEvent::KeyPress || watched != GetTreeCtrl()) - { - return QMainWindow::eventFilter(watched, event); - } - - QKeyEvent* keyEvent = static_cast(event); - - bool bCtrl = keyEvent->modifiers() == Qt::ControlModifier; - - if (keyEvent->matches(QKeySequence::Copy)) - { - OnCopy(); // Ctrl+C - } - else if (keyEvent->matches(QKeySequence::Paste)) - { - OnPaste(); // Ctrl+V - } - else if (keyEvent->matches(QKeySequence::Cut)) - { - OnCut(); // Ctrl+X - } - else if (bCtrl && keyEvent->key() == Qt::Key_D) - { - OnClone(); // Ctrl+D - } - else if (keyEvent->matches(QKeySequence::Delete)) - { - OnRemoveItem(); - } - else if (keyEvent->key() == Qt::Key_F2) - { - OnRenameItem(); - } - else if (keyEvent->key() == Qt::Key_Insert) - { - OnAddItem(); - } - else - { - return QMainWindow::eventFilter(watched, event); - } - - return true; -} - -void CDatabaseFrameWnd::OnUndo() -{ - GetIEditor()->Undo(); -} - -void CDatabaseFrameWnd::OnRedo() -{ - GetIEditor()->Redo(); -} - -void CDatabaseFrameWnd::OnCut() -{ - if (m_pCurrentItem) - { - OnCopy(); - OnRemoveItem(); - } -} - -void CDatabaseFrameWnd::OnClone() -{ - OnCopy(); - OnPaste(); -} - -void CDatabaseFrameWnd::DoesItemExist(const QString& itemName, bool& bOutExist) const -{ - for (int i = 0, iItemCount(m_pLibrary->GetItemCount()); i < iItemCount; ++i) - { - IDataBaseItem* pItem = m_pLibrary->GetItem(i); - if (pItem == NULL) - { - continue; - } - if (pItem->GetName() == itemName) - { - bOutExist = true; - return; - } - } - bOutExist = false; -} - -QString CDatabaseFrameWnd::MakeValidName(const QString& candidateName, AZStd::function FuncForCheck) const -{ - bool bCheck = false; - FuncForCheck(candidateName, bCheck); - if (!bCheck) - { - return candidateName; - } - - int nCounter = 0; - const int nEnoughBigNumber = 1000000; - do - { - QString counterBuffer; - counterBuffer = QString::number(nCounter); - QString newName = candidateName + counterBuffer; - FuncForCheck(newName, bCheck); - if (!bCheck) - { - return newName; - } - } while (nCounter++ < nEnoughBigNumber); - - assert(0 && "CDatabaseFrameWnd::MakeValidName()"); - return candidateName; -} - -void CDatabaseFrameWnd::DoesGroupExist(const QString& groupName, bool& bOutExist) const -{ - bOutExist = m_pLibraryItemTreeModel->DoesGroupExist(groupName); -} - -QString CDatabaseFrameWnd::GetSelectedLibraryName() const -{ - return m_pLibrary ? m_pLibrary->GetName() : ""; -} - -void CDatabaseFrameWnd::OnEditorNotifyEvent(EEditorNotifyEvent event) -{ - switch (event) - { - case eNotify_OnBeginNewScene: - m_bLibsLoaded = false; - // Clear all prototypes and libraries. - SelectItem(0); - if (m_pLibraryListComboBox) - { - m_pLibraryListComboBox->clear(); - } - m_pLibrary = nullptr; - break; - - case eNotify_OnEndSceneOpen: - m_bLibsLoaded = false; - ReloadLibs(); - break; - - case eNotify_OnCloseScene: - { - m_bLibsLoaded = false; - CUndo undo(tr("Close Database Library").toUtf8()); - GetTreeCtrl()->selectionModel()->clear(); - GetTreeCtrl()->clearSelection(); - m_pLibraryItemTreeModel->Clear(); - m_pCurrentItem = nullptr; - m_cpoSelectedLibraryItems.clear(); - } - break; - - case eNotify_OnDataBaseUpdate: - if (m_pLibrary && m_pLibrary->IsModified()) - { - ReloadItems(); - } - break; - } -} - -void CDatabaseFrameWnd::SignalNumUndoRedo(const unsigned int& numUndo, const unsigned int& numRedo) -{ - ui->actionUndo->setEnabled(numUndo > 0); - ui->actionRedo->setEnabled(numRedo > 0); -} - -void CDatabaseFrameWnd::showEvent(QShowEvent* event) -{ - if (!m_initialized) - { - OnInitDialog(); - m_initialized = true; - } - - QMainWindow::showEvent(event); -} - -LibraryListModel::LibraryListModel(CBaseLibraryManager* itemManager, QObject* pParent) - : QAbstractListModel(pParent) - , m_pItemManager(itemManager) -{ -} - -int LibraryListModel::rowCount(const QModelIndex& parent) const -{ - return parent.isValid() ? 0 : m_pItemManager->GetLibraryCount(); -} - -QVariant LibraryListModel::data(const QModelIndex& index, int role) const -{ - const int row = index.row(); - - if (row < 0 || row >= m_pItemManager->GetLibraryCount()) - { - return {}; - } - - auto library = static_cast(m_pItemManager->GetLibrary(row)); - - switch (role) - { - case Qt::DisplayRole: - { - QString name = library->GetName(); - if (library->IsModified()) - { - name += "*"; - } - return name; - } - - case Qt::UserRole: - return QVariant::fromValue(library); - } - - return {}; -} - -void LibraryListModel::Reload() -{ - beginResetModel(); - - const int count = m_pItemManager->GetLibraryCount(); - - for (int i = 0; i < count; i++) - { - CBaseLibrary* pLibrary = static_cast(m_pItemManager->GetLibrary(i)); - connect(pLibrary, &CBaseLibrary::Modified, this, &LibraryListModel::LibraryModified); - } - - endResetModel(); -} - -void LibraryListModel::clear() -{ - beginResetModel(); - endResetModel(); -} - -void LibraryListModel::LibraryModified(bool) -{ - CBaseLibrary* library = qobject_cast(sender()); - - const int count = m_pItemManager->GetLibraryCount(); - - for (int i = 0; i < count; i++) - { - CBaseLibrary* pLibrary = static_cast(m_pItemManager->GetLibrary(i)); - if (pLibrary == library) - { - emit dataChanged(index(i, 0), index(i, 0)); - } - } -} - -LibraryItemTreeModel::LibraryItemTreeModel(CDatabaseFrameWnd* pParent) - : QAbstractItemModel(pParent) - , m_dialog(pParent) -{ -} - -Qt::ItemFlags LibraryItemTreeModel::flags(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return Qt::ItemFlags(); - } - - Qt::ItemFlags flags = QAbstractItemModel::flags(index); - - flags |= Qt::ItemIsEditable; - - if (!index.internalPointer()) - { - flags |= Qt::ItemIsDropEnabled; - } - else - { - flags |= Qt::ItemIsDragEnabled; - } - - return flags; -} - -int LibraryItemTreeModel::columnCount(const QModelIndex&) const -{ - return 1; -} - -int LibraryItemTreeModel::rowCount(const QModelIndex& parent) const -{ - if (!parent.isValid()) - { - return m_groups.size(); - } - else - { - if (!parent.internalPointer() && parent.row() >= 0 && parent.row() < m_groups.size()) - { - auto entry = std::begin(m_groups); - std::advance(entry, parent.row()); - return entry->second->second.size(); - } - } - - return 0; -} - -QModelIndex LibraryItemTreeModel::parent(const QModelIndex& index) const -{ - if (index.isValid() && index.internalPointer()) - { - auto group = static_cast(index.internalPointer()); - auto entry = m_groups.find(group->first); - return createIndex(std::distance(std::begin(m_groups), entry), 0, nullptr); - } - - return {}; -} - -QModelIndex LibraryItemTreeModel::index(int row, int column, const QModelIndex& parent) const -{ - if (column > 0) - { - return {}; - } - - if (!parent.isValid()) - { - if (row >= 0 && row < m_groups.size()) - { - return createIndex(row, 0, nullptr); - } - } - else - { - if (!parent.internalPointer() && parent.row() >= 0 && parent.row() < m_groups.size()) - { - auto entry = std::begin(m_groups); - std::advance(entry, parent.row()); - - if (row >= 0 && row < entry->second->second.size()) - { - return createIndex(row, 0, const_cast(entry->second.get())); - } - } - } - - return {}; -} - -QVariant LibraryItemTreeModel::data(const QModelIndex& index, int role) const -{ - if (!index.isValid()) - { - return {}; - } - - if (!index.internalPointer()) - { - switch (role) - { - case Qt::DisplayRole: - { - auto entry = std::begin(m_groups); - std::advance(entry, index.row()); - return entry->first; - } - case Qt::UserRole: - return QVariant::fromValue(nullptr); - } - } - else - { - auto group = static_cast(index.internalPointer()); - auto item = group->second[index.row()]; - - switch (role) - { - case Qt::DisplayRole: - return item->GetShortName(); - case Qt::UserRole: - return QVariant::fromValue(item); - } - } - - return {}; -} - -void LibraryItemTreeModel::RenameItem(CBaseLibraryItem* item, const QString& fullName) -{ - QString prevFullName = item->GetFullName(); - item->SetName(fullName); - item->SetModified(); - emit itemRenamed(item, prevFullName); -} - -bool LibraryItemTreeModel::setData(const QModelIndex& index, const QVariant& value, int role) -{ - if (!index.isValid() || role != Qt::EditRole) - { - return false; - } - - QString text = value.toString(); - - if (text.isEmpty()) - { - return false; - } - - if (text.contains(QLatin1Char('.'))) - { - QMessageBox::warning(AzToolsFramework::GetActiveWindow(), tr("Warning"), tr("The name must not contain \".\"")); - return false; - } - - if (!index.internalPointer()) - { - // rename group - - auto sourceEntry = std::begin(m_groups); - std::advance(sourceEntry, index.row()); - - if (text == sourceEntry->first) - { - return false; - } - - if (m_groups.find(text) != std::end(m_groups)) - { - QMessageBox::warning(AzToolsFramework::GetActiveWindow(), tr("Warning"), tr("The identical name exists.")); - return false; - } - - int sourceRow = index.row(); - int targetRow = std::distance(std::begin(m_groups), m_groups.lower_bound(text)); - - if (targetRow < sourceRow || targetRow > sourceRow + 1) - { - beginMoveRows({}, sourceRow, sourceRow, {}, targetRow); - } - - auto targetEntry = m_groups.insert({ text, sourceEntry->second }).first; - targetEntry->second->first = text; - m_groups.erase(sourceEntry); - - if (targetRow < sourceRow || targetRow > sourceRow + 1) - { - endMoveRows(); - } - else - { - emit dataChanged(index, index); - } - - CUndo undo(tr("Rename FlareGroupItem").toUtf8()); - - auto group = targetEntry->second.get(); - - for (int row = 0; row < group->second.size(); row++) - { - auto item = group->second[row]; - QString name = QString("%1.%2").arg(text).arg(item->GetShortName()); - RenameItem(item, name); - } - } - else - { - // rename single item - - auto group = static_cast(index.internalPointer()); - auto& items = group->second; - - auto item = items[index.row()]; - - if (text == item->GetShortName()) - { - return false; - } - - QString name = QString("%1.%2").arg(item->GetGroupName(), text); - - if (std::find_if(std::begin(items), std::end(items), - [&](const CBaseLibraryItem* item) - { - return item->GetName() == name; - }) != std::end(items)) - { - QMessageBox::warning(AzToolsFramework::GetActiveWindow(), tr("Warning"), tr("The identical name exists.")); - return false; - } - - CUndo undo(tr("Rename FlareGroupItem").toUtf8()); - RenameItem(item, name); - - emit dataChanged(index, index); - } - - return true; -} - -QModelIndex LibraryItemTreeModel::index(CBaseLibraryItem* item) const -{ - if (!item) - { - return {}; - } - - auto entry = m_groups.find(item->GetGroupName()); - if (entry == std::end(m_groups)) - { - return {}; - } - - auto& items = entry->second->second; - - auto it = std::find(std::begin(items), std::end(items), item); - if (it == std::end(items)) - { - return {}; - } - - return createIndex(std::distance(std::begin(items), it), 0, const_cast(entry->second.get())); -} - -bool LibraryItemTreeModel::removeRows(int row, int count, const QModelIndex& parent) -{ - if (!parent.isValid()) - { - beginRemoveRows({}, row, row + count - 1); - - auto first = std::begin(m_groups); - std::advance(first, row); - - auto last = std::begin(m_groups); - std::advance(last, row + count); - - m_groups.erase(first, last); - - endRemoveRows(); - } - else - { - beginRemoveRows(parent, row, row + count - 1); - - auto entry = std::begin(m_groups); - std::advance(entry, parent.row()); - - auto& items = entry->second->second; - items.erase(std::begin(items) + row, std::begin(items) + row + count); - - endRemoveRows(); - - if (items.empty()) - { - beginRemoveRows({}, parent.row(), parent.row()); - m_groups.erase(entry); - endRemoveRows(); - } - } - - return true; -} - -static bool LibraryItemLess(const CBaseLibraryItem* left, const CBaseLibraryItem* right) -{ - QString leftName = left->GetName(); - QString rightName = right->GetName(); - return leftName.compare(rightName) < 0; -} - -void LibraryItemTreeModel::Clear() -{ - beginResetModel(); - - m_groups.clear(); - - endResetModel(); -} - -void LibraryItemTreeModel::Reload(CBaseLibrary* pLibrary) -{ - beginResetModel(); - - m_groups.clear(); - - for (int i = 0; i < pLibrary->GetItemCount(); i++) - { - auto item = static_cast(pLibrary->GetItem(i)); - - QString itemName = item->GetName(); - QString groupName = item->GetGroupName(); - - auto entry = m_groups.find(groupName); - - if (entry == std::end(m_groups)) - { - entry = m_groups.insert({ groupName, std::make_shared(groupName, std::vector()) }).first; - } - - auto& items = entry->second->second; - items.insert(std::upper_bound(std::begin(items), std::end(items), item, LibraryItemLess), item); - } - - endResetModel(); -} - -QString LibraryItemTreeModel::GetFullName(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return QString(); - } - - if (!index.internalPointer()) - { - auto entry = std::begin(m_groups); - std::advance(entry, index.row()); - return entry->first; - } - else - { - auto group = static_cast(index.internalPointer()); - auto item = group->second[index.row()]; - return item->GetName(); - } -} - -void LibraryItemTreeModel::Add(CBaseLibraryItem* item) -{ - QString groupName = item->GetGroupName(); - - auto entry = m_groups.find(groupName); - if (entry == std::end(m_groups)) - { - int row = std::distance(std::begin(m_groups), m_groups.lower_bound(groupName)); - - emit beginInsertRows({}, row, row); - entry = m_groups.insert({ groupName, std::make_shared(groupName, std::vector()) }).first; - emit endInsertRows(); - } - - QModelIndex parentIndex = createIndex(std::distance(std::begin(m_groups), entry), 0, nullptr); - auto& items = entry->second->second; - - if (std::find(std::begin(items), std::end(items), item) == std::end(items)) - { - auto it = std::upper_bound(std::begin(items), std::end(items), item, LibraryItemLess); - int row = std::distance(std::begin(items), it); - - emit beginInsertRows(parentIndex, row, row); - items.insert(it, item); - emit endInsertRows(); - } -} - -std::vector LibraryItemTreeModel::ChildItems(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return {}; - } - - if (!index.internalPointer()) - { - auto entry = std::begin(m_groups); - std::advance(entry, index.row()); - return entry->second->second; - } - else - { - auto group = static_cast(index.internalPointer()); - return { - group->second[index.row()] - }; - } -} - -bool LibraryItemTreeModel::Remove(CBaseLibraryItem* pItem) -{ - QModelIndex itemIndex = index(pItem); - if (!itemIndex.isValid()) - { - return false; - } - return removeRow(itemIndex.row(), itemIndex.parent()); -} - -void LibraryItemTreeModel::Rename(CBaseLibraryItem* item, const QString& groupName, const QString& shortName) -{ - if (groupName != item->GetGroupName()) - { - auto entry = m_groups.find(groupName); - - if (entry == std::end(m_groups)) - { - int row = std::distance(std::begin(m_groups), m_groups.lower_bound(groupName)); - - emit beginInsertRows({}, row, row); - entry = m_groups.insert({ groupName, std::make_shared(groupName, std::vector()) }).first; - emit endInsertRows(); - } - - MoveItem(item, createIndex(std::distance(std::begin(m_groups), entry), 0, nullptr)); - } - - QString name = QString("%1.%2").arg(groupName).arg(shortName); - RenameItem(item, name); - - QModelIndex itemIndex = index(item); - emit dataChanged(itemIndex, itemIndex); -} - -QModelIndex LibraryItemTreeModel::FindLibraryItemByFullName(const QString& fullName) const -{ - for (auto& entry : m_groups) - { - auto& group = *entry.second; - auto& items = group.second; - - auto it = std::find_if(std::begin(items), std::end(items), - [&](CBaseLibraryItem* item) - { - return item->GetName() == fullName; - }); - - if (it != std::end(items)) - { - return createIndex(std::distance(std::begin(items), it), 0, &group); - } - } - - return {}; -} - -bool LibraryItemTreeModel::DoesGroupExist([[maybe_unused]] const QString& groupName) const -{ -#if 0 - auto it = std::find_if( - std::begin(m_root->m_children), - std::end(m_root->m_children), - [&](const TreeNode* node) - { - return node->m_text.compare(groupName, Qt::CaseInsensitive) == 0; - }); - - return it != std::end(m_root->m_children); -#else - return false; -#endif -} - -QStringList LibraryItemTreeModel::mimeTypes() const -{ - QStringList mimeTypes; - mimeTypes << QStringLiteral("application/x-o3de-libraryitems"); - return mimeTypes; -} - -QString LibraryItemTreeModel::MakeValidName(const Group& group, const QString& baseName) const -{ - auto& items = group.second; - - QString name = baseName; - - int counter = 0; - - while (std::find_if(std::begin(items), std::end(items), - [&](CBaseLibraryItem* item) - { - return item->GetShortName() == name; - }) != std::end(items)) - { - name = QString("%1%2").arg(baseName).arg(counter); - ++counter; - } - - return name; -} - -bool LibraryItemTreeModel::MoveItem(CBaseLibraryItem* item, const QModelIndex& targetParent) -{ - if (!targetParent.isValid() || targetParent.internalPointer()) - { - return false; - } - - auto sourceEntry = m_groups.find(item->GetGroupName()); - - auto targetEntry = std::begin(m_groups); - std::advance(targetEntry, targetParent.row()); - - if (sourceEntry == targetEntry) - { - return false; - } - - auto& sourceItems = sourceEntry->second->second; - auto sourceIt = std::find(std::begin(sourceItems), std::end(sourceItems), item); - int sourceRow = std::distance(std::begin(sourceItems), sourceIt); - - auto& targetItems = targetEntry->second->second; - auto targetIt = std::upper_bound( - std::begin(targetItems), - std::end(targetItems), - item, - [](CBaseLibraryItem* left, CBaseLibraryItem* right) - { - QString leftShortName = left->GetShortName(); - QString rightShortName = right->GetShortName(); - return leftShortName.compare(rightShortName) < 0; - }); - int targetRow = std::distance(std::begin(targetItems), targetIt); - - QModelIndex sourceParent = createIndex(std::distance(std::begin(m_groups), sourceEntry), 0, nullptr); - - beginMoveRows(sourceParent, sourceRow, sourceRow, targetParent, targetRow); - targetItems.insert(targetIt, item); - sourceItems.erase(sourceIt); - endMoveRows(); - - if (sourceItems.empty()) - { - removeRow(sourceParent.row(), {}); - } - - return true; -} - -bool LibraryItemTreeModel::dropMimeData(const QMimeData* data, [[maybe_unused]] Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column, const QModelIndex& index) -{ - if (data->hasFormat("application/x-o3de-libraryitems")) - { - QByteArray array = data->data("application/x-o3de-libraryitems"); - - QModelIndex targetParent = index; - - if (!targetParent.isValid()) - { - return false; - } - - if (targetParent.internalPointer()) - { - targetParent = parent(targetParent); - } - - int count = array.size() / sizeof(CBaseLibraryItem*); - auto items = reinterpret_cast(array.data()); - - auto entry = std::begin(m_groups); - std::advance(entry, targetParent.row()); - - CUndo undo(tr("Copy/Cut & Paste for Lens Flare").toUtf8()); - - for (int i = 0; i < count; i++) - { - auto item = items[i]; - - QString shortName = MakeValidName(*entry->second, item->GetShortName()); - - if (MoveItem(item, targetParent)) - { - RenameItem(item, QString("%1.%2").arg(entry->first).arg(shortName)); - } - } - - return true; - } - - return false; -} - -QMimeData* LibraryItemTreeModel::mimeData(const QModelIndexList& indexes) const -{ - QByteArray array; - - for (auto& index : indexes) - { - auto item = static_cast(index.data(Qt::UserRole).value()); - - if (item) - { - array.append(reinterpret_cast(&item), sizeof(CBaseLibraryItem*)); - } - } - - if (array.isEmpty()) - { - return nullptr; - } - - QMimeData* data = new QMimeData; - data->setData(QStringLiteral("application/x-o3de-libraryitems"), array); - return data; -} - -Qt::DropActions LibraryItemTreeModel::supportedDragActions() const -{ - return Qt::MoveAction; -} - -Qt::DropActions LibraryItemTreeModel::supportedDropActions() const -{ - return Qt::MoveAction; -} - -#include diff --git a/Code/Sandbox/Editor/DatabaseFrameWnd.h b/Code/Sandbox/Editor/DatabaseFrameWnd.h deleted file mode 100644 index 71ef50191c..0000000000 --- a/Code/Sandbox/Editor/DatabaseFrameWnd.h +++ /dev/null @@ -1,250 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#pragma once -//////////////////////////////////////////////////////////////////////////// -// Crytek Engine Source File. -// Copyright (C), Crytek Studios, 2011. -// ------------------------------------------------------------------------- -// File name: DatabaseFrameWnd.h -// Created: 10/Dec/2012 by Jaesik. -//////////////////////////////////////////////////////////////////////////// -#ifndef CRYINCLUDE_EDITOR_DATABASEFRAMEWND_H -#define CRYINCLUDE_EDITOR_DATABASEFRAMEWND_H - -#if !defined(Q_MOC_RUN) -#include -#include -#include "Undo/IUndoManagerListener.h" -#include "BaseLibrary.h" - -#include -#include -#include -#include -#endif - -class QComboBox; -class QTreeView; -class QMimeData; - -class CBaseLibraryItem; -class CBaseLibraryManager; - -class LibraryListModel; -class LibraryItemTreeModel; - -namespace Ui { - class DatabaseFrameWnd; -} - -class CDatabaseFrameWnd - : public AzQtComponents::DockMainWindow - , public IEditorNotifyListener - , public IUndoManagerListener -{ - Q_OBJECT -public: - CDatabaseFrameWnd(CBaseLibraryManager* pItemManager, QWidget* pParent = nullptr); - virtual ~CDatabaseFrameWnd(); - - enum SortRecursionType - { - SORT_RECURSION_NONE = 1, - SORT_RECURSION_ITEM = 2, - SORT_RECURSION_FULL = 9999 - }; - - virtual void ReloadLibs(); - virtual void ReloadItems(); - virtual void SelectLibrary(const QString& library, bool bForceSelect = false); - virtual void SelectLibrary(CBaseLibrary* pItem, bool bForceSelect = false); - virtual void SelectItem(CBaseLibraryItem* item, bool bForceReload = false); - - virtual CBaseLibrary* FindLibrary(const QString& libraryName); - virtual CBaseLibrary* NewLibrary(const QString& libraryName); - virtual void DeleteLibrary(CBaseLibrary* pLibrary); - virtual void DeleteItem(CBaseLibraryItem* pItem); - - virtual void ReleasePreviewControl(){} - - virtual bool SetItemName(CBaseLibraryItem* item, const QString& groupName, const QString& itemName); - - void DoesItemExist(const QString& itemName, bool& bOutExist) const; - void DoesGroupExist(const QString& groupName, bool& bOutExist) const; - - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event) override; - - void SignalNumUndoRedo(const unsigned int& numUndo, const unsigned int& numRedo) override; - - QString GetSelectedLibraryName() const; - - virtual const char* GetClassName() = 0; - -protected: - int GetComboBoxIndex(CBaseLibrary* pLibrary); - - virtual void OnInitDialog() = 0; - - void showEvent(QShowEvent* event) override; - - void OnUndo(); - void OnRedo(); - - virtual void OnAddLibrary(); - virtual void OnRemoveLibrary(); - virtual void OnAddItem(); - virtual void OnRemoveItem(); - virtual void OnRenameItem(); - virtual void OnChangedLibrary(); - virtual void OnExportLibrary(); - virtual void OnSave(); - virtual void OnReloadLib(); - virtual void OnLoadLibrary(); - - void OnSelChangedItemTree(const QModelIndex& index); - bool eventFilter(QObject* watched, QEvent* event); - - virtual void OnCopy() = 0; - virtual void OnPaste() = 0; - virtual void OnCut(); - virtual void OnClone(); - - void InitTreeCtrl(); - - virtual AssetSelectionModel GetAssetSelectionModel() const = 0; - - void LoadLibrary(); - - QString MakeValidName(const QString& candidateName, AZStd::function cb) const; - - virtual QTreeView* GetTreeCtrl() = 0; - virtual const QTreeView* GetTreeCtrl() const = 0; - -private: - LibraryListModel* m_pLibraryListModel; - QComboBox* m_pLibraryListComboBox; - - bool m_bLibsLoaded; - -protected: - LibraryItemTreeModel* m_pLibraryItemTreeModel; - - //! Selected library. - _smart_ptr m_pLibrary; - - //! Last selected Item. (kept here for compatibility reasons) - // See comments on m_cpoSelectedLibraryItems for more details. - _smart_ptr m_pCurrentItem; - - // A set containing all the currently selected items - // (it's disabled for MOST, but not ALL cases). - // This should be the new standard way of storing selections as - // opposed to the former mean, it allows us to store multiple selections. - // The migration to this new style should be done according to the needs - // for multiple selection. - std::set m_cpoSelectedLibraryItems; - - //! Pointer to item manager. - CBaseLibraryManager* m_pItemManager; - SortRecursionType m_sortRecursionType; - QString m_selectedGroup; - - QScopedPointer ui; - - bool m_initialized; -}; - -class LibraryListModel - : public QAbstractListModel -{ - Q_OBJECT - -public: - LibraryListModel(CBaseLibraryManager* itemManager, QObject* pParent = nullptr); - - int rowCount(const QModelIndex& parent = {}) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - - void Reload(); - - void clear(); - -private: - void LibraryModified(bool bModified); - - CBaseLibraryManager* m_pItemManager; -}; - -class LibraryItemTreeModel - : public QAbstractItemModel -{ - Q_OBJECT - - using Group = std::pair >; - -public: - LibraryItemTreeModel(CDatabaseFrameWnd* pParent); - - QModelIndex parent(const QModelIndex& index) const override; - QModelIndex index(int row, int column, const QModelIndex& parent = {}) const override; - QModelIndex index(CBaseLibraryItem* pItem) const; - - int rowCount(const QModelIndex& parent) const override; - int columnCount(const QModelIndex& parent) const override; - - Qt::ItemFlags flags(const QModelIndex& index) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; - - bool removeRows(int row, int count, const QModelIndex& parent = {}) override; - - QStringList mimeTypes() const override; - bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; - QMimeData* mimeData(const QModelIndexList& indexes) const override; - - Qt::DropActions supportedDragActions() const override; - Qt::DropActions supportedDropActions() const override; - - void Clear(); - - void Reload(CBaseLibrary* library); - - void Add(CBaseLibraryItem* item); - bool Remove(CBaseLibraryItem* item); - - void Rename(CBaseLibraryItem* item, const QString& groupName, const QString& shortName); - - std::vector ChildItems(const QModelIndex& index) const; - - QString GetFullName(const QModelIndex& index) const; - - QModelIndex FindLibraryItemByFullName(const QString& fullName) const; - bool DoesGroupExist(const QString& groupName) const; - -signals: - void itemRenamed(CBaseLibraryItem* item, const QString& prevFullName); - -protected: - void RenameItem(CBaseLibraryItem* item, const QString& fullName); - QString MakeValidName(const Group& group, const QString& baseName) const; - bool MoveItem(CBaseLibraryItem* item, const QModelIndex& parent); - - CDatabaseFrameWnd* m_dialog; - - std::map > m_groups; -}; - -Q_DECLARE_METATYPE(CBaseLibrary*) - -#endif // CRYINCLUDE_EDITOR_DATABASEFRAMEWND_H diff --git a/Code/Sandbox/Editor/DatabaseFrameWnd.qrc b/Code/Sandbox/Editor/DatabaseFrameWnd.qrc deleted file mode 100644 index 37d97f5c9f..0000000000 --- a/Code/Sandbox/Editor/DatabaseFrameWnd.qrc +++ /dev/null @@ -1,35 +0,0 @@ - - - res/db_library_bar_00.png - res/db_library_bar_01.png - res/db_library_bar_02.png - res/db_library_bar_03.png - res/db_library_bar_04.png - res/db_library_bar_05.png - res/db_standart_00.png - res/db_standart_01.png - res/db_standart_02.png - res/db_standart_03.png - res/db_library_item_bar_00.png - res/db_library_item_bar_01.png - res/db_library_item_bar_02.png - res/db_library_item_bar_03.png - res/db_library_item_bar_04.png - res/db_library_item_bar_05.png - res/db_library_open.svg - res/db_library_save.svg - res/db_library_add.svg - res/db_library_delete.svg - res/db_library_refresh.svg - res/db_library_undo.svg - res/db_library_redo.svg - res/db_library_copy.svg - res/db_library_paste.svg - res/db_library_additem.svg - res/db_library_cloneitem.svg - res/db_library_removeitem.svg - res/db_library_assignitem.svg - res/db_library_getproperties.svg - res/db_library_reload.svg - - diff --git a/Code/Sandbox/Editor/DatabaseFrameWnd.ui b/Code/Sandbox/Editor/DatabaseFrameWnd.ui deleted file mode 100644 index 655de74a6e..0000000000 --- a/Code/Sandbox/Editor/DatabaseFrameWnd.ui +++ /dev/null @@ -1,279 +0,0 @@ - - - DatabaseFrameWnd - - - - 0 - 0 - 633 - 42 - - - - - Lens Flare Toolbar - - - - 32 - 32 - - - - false - - - TopToolBarArea - - - false - - - - - - - - - - StandartToolBar - - - - 32 - 32 - - - - false - - - TopToolBarArea - - - false - - - - - - - - - - ItemToolBar - - - - 32 - 32 - - - - false - - - TopToolBarArea - - - false - - - - - - - - - - - - - :/DatabaseFrameWnd/db_library_open.svg:/DatabaseFrameWnd/db_library_open.svg - - - Load Library - - - Load Library - - - - - - :/DatabaseFrameWnd/db_library_save.svg:/DatabaseFrameWnd/db_library_save.svg - - - Save Modified Libraries - - - Save Modified Libraries - - - - - - :/DatabaseFrameWnd/db_library_add.svg:/DatabaseFrameWnd/db_library_add.svg - - - Add Library - - - Add Library - - - - - - :/DatabaseFrameWnd/db_library_delete.svg:/DatabaseFrameWnd/db_library_delete.svg - - - Remove Library - - - Remove Library - - - - - - :/DatabaseFrameWnd/db_library_refresh.svg:/DatabaseFrameWnd/db_library_refresh.svg - - - Reload Library - - - Reload Library - - - - - false - - - - :/DatabaseFrameWnd/db_library_undo.svg:/DatabaseFrameWnd/db_library_undo.svg - - - Undo last operation - - - Undo - - - - - false - - - - :/DatabaseFrameWnd/db_library_redo.svg:/DatabaseFrameWnd/db_library_redo.svg - - - Redo last undo operation - - - Redo - - - - - - :/DatabaseFrameWnd/db_library_copy.svg:/DatabaseFrameWnd/db_library_copy.svg - - - Copy Item - - - Copy Item - - - - - - :/DatabaseFrameWnd/db_library_paste.svg:/DatabaseFrameWnd/db_library_paste.svg - - - Paste Item - - - Paste Item - - - - - - :/DatabaseFrameWnd/db_library_additem.svg:/DatabaseFrameWnd/db_library_additem.svg - - - Add New Item - - - Add New Item - - - - - - :/DatabaseFrameWnd/db_library_cloneitem.svg:/DatabaseFrameWnd/db_library_cloneitem.svg - - - Clone Library Item - - - Clone Library Item - - - - - - :/DatabaseFrameWnd/db_library_removeitem.svg:/DatabaseFrameWnd/db_library_removeitem.svg - - - Remove Item - - - Remove Item - - - - - - :/DatabaseFrameWnd/db_library_assignitem.svg:/DatabaseFrameWnd/db_library_assignitem.svg - - - Assign Item to Selected Objects - - - Assign Item to Selected Objects - - - - - - :/DatabaseFrameWnd/db_library_getproperties.svg:/DatabaseFrameWnd/db_library_getproperties.svg - - - Get Properties From Selection - - - Get Properties From Selection - - - - - - :/DatabaseFrameWnd/db_library_reload.svg:/DatabaseFrameWnd/db_library_reload.svg - - - Reload Item - - - Reload Item - - - - - - diff --git a/Code/Sandbox/Editor/GameExporter.cpp b/Code/Sandbox/Editor/GameExporter.cpp index 8a93dbedce..8f0b6f6d0f 100644 --- a/Code/Sandbox/Editor/GameExporter.cpp +++ b/Code/Sandbox/Editor/GameExporter.cpp @@ -34,9 +34,6 @@ #include "Objects/ObjectManager.h" #include "Objects/EntityObject.h" -#include "LensFlareEditor/LensFlareManager.h" -#include "LensFlareEditor/LensFlareLibrary.h" -#include "LensFlareEditor/LensFlareItem.h" #include @@ -210,7 +207,6 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE ExportLevelInfo(sLevelPath); - ExportLevelLensFlares(sLevelPath); ExportLevelResourceList(sLevelPath); ExportLevelUsedResourceList(sLevelPath); ExportLevelShaderCache(sLevelPath); @@ -554,67 +550,6 @@ void CGameExporter::ExportMaterials(XmlNodeRef& levelDataNode, const QString& pa m_numExportedMaterials = numMtls; } -////////////////////////////////////////////////////////////////////////// -void CGameExporter::ExportLevelLensFlares(const QString& path) -{ - GetIEditor()->SetStatusText(QObject::tr("Exporting Lens Flares...")); - std::vector objects; - GetIEditor()->GetObjectManager()->FindObjectsOfType(&CEntityObject::staticMetaObject, objects); - std::set flareNameSet; - for (int i = 0, iObjectSize(objects.size()); i < iObjectSize; ++i) - { - CEntityObject* pEntity = (CEntityObject*)objects[i]; - if (!pEntity->IsLight()) - { - continue; - } - QString flareName = pEntity->GetEntityPropertyString(CEntityObject::s_LensFlarePropertyName); - if (flareName.isEmpty() || flareName == "@root") - { - continue; - } - flareNameSet.insert(flareName); - } - - XmlNodeRef pRootNode = GetIEditor()->GetSystem()->CreateXmlNode("LensFlareList"); - pRootNode->setAttr("Version", FLARE_EXPORT_FILE_VERSION); - - CLensFlareManager* pLensManager = GetIEditor()->GetLensFlareManager(); - - if (CLensFlareLibrary* pLevelLib = (CLensFlareLibrary*)pLensManager->GetLevelLibrary()) - { - for (int i = 0; i < pLevelLib->GetItemCount(); i++) - { - CLensFlareItem* pItem = (CLensFlareItem*)pLevelLib->GetItem(i); - - if (flareNameSet.find(pItem->GetFullName()) == flareNameSet.end()) - { - continue; - } - - CBaseLibraryItem::SerializeContext ctx(pItem->CreateXmlData(), false); - pRootNode->addChild(ctx.node); - pItem->Serialize(ctx); - flareNameSet.erase(pItem->GetFullName()); - } - } - - std::set::iterator iFlareNameSet = flareNameSet.begin(); - for (; iFlareNameSet != flareNameSet.end(); ++iFlareNameSet) - { - QString flareName = *iFlareNameSet; - XmlNodeRef pFlareNode = GetIEditor()->GetSystem()->CreateXmlNode("LensFlare"); - pFlareNode->setAttr("name", flareName.toUtf8().data()); - pRootNode->addChild(pFlareNode); - } - - CCryMemFile lensFlareNames; - lensFlareNames.Write(pRootNode->getXMLData()->GetString(), pRootNode->getXMLData()->GetStringLength()); - - QString exportPathName = path + FLARE_EXPORT_FILE; - m_levelPak.m_pakFile.UpdateFile(exportPathName.toUtf8().data(), lensFlareNames); -} - ////////////////////////////////////////////////////////////////////////// void CGameExporter::ExportLevelResourceList(const QString& path) { diff --git a/Code/Sandbox/Editor/GameExporter.h b/Code/Sandbox/Editor/GameExporter.h index 87e24ef844..52731a7000 100644 --- a/Code/Sandbox/Editor/GameExporter.h +++ b/Code/Sandbox/Editor/GameExporter.h @@ -95,7 +95,6 @@ private: void ExportOcclusionMesh(const char* pszGamePath); void ExportMapInfo(XmlNodeRef& node); - void ExportLevelLensFlares(const QString& path); void ExportLevelResourceList(const QString& path); void ExportLevelUsedResourceList(const QString& path); void ExportLevelShaderCache(const QString& path); diff --git a/Code/Sandbox/Editor/IEditor.h b/Code/Sandbox/Editor/IEditor.h index e1f41b9f41..838f48573d 100644 --- a/Code/Sandbox/Editor/IEditor.h +++ b/Code/Sandbox/Editor/IEditor.h @@ -50,7 +50,6 @@ class CMaterialManager; class CMusicManager; class CMaterail; struct IEditorParticleManager; -class CLensFlareManager; class CEAXPresetManager; class CErrorReport; class CBaseLibraryItem; @@ -555,8 +554,6 @@ struct IEditor virtual IEditorPanelUtils* GetEditorPanelUtils() = 0; //! Get Music Manager. virtual CMusicManager* GetMusicManager() = 0; - //! Get Lens Flare Manager. - virtual CLensFlareManager* GetLensFlareManager() = 0; virtual float GetTerrainElevation(float x, float y) = 0; virtual Editor::EditorQtApplication* GetEditorQtApplication() = 0; virtual const QColor& GetColorByName(const QString& name) = 0; diff --git a/Code/Sandbox/Editor/IEditorImpl.cpp b/Code/Sandbox/Editor/IEditorImpl.cpp index a81aff86a9..060bf41189 100644 --- a/Code/Sandbox/Editor/IEditorImpl.cpp +++ b/Code/Sandbox/Editor/IEditorImpl.cpp @@ -60,7 +60,6 @@ AZ_POP_DISABLE_WARNING #include "ToolBox.h" #include "MainWindow.h" #include "Alembic/AlembicCompiler.h" -#include "LensFlareEditor/LensFlareManager.h" #include "UIEnumsDatabase.h" #include "Util/Ruler.h" #include "RenderHelpers/AxisHelper.h" @@ -170,7 +169,6 @@ CEditorImpl::CEditorImpl() , m_pToolBoxManager(nullptr) , m_pMaterialManager(nullptr) , m_pMusicManager(nullptr) - , m_pLensFlareManager(nullptr) , m_pErrorReport(nullptr) , m_pLasLoadedLevelErrorReport(nullptr) , m_pErrorsDlg(nullptr) @@ -230,7 +228,6 @@ CEditorImpl::CEditorImpl() m_pAnimationContext = new CAnimationContext; m_pImageUtil = new CImageUtil_impl(); - m_pLensFlareManager = new CLensFlareManager; m_pResourceSelectorHost.reset(CreateResourceSelectorHost()); m_pRuler = new CRuler; m_selectedRegion.min = Vec3(0, 0, 0); diff --git a/Code/Sandbox/Editor/IEditorImpl.h b/Code/Sandbox/Editor/IEditorImpl.h index 908136297b..3c440dd5fc 100644 --- a/Code/Sandbox/Editor/IEditorImpl.h +++ b/Code/Sandbox/Editor/IEditorImpl.h @@ -42,7 +42,6 @@ class CUndoManager; class CGameEngine; class CExportManager; class CErrorsDlg; -class CLensFlareManager; class CIconManager; class CBackgroundTaskManager; class CTrackViewSequenceManager; @@ -183,7 +182,6 @@ public: IDataBaseManager* GetDBItemManager(EDataBaseItemType itemType); CMaterialManager* GetMaterialManager() { return m_pMaterialManager; } CMusicManager* GetMusicManager() { return m_pMusicManager; }; - CLensFlareManager* GetLensFlareManager() { return m_pLensFlareManager; }; IBackgroundTaskManager* GetBackgroundTaskManager() override; IBackgroundScheduleManager* GetBackgroundScheduleManager() override; @@ -384,7 +382,6 @@ protected: CMaterialManager* m_pMaterialManager; CAlembicCompiler* m_pAlembicCompiler; CMusicManager* m_pMusicManager; - CLensFlareManager* m_pLensFlareManager; CErrorReport* m_pErrorReport; //! Contains the error reports for the last loaded level. CErrorReport* m_pLasLoadedLevelErrorReport; diff --git a/Code/Sandbox/Editor/LensFlareEditor/ILensFlareListener.h b/Code/Sandbox/Editor/LensFlareEditor/ILensFlareListener.h deleted file mode 100644 index 913faf2bb3..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/ILensFlareListener.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_ILENSFLARELISTENER_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_ILENSFLARELISTENER_H -#pragma once - -class CLensFlareItem; -class CLensFlareElement; - -class ILensFlareChangeItemListener -{ -public: - virtual void OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem) = 0; - virtual void OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem) = 0; -}; - -class ILensFlareChangeElementListener -{ -public: - virtual void OnLensFlareChangeElement(CLensFlareElement* pLensFlareElement) = 0; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_ILENSFLARELISTENER_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.cpp deleted file mode 100644 index d30db3f5f3..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareAtomicList.h" - -// Qt -#include -#include - -// Editor -#include "LensFlareUtil.h" -#include "Util/Image.h" -#include "Util/ImageUtil.h" - - -struct QLensFlareAtomicListModel::Item -{ - QString text; - QSize size; - QPixmap pixmap; - EFlareType flareType; -}; - -CLensFlareAtomicList::CLensFlareAtomicList(QWidget* parent) - : CImageListCtrl(parent) - , m_model(new QLensFlareAtomicListModel(this)) -{ - setDragEnabled(true); - setDragDropMode(DragOnly); - setModel(m_model.data()); -} - -CLensFlareAtomicList::~CLensFlareAtomicList() -{ -} - -QModelIndex QLensFlareAtomicListModel::InsertItem(const FlareInfo& flareInfo) -{ - Item* pPreviewItem = new Item; - - if (flareInfo.imagename) - { - CImageEx* pImage = new CImageEx(); - if (CImageUtil::LoadImage(flareInfo.imagename, *pImage)) - { - pImage->SwapRedAndBlue(); - pPreviewItem->size = QSize(pImage->GetWidth(), pImage->GetHeight()); - QImage img(reinterpret_cast(pImage->GetData()), pImage->GetWidth(), pImage->GetHeight(), QImage::Format_RGB32); - pPreviewItem->pixmap = QPixmap::fromImage(img.copy()); - } - - delete pImage; - } - - if (pPreviewItem->pixmap.isNull()) - { - pPreviewItem->pixmap = QPixmap(":/water.png"); - pPreviewItem->size = QSize(64, 64); - } - - pPreviewItem->text = flareInfo.name; - pPreviewItem->flareType = flareInfo.type; - - const int row = m_items.count(); - beginInsertRows(QModelIndex(), row, row); - m_items.append(pPreviewItem); - endInsertRows(); - - return index(row, 0); -} - -void QLensFlareAtomicListModel::Populate() -{ - Clear(); - const FlareInfoArray::Props array = FlareInfoArray::Get(); - for (size_t i = 0; i < array.size; ++i) - { - const FlareInfo& flareInfo(array.p[i]); - if (LensFlareUtil::IsElement(flareInfo.type)) - { - InsertItem(flareInfo); - } - } -} - -void CLensFlareAtomicList::FillAtomicItems() -{ - if (m_model) - { - m_model->Populate(); - } -} - -void CLensFlareAtomicList::updateGeometries() -{ - ClearItemGeometries(); - - if (!model()) - { - return; - } - - const int rowCount = model()->rowCount(); - - const int nPageHorz = viewport()->width(); - const int nPageVert = viewport()->height(); - - if (nPageHorz == 0 || nPageVert == 0 || rowCount <= 0) - { - return; - } - - const QSize& borderSize = BorderSize(); - int x = borderSize.width(); - int y = borderSize.height(); - - QSize itemSize = ItemSize(); - const int nTextHeight = fontMetrics().height(); - const int xMax = nPageHorz - borderSize.width(); - int itemHeightMax = 0; - - for (int row = 0; row < rowCount; ++row) - { - QModelIndex index = m_model->index(row, 0); - itemSize = index.data(Qt::SizeHintRole).toSize(); - - if ((x + itemSize.width()) > xMax) - { - y += itemHeightMax + borderSize.height() + nTextHeight; - x = borderSize.width(); - itemHeightMax = 0; - } - - if (itemSize.height() > itemHeightMax) - { - itemHeightMax = itemSize.height(); - } - - SetItemGeometry(index, QRect(QPoint(x, y), itemSize)); - - x += itemSize.width() + borderSize.width(); - } - - verticalScrollBar()->setPageStep(viewport()->height()); - verticalScrollBar()->setRange(0, (y + itemHeightMax - viewport()->height())); -} - -QLensFlareAtomicListModel::QLensFlareAtomicListModel(QObject* parent) - : QAbstractListModel(parent) -{ -} - -QLensFlareAtomicListModel::~QLensFlareAtomicListModel() -{ -} - -void QLensFlareAtomicListModel::Clear() -{ - qDeleteAll(m_items); - m_items.clear(); -} - -int QLensFlareAtomicListModel::rowCount(const QModelIndex& parent) const -{ - if (parent.isValid()) - { - return 0; - } - - return m_items.count(); -} - -QVariant QLensFlareAtomicListModel::data(const QModelIndex& index, int role) const -{ - Item* item; - if (!index.isValid()) - { - return QVariant(); - } - else - { - item = ItemFromIndex(index); - if (!item) - { - return QVariant(); - } - } - - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return item->text; - - case Qt::SizeHintRole: - return item->size; - - case Qt::DecorationRole: - return item->pixmap; - - case Qt::UserRole: - return item->flareType; - } - - return QVariant(); -} - -bool QLensFlareAtomicListModel::setData(const QModelIndex& index, const QVariant& value, int role) -{ - Item* item; - if (index.isValid()) - { - return false; - } - else - { - item = ItemFromIndex(index); - if (!item) - { - return false; - } - } - - switch (role) - { - case Qt::EditRole: - item->text = value.toString(); - break; - - case Qt::DecorationRole: - item->pixmap = value.value(); - break; - - case Qt::SizeHintRole: - item->size = value.toSize(); - break; - - default: - return false; - } - - emit dataChanged(index, index, QVector() << role); - return false; -} - -Qt::ItemFlags QLensFlareAtomicListModel::flags(const QModelIndex& index) const -{ - return QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled; -} - -EFlareType QLensFlareAtomicListModel::FlareTypeFromIndex(QModelIndex index) const -{ - Item* item; - if (!index.isValid()) - { - return eFT_Max; - } - else - { - item = ItemFromIndex(index); - if (!item) - { - return eFT_Max; - } - } - - return item->flareType; -} - -QLensFlareAtomicListModel::Item* QLensFlareAtomicListModel::ItemFromIndex(QModelIndex index) const -{ - if (!index.isValid()) - { - return nullptr; - } - - return m_items.at(index.row()); -} - -QStringList QLensFlareAtomicListModel::mimeTypes() const -{ - return { - QStringLiteral("application/x-o3de-flaretypes") - }; -} - -QMimeData* QLensFlareAtomicListModel::mimeData(const QModelIndexList& indexes) const -{ - QMimeData* data = new QMimeData(); - - QByteArray encoded; - QDataStream stream(&encoded, QIODevice::WriteOnly); - - for (const QModelIndex& index : indexes) - { - stream << static_cast(FlareTypeFromIndex(index)); - } - - data->setData(QStringLiteral("application/x-o3de-flaretypes"), encoded); - - return data; -} - -bool QLensFlareAtomicListModel::dropMimeData([[maybe_unused]] const QMimeData* data, [[maybe_unused]] Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column, [[maybe_unused]] const QModelIndex& parent) -{ - return false; -} - -Qt::DropActions QLensFlareAtomicListModel::supportedDragActions() const -{ - return Qt::CopyAction; -} - -#include diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.h deleted file mode 100644 index 5748ff07f7..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREATOMICLIST_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREATOMICLIST_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "Controls/ImageListCtrl.h" -#endif - -#if !defined(Q_MOC_RUN) -#include -#include -#endif - -class CLensFlareEditor; -class QLensFlareAtomicListModel; - -class CLensFlareAtomicList - : public CImageListCtrl -{ - Q_OBJECT -public: - CLensFlareAtomicList(QWidget* parent = nullptr); - virtual ~CLensFlareAtomicList(); - - void FillAtomicItems(); - -protected: - void updateGeometries() override; - -private: - QScopedPointer m_model; -}; - -class QLensFlareAtomicListModel - : public QAbstractListModel -{ - struct Item; - Q_OBJECT -public: - QLensFlareAtomicListModel(QObject* parent = nullptr); - ~QLensFlareAtomicListModel(); - - void Clear(); - void Populate(); - - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; - Qt::ItemFlags flags(const QModelIndex& index) const override; - - QStringList mimeTypes() const override; - QMimeData* mimeData(const QModelIndexList& indexes) const override; - bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; - Qt::DropActions supportedDragActions() const override; - - EFlareType FlareTypeFromIndex(QModelIndex index) const; - -protected: - QModelIndex InsertItem(const FlareInfo& flareInfo); - Item* ItemFromIndex(QModelIndex index) const; - -private: - QVector m_items; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREATOMICLIST_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.cpp deleted file mode 100644 index 763b5bf19b..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.cpp +++ /dev/null @@ -1,1225 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareEditor.h" - -// Qt -#include -#include - -// AzToolsFramework -#include -#include - -// AzQtComponents -#include -#include -#include - -// LmbrCentral -#include // for LmbrCentral::LensFlareAsset - -// Editor -#include "Clipboard.h" -#include "StringDlg.h" -#include "Settings.h" -#include "Include/IObjectManager.h" -#include "LensFlareView.h" -#include "LensFlareAtomicList.h" -#include "LensFlareElementTree.h" -#include "LensFlareManager.h" -#include "LensFlareItem.h" -#include "LensFlareLibrary.h" -#include "LensFlareUndo.h" -#include "LensFlareLightEntityTree.h" -#include "Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.h" -#include "ui_DatabaseFrameWnd.h" -#include "LyViewPaneNames.h" - - - - -CLensFlareEditor* CLensFlareEditor::s_pLensFlareEditor = NULL; -const char* CLensFlareEditor::s_pLensFlareEditorClassName = LyViewPane::LensFlareEditor; - -#define DISABLE_REFERENCETREE - -CLensFlareEditor::CLensFlareEditor(QWidget* pParent) - : CDatabaseFrameWnd(GetIEditor()->GetLensFlareManager(), pParent) - , m_pLensFlareView(NULL) - , m_pLensFlareAtomicList(NULL) - , m_pLensFlareElementTree(NULL) - , m_pWndProps(NULL) - , m_pLensFlareLightEntityTree(NULL) - , m_pLensFlareReferenceTree(NULL) - , m_LensFlareItemTree(NULL) -{ - assert(!s_pLensFlareEditor); - s_pLensFlareEditor = this; - - m_pLensFlareView = new CLensFlareView(this); - m_pLensFlareAtomicList = new CLensFlareAtomicList(this); - m_pLensFlareElementTree = new CLensFlareElementTree(this); - m_pWndProps = new ReflectedPropertyControl(this); - m_pWndProps->Setup(); - m_pLensFlareLightEntityTree = new CLensFlareLightEntityTree(this); -#ifndef DISABLE_REFERENCETREE - m_pLensFlareReferenceTree = new CLensFlareReferenceTree; -#endif - m_LensFlareItemTree = new CLensFlareItemTree(this); - - m_pLibraryItemTreeModel = new LensFlareItemTreeModel(this); - m_LensFlareItemTree->setModel(m_pLibraryItemTreeModel); - - setCentralWidget(m_pLensFlareView); - - setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); - setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); - setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); - setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); - - m_advancedDockManager = new AzQtComponents::FancyDocking(this, "lensFlareEditor"); - - addDockWidget(Qt::LeftDockWidgetArea, m_LensFlareItemTree, tr("Lens Flare Tree"), false); - addDockWidget(Qt::LeftDockWidgetArea, m_pLensFlareElementTree, tr("Element Tree"), false); - - addDockWidget(Qt::BottomDockWidgetArea, m_pLensFlareAtomicList, tr("Basic Set"), false); -#ifndef DISABLE_REFERENCETREE - addDockWidget(Qt::TopDockWidgetArea, m_pLensFlareReferenceTree, tr("Reference Tree"), false); -#endif - - addDockWidget(Qt::RightDockWidgetArea, m_pWndProps, tr("Properties"), false); - addDockWidget(Qt::RightDockWidgetArea, m_pLensFlareLightEntityTree, tr("Light Entities"), false); - - m_pLensFlareElementTree->RegisterListener(this); - m_pLensFlareElementTree->RegisterListener(m_pLensFlareView); - - m_pWndProps->ExpandAll(); - m_pWndProps->SetUpdateCallback(AZStd::bind(&CLensFlareEditor::OnUpdateProperties, this, AZStd::placeholders::_1)); - m_pWndProps->SetCallbackOnNonModified(false); - - connect(ui->actionDBAdd, &QAction::triggered, this, &CLensFlareEditor::OnAddItem); - connect(ui->actionDBAssignToSelection, &QAction::triggered, this, &CLensFlareEditor::OnAssignFlareToLightEntities); - connect(ui->actionDBGetFromSelection, &QAction::triggered, this, &CLensFlareEditor::OnGetFlareFromSelection); - - connect(m_pLibraryItemTreeModel, &LibraryItemTreeModel::itemRenamed, this, &CLensFlareEditor::OnItemTreeDataRenamed); - - AzQtComponents::StyleManager::setStyleSheet(this, "style:LensFlareEditor.qss"); -} - -CLensFlareEditor::~CLensFlareEditor() -{ - if (m_pLensFlareElementTree) - { - m_pLensFlareElementTree->UnregisterListener(this); - m_pLensFlareElementTree->UnregisterListener(m_pLensFlareView); - } - - ReleaseWindowsToBePutIntoPanels(); - s_pLensFlareEditor = NULL; -} - -QMenu* CLensFlareEditor::createPopupMenu() -{ - return QMainWindow::createPopupMenu(); -} - -void CLensFlareEditor::OnInitDialog() -{ - InitTreeCtrl(); - - connect(m_LensFlareItemTree->selectionModel(), &QItemSelectionModel::selectionChanged, this, &CLensFlareEditor::OnTvnItemSelChanged); - connect(m_LensFlareItemTree, &QWidget::customContextMenuRequested, this, &CLensFlareEditor::OnNotifyTreeRClick); - - m_pLensFlareAtomicList->FillAtomicItems(); - - ReloadLibs(); -} - -void CLensFlareEditor::addDockWidget(Qt::DockWidgetArea area, QWidget* widget, const QString& title, bool closable) -{ - QDockWidget* w = new AzQtComponents::StyledDockWidget(title); - w->setObjectName(widget->metaObject()->className()); - widget->setParent(w); - w->setWidget(widget); - if (!closable) - { - w->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); - } - QMainWindow::addDockWidget(area, w); -} - -void CLensFlareEditor::ReleaseWindowsToBePutIntoPanels() -{ - SAFE_DELETE(m_pWndProps); - SAFE_DELETE(m_pLensFlareAtomicList); - SAFE_DELETE(m_pLensFlareView); - SAFE_DELETE(m_pLensFlareElementTree); - SAFE_DELETE(m_pLensFlareLightEntityTree); -#ifndef DISABLE_REFERENCETREE - SAFE_DELETE(m_pLensFlareReferenceTree); -#endif -} - -const GUID& CLensFlareEditor::GetClassID() -{ - // {7e7a40e0-f0b8-4918-b94f-8cdd6c55f30b} - static const GUID guid = { - 0x7e7a40e0, 0xf0b8, 0x4918, { 0xb9, 0x4f, 0x8c, 0xdd, 0x6c, 0x55, 0xf3, 0x0b } - }; - return guid; -} - -void CLensFlareEditor::RegisterViewClass() -{ - AzToolsFramework::ViewPaneOptions options; - AzToolsFramework::RegisterViewPane(s_pLensFlareEditorClassName, LyViewPane::CategoryOther, options); - GetIEditor()->GetSettingsManager()->AddToolName("LensFlareEditor", "Lens Flare"); -} - -CLensFlareItem* CLensFlareEditor::GetSelectedLensFlareItem() const -{ - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return nullptr; - } - return static_cast(selected.first().data(Qt::UserRole).value()); -} - -void CLensFlareEditor::ResetElementTreeControl() -{ - m_pLensFlareElementTree->InvalidateLensFlareItem(); -} - -void CLensFlareEditor::SelectItem(CBaseLibraryItem* item, bool bForceReload) -{ - if (item != m_pCurrentItem || bForceReload) - { - //Ensure that the property window is emptied out whenever the selected library changes - m_pWndProps->RemoveAllItems(); - } - - CDatabaseFrameWnd::SelectItem(item, bForceReload); -} - -void CLensFlareEditor::OnTvnItemSelChanged(const QItemSelection& selected, const QItemSelection& deselected) -{ - QModelIndex hItem; - - QModelIndexList selectedIndexes = selected.indexes(); - if (!selectedIndexes.isEmpty()) - { - hItem = selectedIndexes.first(); - } - - QModelIndex hPrevItem; - - QModelIndexList deselectedIndexes = deselected.indexes(); - if (!deselectedIndexes.isEmpty()) - { - hPrevItem = deselectedIndexes.first(); - } - - SelectLensFlareItem(hItem, hPrevItem); - UpdateLensFlareItem(GetSelectedLensFlareItem()); -} - -void CLensFlareEditor::SelectLensFlareItem(const QModelIndex& hItem, const QModelIndex& hPrevItem) -{ - if (hPrevItem.isValid() && CUndo::IsRecording()) - { - QString fullItemName = m_pLibraryItemTreeModel->GetFullName(hPrevItem); - if (!fullItemName.isEmpty()) - { - CUndo::Record(new CUndoLensFlareItemSelectionChange(fullItemName)); - } - } - m_pWndProps->RemoveAllItems(); - if (!hItem.isValid()) - { - return; - } - CLensFlareItem* pSelectedLensFlareItem = static_cast(hItem.data(Qt::UserRole).value()); - SelectItem(pSelectedLensFlareItem); -} - -void CLensFlareEditor::SelectLensFlareItem(const QModelIndex& hItem) -{ - QModelIndex hPrevItem; - - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (!selected.isEmpty()) - { - hPrevItem = selected.first(); - } - - SelectLensFlareItem(hItem, hPrevItem); -} - -void CLensFlareEditor::SelectLensFlareItem(const QString& fullItemName) -{ - QModelIndex hNewItem = m_pLibraryItemTreeModel->FindLibraryItemByFullName(fullItemName); - if (!hNewItem.isValid()) - { - return; - } - - SelectLensFlareItem(hNewItem); -} - -void CLensFlareEditor::RemovePropertyItems() -{ - m_pWndProps->RemoveAllItems(); -} - -bool CLensFlareEditor::IsExistTreeItem(const QString& name, bool bExclusiveSelectedItem) -{ - CBaseLibraryItem* pSelectedItem = GetSelectedLensFlareItem(); - - for (int i = 0; i < m_pLibrary->GetItemCount(); i++) - { - CBaseLibraryItem* pItem = static_cast(m_pLibrary->GetItem(i)); - - if (!bExclusiveSelectedItem || pItem != pSelectedItem) - { - if (pItem->GetName() == name) - { - return true; - } - } - } - - return false; -} - -void CLensFlareEditor::RenameLensFlareItem(CLensFlareItem* pLensFlareItem, const QString& newGroupName, const QString& newShortName) -{ - if (pLensFlareItem == NULL || newShortName.isEmpty() || newGroupName.isEmpty()) - { - return; - } - - m_pLibraryItemTreeModel->Rename(pLensFlareItem, newGroupName, newShortName); -} - -IOpticsElementBasePtr CLensFlareEditor::FindOptics(const QString& itemPath, const QString& opticsPath) -{ - CLensFlareItem* pItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(itemPath); - if (pItem == NULL) - { - return NULL; - } - - IOpticsElementBasePtr pOptics = pItem->GetOptics(); - if (pOptics == NULL) - { - return NULL; - } - - return LensFlareUtil::FindOptics(pOptics, opticsPath); -} - -void CLensFlareEditor::UpdateLensOpticsNames(const QString& oldFullName, const QString& newFullName) -{ - std::vector pEntityObjects; - GetIEditor()->GetObjectManager()->FindObjectsOfType(&CEntityObject::staticMetaObject, pEntityObjects); - for (int i = 0, iObjectSize(pEntityObjects.size()); i < iObjectSize; ++i) - { - CEntityObject* pEntity = (CEntityObject*)pEntityObjects[i]; - if (pEntity == NULL) - { - continue; - } - if (pEntity->CheckFlags(OBJFLAG_DELETED)) - { - continue; - } - if (!pEntity->IsLight()) - { - continue; - } - if (oldFullName == pEntity->GetEntityPropertyString(CEntityObject::s_LensFlarePropertyName)) - { - pEntity->SetOpticsName(newFullName); - } - } -} - -void CLensFlareEditor::OnCopy() -{ - UpdateClipboard(FLARECLIPBOARDTYPE_COPY); -} - -void CLensFlareEditor::OnPaste() -{ - if (!m_pLibrary) - { - return; - } - - CClipboard clipboard(this); - if (clipboard.IsEmpty()) - { - return; - } - - XmlNodeRef clipboardXML = clipboard.Get(); - if (clipboardXML == NULL) - { - return; - } - - Paste(clipboardXML); -} - -void CLensFlareEditor::Paste(XmlNodeRef node) -{ - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - Paste(selected.first(), node); -} - -void CLensFlareEditor::Paste(const QModelIndex& hSelectedTreeItem, XmlNodeRef node) -{ - if (!m_pLibrary || node == NULL) - { - return; - } - - QString type; - node->getAttr("Type", type); - - QString sourceGroupName; - node->getAttr("GroupName", sourceGroupName); - - if (m_pLibrary == NULL) - { - return; - } - - bool bShouldCreateNewGroup(false); - if (!sourceGroupName.isEmpty()) - { - unsigned int nAnswer = CryMessageBox("Do you want to create a new group(YES) or add to the selected group(NO)?", "Question", MB_YESNOCANCEL); - if (nAnswer == IDCANCEL) - { - return; - } - bShouldCreateNewGroup = nAnswer == IDYES; - } - - QString targetGroupName; - - if (bShouldCreateNewGroup) - { - using namespace AZStd::placeholders; - targetGroupName = MakeValidName("NewGroup", AZStd::bind(&CDatabaseFrameWnd::DoesGroupExist, this, _1, _2)); - } - else - { - QModelIndex hTargetItem; - if (!m_pLibraryItemTreeModel->hasChildren(hSelectedTreeItem)) - { - hTargetItem = m_pLibraryItemTreeModel->parent(hSelectedTreeItem); - } - else - { - hTargetItem = hSelectedTreeItem; - } - - if (!hTargetItem.isValid()) - { - return; - } - - targetGroupName = m_pLibraryItemTreeModel->GetFullName(hTargetItem); - } - - CUndo undo(tr("Copy/Cut & Paste for Lens Flare").toUtf8()); - CLensFlareItem* pNewItem = NULL; - - for (int i = 0, iChildCount(node->getChildCount()); i < iChildCount; ++i) - { - LensFlareUtil::SClipboardData clipboardData; - clipboardData.FillThisFromXmlNode(node->getChild(i)); - - _smart_ptr pSourceItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(clipboardData.m_LensFlareFullPath); - if (pSourceItem == NULL) - { - continue; - } - - IOpticsElementBasePtr pSourceOptics = FindOptics(clipboardData.m_LensFlareFullPath, clipboardData.m_LensOpticsPath); - if (pSourceOptics == NULL) - { - continue; - } - - if (type == FLARECLIPBOARDTYPE_CUT) - { - if (clipboardData.m_From == LENSFLARE_ELEMENT_TREE) - { - LensFlareUtil::RemoveOptics(pSourceOptics); - } - else - { - DeleteItem(pSourceItem); - } - } - - QString sourceName; - if (clipboardData.m_From == LENSFLARE_ELEMENT_TREE) - { - sourceName = LensFlareUtil::GetShortName(pSourceOptics->GetName().c_str()); - } - else - { - sourceName = pSourceItem->GetShortName(); - } - - QString candidateName = targetGroupName + QString(".") + sourceName; - QString validName = MakeValidName(candidateName, - AZStd::bind(&CDatabaseFrameWnd::DoesItemExist, this, AZStd::placeholders::_1, AZStd::placeholders::_2)); - QString validShortName = LensFlareUtil::GetShortName(validName); - pNewItem = AddNewLensFlareItem(targetGroupName, validShortName); - assert(pNewItem); - if (pNewItem == NULL) - { - continue; - } - - if (LensFlareUtil::IsGroup(pSourceOptics->GetType())) - { - LensFlareUtil::CopyOptics(pSourceOptics, pNewItem->GetOptics(), true); - } - else - { - IOpticsElementBasePtr pNewOptics = LensFlareUtil::CreateOptics(pSourceOptics); - if (pNewOptics) - { - pNewItem->GetOptics()->AddElement(pNewOptics); - } - } - - if (type == FLARECLIPBOARDTYPE_CUT) - { - if (clipboardData.m_From == LENSFLARE_ITEM_TREE) - { - UpdateLensOpticsNames(pSourceItem->GetFullName(), pNewItem->GetFullName()); - } - if (pSourceItem != GetSelectedLensFlareItem()) - { - pSourceItem->UpdateLights(); - } - } - - LensFlareUtil::UpdateOpticsName(pNewItem->GetOptics()); - LensFlareUtil::ChangeOpticsRootName(pNewItem->GetOptics(), validShortName); - - ReloadItems(); - SelectLensFlareItem(m_pLibraryItemTreeModel->index(pNewItem), {}); - } -} - -void CLensFlareEditor::OnCut() -{ - UpdateClipboard(FLARECLIPBOARDTYPE_CUT); -} - -XmlNodeRef CLensFlareEditor::CreateXML(const char* type) const -{ - std::vector clipboardDataList; - QString groupName; - if (!GetClipboardDataList(clipboardDataList, groupName)) - { - return NULL; - } - return LensFlareUtil::CreateXMLFromClipboardData(type, groupName, false, clipboardDataList); -} - -void CLensFlareEditor::UpdateClipboard(const char* type) const -{ - std::vector clipboardDataList; - QString groupName; - if (!GetClipboardDataList(clipboardDataList, groupName)) - { - return; - } - LensFlareUtil::UpdateClipboard(type, groupName, false, clipboardDataList); -} - -bool CLensFlareEditor::GetClipboardDataList(std::vector& outList, QString& outGroupName) const -{ - CLensFlareLibrary* pLibrary = GetCurrentLibrary(); - if (pLibrary == NULL) - { - return false; - } - - std::vector clipboardDataList; - - CLensFlareItem* pLensFlareItem = GetSelectedLensFlareItem(); - if (pLensFlareItem) - { - clipboardDataList.push_back(LensFlareUtil::SClipboardData(LENSFLARE_ITEM_TREE, pLensFlareItem->GetFullName(), pLensFlareItem->GetShortName())); - } - else if (GetSelectedItemStatus() == eSIS_Group) - { - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return false; - } - outGroupName = selected.first().data(Qt::DisplayRole).toString(); - for (CBaseLibraryItem* pItem : m_pLibraryItemTreeModel->ChildItems(selected.first())) - { - pLensFlareItem = static_cast(pItem); - clipboardDataList.push_back(LensFlareUtil::SClipboardData(LENSFLARE_ITEM_TREE, pLensFlareItem->GetFullName(), pLensFlareItem->GetShortName())); - } - } - else - { - return false; - } - - outList = clipboardDataList; - - return true; -} - -void CLensFlareEditor::OnAddItem() -{ - if (!m_pLibrary) - { - return; - } - - StringGroupDlg dlg(tr("New Flare Name"), this); - dlg.SetGroup(m_selectedGroup); - - if (dlg.exec() != QDialog::Accepted || dlg.GetString().isEmpty()) - { - return; - } - - QString fullName = m_pItemManager->MakeFullItemName(m_pLibrary, dlg.GetGroup(), dlg.GetString()); - if (m_pItemManager->FindItemByName(fullName)) - { - Warning("Item with name %s already exist", fullName.toUtf8().data()); - return; - } - - CUndo undo(tr("Add flare library item").toUtf8()); - - CLensFlareItem* pNewLensFlare = AddNewLensFlareItem(dlg.GetGroup(), dlg.GetString()); - if (pNewLensFlare) - { - m_pLibraryItemTreeModel->Add(pNewLensFlare); - SelectItem(pNewLensFlare); - } -} - -CLensFlareItem* CLensFlareEditor::AddNewLensFlareItem(const QString& groupName, const QString& shortName) -{ - CLensFlareItem* pNewFlare = (CLensFlareItem*)m_pItemManager->CreateItem(m_pLibrary); - if (pNewFlare == NULL) - { - return NULL; - } - if (!SetItemName(pNewFlare, groupName, shortName)) - { - m_pItemManager->DeleteItem(pNewFlare); - return NULL; - } - pNewFlare->GetOptics()->SetName(pNewFlare->GetShortName().toUtf8().data()); - return pNewFlare; -} - -QModelIndex CLensFlareEditor::GetTreeLensFlareItem(CLensFlareItem* pItem) const -{ - return m_pLibraryItemTreeModel->index(pItem); -} - -void CLensFlareEditor::OnCopyNameToClipboard() -{ - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - QString itemName = m_pLibraryItemTreeModel->GetFullName(selected.first()); - CClipboard clipboard(this); - clipboard.PutString(itemName); -} - -void CLensFlareEditor::OnAssignFlareToLightEntities() -{ - CLensFlareItem* pLensFlareItem = GetSelectedLensFlareItem(); - if (pLensFlareItem == NULL) - { - return; - } - std::vector entityList; - LensFlareUtil::GetSelectedLightEntities(entityList); - - for (int i = 0, iEntityCount(entityList.size()); i < iEntityCount; ++i) - { - entityList[i]->ApplyOptics(pLensFlareItem->GetFullName(), pLensFlareItem->GetOptics()); - } - - m_pLensFlareLightEntityTree->OnLensFlareChangeItem(pLensFlareItem); -} - -void CLensFlareEditor::OnSelectAssignedObjects() -{ - std::vector lightEntities; - LensFlareUtil::GetLightEntityObjects(lightEntities); - - CLensFlareItem* pLensFlareItem = GetSelectedLensFlareItem(); - if (pLensFlareItem == NULL) - { - return; - } - - int iLightSize(lightEntities.size()); - std::vector assignedObjects; - assignedObjects.reserve(iLightSize); - - for (int i = 0; i < iLightSize; ++i) - { - CEntityObject* pLightEntity = lightEntities[i]; - if (pLightEntity == NULL) - { - continue; - } - - IOpticsElementBasePtr pTargetOptics = pLightEntity->GetOpticsElement(); - if (pTargetOptics == NULL) - { - continue; - } - - if (QString::compare(pLensFlareItem->GetFullName(), pTargetOptics->GetName().c_str(), Qt::CaseInsensitive)) - { - continue; - } - - assignedObjects.push_back(pLightEntity); - } - - if (assignedObjects.empty()) - { - return; - } - - GetIEditor()->ClearSelection(); - for (int i = 0, iAssignedObjectsSize(assignedObjects.size()); i < iAssignedObjectsSize; ++i) - { - GetIEditor()->SelectObject(assignedObjects[i]); - } -} - -void CLensFlareEditor::OnGetFlareFromSelection() -{ - CEntityObject* pEntity = LensFlareUtil::GetSelectedLightEntity(); - if (pEntity == NULL) - { - QMessageBox::warning(this, tr("Warning"), tr("Please select a light entity first.")); - return; - } - if (m_pLibrary == NULL) - { - return; - } - - QString fullFlareName = pEntity->GetEntityPropertyString(CEntityObject::s_LensFlarePropertyName); - int nDotPosition = fullFlareName.indexOf("."); - if (nDotPosition == -1) - { - return; - } - - QString libraryName = fullFlareName.left(nDotPosition); - if (m_pLibrary->GetName() != libraryName) - { - GetIEditor()->GetLensFlareManager()->LoadItemByName(fullFlareName); - SelectLibrary(libraryName); - } - - SelectItemByName(fullFlareName); -} - -void CLensFlareEditor::OnUpdateTreeCtrl() -{ - OnGetFlareFromSelection(); -} - -void CLensFlareEditor::OnNotifyTreeRClick() -{ - CLensFlareItem* pLensFlareItem = 0; - - QModelIndex hItem = LensFlareUtil::GetTreeItemByHitTest(*GetTreeCtrl()); - if (hItem.isValid()) - { - pLensFlareItem = static_cast(hItem.data(Qt::UserRole).value()); - } - - SelectItem(pLensFlareItem); - - bool bGrayedFlag = false; - if (!pLensFlareItem) - { - bGrayedFlag = true; - } - - CClipboard clipboard(this); - bool bPasteFlags = true; - if (clipboard.IsEmpty()) - { - bPasteFlags = false; - } - - bool bCopyPasteCloneFlag = true; - if (GetSelectedItemStatus() != eSIS_Flare && GetSelectedItemStatus() != eSIS_Group) - { - bCopyPasteCloneFlag = false; - } - - QMenu menu; - - QAction* actionDBCut = menu.addAction(tr("Cut")); - actionDBCut->setEnabled(bCopyPasteCloneFlag); - connect(actionDBCut, &QAction::triggered, this, &CLensFlareEditor::OnCut); - - QAction* actionDBCopy = menu.addAction(tr("Copy")); - actionDBCopy->setEnabled(bCopyPasteCloneFlag); - connect(actionDBCopy, &QAction::triggered, this, &CLensFlareEditor::OnCopy); - - QAction* actionDBPaste = menu.addAction(tr("Paste")); - actionDBPaste->setEnabled(bPasteFlags); - connect(actionDBPaste, &QAction::triggered, this, &CLensFlareEditor::OnPaste); - - QAction* actionDBClone = menu.addAction(tr("Clone")); - actionDBClone->setEnabled(bCopyPasteCloneFlag); - connect(actionDBClone, &QAction::triggered, this, &CLensFlareEditor::OnClone); - - menu.addSeparator(); - - QAction* actionDBRename = menu.addAction(tr("Rename\tF2")); - connect(actionDBRename, &QAction::triggered, this, &CLensFlareEditor::OnRenameItem); - - QAction* actionDBRemove = menu.addAction(tr("Delete\tDel")); - connect(actionDBRemove, &QAction::triggered, this, &CLensFlareEditor::OnRemoveItem); - - menu.addSeparator(); - - QAction* actionDBAssignToSelection = menu.addAction(tr("Assign to Selected Objects")); - actionDBAssignToSelection->setEnabled(!bGrayedFlag); - connect(actionDBAssignToSelection, &QAction::triggered, this, &CLensFlareEditor::OnAssignFlareToLightEntities); - - QAction* actionDBSelectAssignedObjects = menu.addAction(tr("Select Assigned Objects")); - actionDBSelectAssignedObjects->setEnabled(!bGrayedFlag); - connect(actionDBSelectAssignedObjects, &QAction::triggered, this, &CLensFlareEditor::OnSelectAssignedObjects); - - QAction* actionDBCopyNameToClipboard = menu.addAction(tr("Copy Name to ClipBoard")); - connect(actionDBCopyNameToClipboard, &QAction::triggered, this, &CLensFlareEditor::OnCopyNameToClipboard); - - menu.exec(QCursor::pos()); -} - -bool CLensFlareEditor::SelectItemByName(const QString& itemName) -{ - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(itemName); - if (pLensFlareItem == NULL) - { - return false; - } - - GetIEditor()->GetLensFlareManager()->SetSelectedItem(pLensFlareItem); - - SelectLensFlareItem(m_pLibraryItemTreeModel->index(pLensFlareItem)); - - return true; -} - - -void CLensFlareEditor::StartEditItem(const QModelIndex& hItem) -{ - if (!hItem.isValid()) - { - return; - } - GetTreeCtrl()->edit(hItem); -} - -bool CLensFlareEditor::GetFullLensFlareItemName(const QModelIndex& hItem, QString& outFullName) const -{ - if (!hItem.isValid()) - { - return false; - } - - outFullName = m_pLibraryItemTreeModel->GetFullName(hItem); - - return true; -} - -CLensFlareEditor::ESelectedItemStatus CLensFlareEditor::GetSelectedItemStatus() const -{ - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return eSIS_Unselected; - } - if (m_pLibraryItemTreeModel->hasChildren(selected.first())) - { - return eSIS_Group; - } - return eSIS_Flare; -} - -void CLensFlareEditor::SelectItemInLensFlareElementTreeByName(const QString& name) -{ - m_pLensFlareElementTree->SelectTreeItemByName(name); -} - -bool CLensFlareEditor::GetSelectedLensFlareName(QString& outName) const -{ - const CLensFlareElement* pElement = m_pLensFlareElementTree->GetCurrentLensFlareElement(); - if (pElement == NULL) - { - return false; - } - return pElement->GetName(outName); -} - -void CLensFlareEditor::ReloadItems() -{ - CDatabaseFrameWnd::ReloadItems(); - ResetElementTreeControl(); -} - -void CLensFlareEditor::OnRemoveItem() -{ - CLensFlareItem* pSelectedLensFlareItem = GetSelectedLensFlareItem(); - CUndo undo(tr("Remove Flare Group Item").toUtf8()); - - if (pSelectedLensFlareItem == NULL) - { - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - QModelIndex hLensFlareItem = selected.first(); - - QString fullLensFlareItemName = m_pLibraryItemTreeModel->GetFullName(hLensFlareItem); - - if (!fullLensFlareItemName.isEmpty()) - { - QString deleteMsgStr = tr("Delete %1?").arg(fullLensFlareItemName); - if (QMessageBox::question(this, tr("Confirmation"), deleteMsgStr) == QMessageBox::Yes) - { - CLensFlareLibrary* pLensFlareLibrary = GetCurrentLibrary(); - if (pLensFlareLibrary) - { - std::vector< _smart_ptr > deletedItems; - for (int i = 0, iItemCount(pLensFlareLibrary->GetItemCount()); i < iItemCount; ++i) - { - CLensFlareItem* pItem = (CLensFlareItem*)pLensFlareLibrary->GetItem(i); - if (pItem == NULL) - { - continue; - } - if (pItem->GetName().indexOf(fullLensFlareItemName) == -1) - { - continue; - } - QModelIndex hFlareItem = m_pLibraryItemTreeModel->index(pItem); - if (hFlareItem.isValid()) - { - UpdateLensOpticsNames(pItem->GetFullName(), ""); - deletedItems.push_back(pItem); - } - } - for (int i = 0, iDeleteItemSize(deletedItems.size()); i < iDeleteItemSize; ++i) - { - m_pLensFlareLightEntityTree->OnLensFlareDeleteItem(deletedItems[i]); - DeleteItem(deletedItems[i]); - } - - m_pLibraryItemTreeModel->removeRow(hLensFlareItem.row(), hLensFlareItem.parent()); - } - GetIEditor()->SetModifiedFlag(); - } - } - } - else - { - QString deleteMsgStr = tr("Delete %1?").arg(pSelectedLensFlareItem->GetName()); - // Remove prototype from prototype manager and library. - if (QMessageBox::question(this, tr("Confirmation"), deleteMsgStr) == QMessageBox::Yes) - { - m_pLensFlareLightEntityTree->OnLensFlareDeleteItem(pSelectedLensFlareItem); - - DeleteItem(pSelectedLensFlareItem); - - UpdateLensOpticsNames(pSelectedLensFlareItem->GetFullName(), ""); - - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (!selected.isEmpty()) - { - QModelIndex hLensFlareItem = selected.first(); - m_pLibraryItemTreeModel->removeRow(hLensFlareItem.row(), hLensFlareItem.parent()); - } - - m_pCurrentItem = NULL; - - GetIEditor()->SetModifiedFlag(); - SelectItem(0); - } - } -} - -void CLensFlareEditor::OnAddLibrary() -{ - StringDlg dlg(tr("Library Name"), this); - - dlg.SetCheckCallback([this](QString library) -> bool - { - QString path = m_pItemManager->MakeFilename(library); - if (CFileUtil::FileExists(path)) - { - QMessageBox::warning(this, tr("Library exists"), tr("Library '%1' already exists.").arg(library)); - return false; - } - return true; - }); - - if (dlg.exec() == QDialog::Accepted) - { - if (!dlg.GetString().isEmpty()) - { - SelectItem(0); - // Make new library. - QString library = dlg.GetString(); - NewLibrary(library); - ReloadLibs(); - SelectLibrary(library); - GetIEditor()->SetModifiedFlag(); - } - } -} - -void CLensFlareEditor::OnRenameItem() -{ - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - StartEditItem(selected.first()); -} - -void CLensFlareEditor::OnReloadLib() -{ - CDatabaseFrameWnd::OnReloadLib(); - CLensFlareLibrary* pLibrary = GetCurrentLibrary(); - if (pLibrary == NULL) - { - return; - } - for (int i = 0, iItemCount(pLibrary->GetItemCount()); i < iItemCount; ++i) - { - CLensFlareItem* pItem = (CLensFlareItem*)pLibrary->GetItem(i); - if (pItem == NULL) - { - continue; - } - pItem->UpdateLights(NULL); - } -} - -void CLensFlareEditor::RegisterLensFlareItemChangeListener(ILensFlareChangeItemListener* pListener) -{ - for (int i = 0, iSize(m_LensFlareChangeItemListenerList.size()); i < iSize; ++i) - { - if (m_LensFlareChangeItemListenerList[i] == pListener) - { - return; - } - } - m_LensFlareChangeItemListenerList.push_back(pListener); -} - -void CLensFlareEditor::UnregisterLensFlareItemChangeListener(ILensFlareChangeItemListener* pListener) -{ - auto iter = m_LensFlareChangeItemListenerList.begin(); - for (; iter != m_LensFlareChangeItemListenerList.end(); ++iter) - { - if (*iter == pListener) - { - m_LensFlareChangeItemListenerList.erase(iter); - return; - } - } -} - -void CLensFlareEditor::OnItemTreeDataRenamed(CBaseLibraryItem* pItem, const QString& prevFullName) -{ - CLensFlareItem* pLensFlareItem = static_cast(pItem); - - UpdateLensOpticsNames(prevFullName, pLensFlareItem->GetFullName()); - LensFlareUtil::ChangeOpticsRootName(pLensFlareItem->GetOptics(), pLensFlareItem->GetShortName()); - - if (pLensFlareItem == GetSelectedLensFlareItem()) - { - UpdateLensFlareItem(pLensFlareItem); - } - - GetIEditor()->GetLensFlareManager()->Modified(); -} - -void CLensFlareEditor::UpdateLensFlareItem(CLensFlareItem* pLensFlareItem) -{ - for (int i = 0, iSize(m_LensFlareChangeItemListenerList.size()); i < iSize; ++i) - { - m_LensFlareChangeItemListenerList[i]->OnLensFlareChangeItem(pLensFlareItem); - } -} - -void CLensFlareEditor::OnLensFlareChangeElement(CLensFlareElement* pLensFlareElement) -{ - ReflectedPropertyControl* pPropertyCtrl = m_pWndProps; - pPropertyCtrl->RemoveAllItems(); - - if (pLensFlareElement == NULL) - { - return; - } - - // Update properties in a property panel - if (pLensFlareElement && pLensFlareElement->GetProperties()) - { - pPropertyCtrl->AddVarBlock(pLensFlareElement->GetProperties()); - pPropertyCtrl->ExpandAllChildren(pPropertyCtrl->GetRootItem(), false); - pPropertyCtrl->setEnabled(true); - } -} - -void CLensFlareEditor::AddNewItemByAtomicOptics(const QModelIndex& hSelectedItem, EFlareType flareType) -{ - if (!LensFlareUtil::IsValidFlare(flareType)) - { - return; - } - - QString groupName; - QModelIndex hParentItem = hSelectedItem.parent(); - if (hParentItem.isValid()) - { - groupName = hParentItem.data(Qt::DisplayRole).toString(); - } - else - { - groupName = hSelectedItem.data(Qt::DisplayRole).toString(); - } - - FlareInfoArray::Props flareProps = FlareInfoArray::Get(); - QString itemName = MakeValidName(groupName + QString(".") + flareProps.p[flareType].name, - AZStd::bind(&CDatabaseFrameWnd::DoesItemExist, this, AZStd::placeholders::_1, AZStd::placeholders::_2)); - CLensFlareItem* pNewItem = AddNewLensFlareItem(groupName, LensFlareUtil::GetShortName(itemName)); - - if (pNewItem) - { - pNewItem->GetOptics()->AddElement(gEnv->pOpticsManager->Create(flareType)); - ReloadItems(); - SelectLensFlareItem(GetTreeLensFlareItem(pNewItem), {}); - } -} - -void CLensFlareEditor::OnUpdateProperties([[maybe_unused]] IVariable* var) -{ - GetIEditor()->GetLensFlareManager()->Modified(); -} - -AssetSelectionModel CLensFlareEditor::GetAssetSelectionModel() const -{ - return AssetSelectionModel::AssetTypeSelection(AZ::AzTypeInfo::Uuid()); -} - -LensFlareItemTreeModel::LensFlareItemTreeModel(CDatabaseFrameWnd* pParent) - : LibraryItemTreeModel(pParent) -{ -} - -QStringList LensFlareItemTreeModel::mimeTypes() const -{ - QStringList mimeTypes = LibraryItemTreeModel::mimeTypes(); - mimeTypes << QStringLiteral("application/x-o3de-flaretypes"); - return mimeTypes; -} - -bool LensFlareItemTreeModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) -{ - if (LibraryItemTreeModel::dropMimeData(data, action, row, column, parent)) - { - return true; - } - - if (data->hasFormat(QStringLiteral("application/x-o3de-flaretypes"))) - { - QByteArray encoded = data->data(QStringLiteral("application/x-o3de-flaretypes")); - QDataStream stream(&encoded, QIODevice::ReadOnly); - - while (!stream.atEnd()) - { - int flareType; - stream >> flareType; - static_cast(m_dialog)->AddNewItemByAtomicOptics(parent, static_cast(flareType)); - } - - return true; - } - - return false; -} - -Qt::ItemFlags LensFlareItemTreeModel::flags(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return Qt::ItemFlags(); - } - - return LibraryItemTreeModel::flags(index) | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled; -} - -Qt::DropActions LensFlareItemTreeModel::supportedDragActions() const -{ - return Qt::CopyAction | Qt::MoveAction; -} - -Qt::DropActions LensFlareItemTreeModel::supportedDropActions() const -{ - return Qt::CopyAction | Qt::MoveAction; -} - -#include diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.h deleted file mode 100644 index d5753fa332..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.h +++ /dev/null @@ -1,233 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREEDITOR_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREEDITOR_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "DatabaseFrameWnd.h" -#include "LensFlareUtil.h" -#include "ILensFlareListener.h" -#include "LensFlareItemTree.h" -#include "UserMessageDefines.h" -#endif - -#include - -namespace AzQtComponents -{ - class FancyDocking; -} - -class CLensFlareView; -class CLensFlareElementTree; -class CLensFlareAtomicList; -class CLensFlareElementPropertyView; -class CLensFlareItem; -class CLensFlareLibrary; -class ReflectedPropertyControl; -class CLensFlareLightEntityTree; -class CLensFlareReferenceTree; - -class CLensFlareEditor - : public CDatabaseFrameWnd - , public ILensFlareChangeElementListener -{ - Q_OBJECT - -public: - static const GUID& GetClassID(); - static void RegisterViewClass(); - - CLensFlareEditor(QWidget* pParent = nullptr); - ~CLensFlareEditor(); - - QMenu* createPopupMenu() override; - - // CDatabaseFrameWnd overrides... - virtual void SelectItem(CBaseLibraryItem* item, bool bForceReload = false) override; - - CLensFlareItem* GetSelectedLensFlareItem() const; - bool GetSelectedLensFlareName(QString& outName) const; - void UpdateLensFlareItem(CLensFlareItem* pLensFlareItem); - void ResetElementTreeControl(); - - CLensFlareLibrary* GetCurrentLibrary() const - { - if (m_pLibrary == NULL) - { - return NULL; - } - return (CLensFlareLibrary*)&(*m_pLibrary); - } - - bool IsExistTreeItem(const QString& name, bool bExclusiveSelectedItem = false); - void RenameLensFlareItem(CLensFlareItem* pLensFlareItem, const QString& newGroupName, const QString& newShortName); - - IOpticsElementBasePtr FindOptics(const QString& itemPath, const QString& opticsPath); - - CLensFlareElementTree* GetLensFlareElementTree() - { - return m_pLensFlareElementTree; - } - - CLensFlareView* GetLensFlareView() const - { - return m_pLensFlareView; - } - - CLensFlareItemTree* GetLensFlareItemTree() - { - return m_LensFlareItemTree; - } - - void RemovePropertyItems(); - - ReflectedPropertyControl* GetPropertyCtrl() - { - return m_pWndProps; - } - - void UpdateLensOpticsNames(const QString& oldFullName, const QString& newFullName); - void SelectItemInLensFlareElementTreeByName(const QString& name); - void ReloadItems(); - - void RegisterLensFlareItemChangeListener(ILensFlareChangeItemListener* pListener); - void UnregisterLensFlareItemChangeListener(ILensFlareChangeItemListener* pListener); - - bool SelectItemByName(const QString& itemName); - - static CLensFlareEditor* GetLensFlareEditor() - { - return s_pLensFlareEditor; - } - - bool GetFullSelectedFlareItemName(QString& outFullName) const - { - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return false; - } - return GetFullLensFlareItemName(selected.first(), outFullName); - } - - void SelectLensFlareItem(const QString& fullItemName); - - const char* GetClassName() - { - return s_pLensFlareEditorClassName; - } - - void Paste(XmlNodeRef node); - void Paste(const QModelIndex& index, XmlNodeRef node); - XmlNodeRef CreateXML(const char* type) const; - - static const char* s_pLensFlareEditorClassName; - - QTreeView* GetTreeCtrl() override - { - return m_LensFlareItemTree; - } - - const QTreeView* GetTreeCtrl() const override - { - return m_LensFlareItemTree; - } - - void AddNewItemByAtomicOptics(const QModelIndex& hSelectedItem, EFlareType flareType); - -public slots: - void OnUpdateTreeCtrl(); - -protected: - static CLensFlareEditor* s_pLensFlareEditor; - - void OnInitDialog() override; - - void OnCopy(); - void OnPaste(); - void OnCut(); - - void UpdateClipboard(const char* type) const; - bool GetClipboardDataList(std::vector& outList, QString& outGroupName) const; - void OnLensFlareChangeElement(CLensFlareElement* pLensFlareElement); - - void OnAddLibrary(); - void OnAssignFlareToLightEntities(); - void OnSelectAssignedObjects(); - void OnGetFlareFromSelection(); - void OnRenameItem(); - void OnAddItem(); - void OnRemoveItem(); - void OnCopyNameToClipboard(); - void OnNotifyTreeRClick(); - - void OnTvnItemSelChanged(const QItemSelection& selected, const QItemSelection& deselected); - void OnReloadLib(); - void ReleaseWindowsToBePutIntoPanels(); - void SelectLensFlareItem(const QModelIndex& hItem); - void SelectLensFlareItem(const QModelIndex& hItem, const QModelIndex& hPrevItem); - - void StartEditItem(const QModelIndex& hItem); - bool GetFullLensFlareItemName(const QModelIndex& hItem, QString& outFullName) const; - AssetSelectionModel GetAssetSelectionModel() const override; - - CLensFlareItem* AddNewLensFlareItem(const QString& groupName, const QString& shortName); - QModelIndex GetTreeLensFlareItem(CLensFlareItem* pItem) const; - - void OnItemTreeDataRenamed(CBaseLibraryItem* pItem, const QString& prevFullName); - - enum ESelectedItemStatus - { - eSIS_Unselected, - eSIS_Group, - eSIS_Flare - }; - ESelectedItemStatus GetSelectedItemStatus() const; - - void addDockWidget(Qt::DockWidgetArea area, QWidget* widget, const QString& title, bool closable = true); - void OnUpdateProperties(IVariable* var); - -private: - - CLensFlareView* m_pLensFlareView; - CLensFlareAtomicList* m_pLensFlareAtomicList; - CLensFlareElementTree* m_pLensFlareElementTree; - ReflectedPropertyControl* m_pWndProps; - CLensFlareLightEntityTree* m_pLensFlareLightEntityTree; - CLensFlareReferenceTree* m_pLensFlareReferenceTree; - CLensFlareItemTree* m_LensFlareItemTree; - - std::vector m_LensFlareChangeItemListenerList; - AzQtComponents::FancyDocking* m_advancedDockManager = nullptr; -}; - -class LensFlareItemTreeModel - : public LibraryItemTreeModel -{ - Q_OBJECT - -public: - LensFlareItemTreeModel(CDatabaseFrameWnd* pParent); - - Qt::ItemFlags flags(const QModelIndex& index) const override; - - QStringList mimeTypes() const override; - bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; - Qt::DropActions supportedDragActions() const override; - Qt::DropActions supportedDropActions() const override; -}; - -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREEDITOR_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElement.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareElement.cpp deleted file mode 100644 index a51c788a8b..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElement.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareElement.h" - -// Editor -#include "LensFlareElementTree.h" -#include "LensFlareUtil.h" -#include "LensFlareItem.h" -#include "LensFlareEditor.h" -#include "LensFlareView.h" -#include "LensFlareLibrary.h" - - -CLensFlareElement::CLensFlareElement() - : m_vars(NULL) - , m_pOpticsElement(NULL) - , m_pParent(NULL) -{ -} - -CLensFlareElement::~CLensFlareElement() -{ -} - -void CLensFlareElement::OnInternalVariableChange(IVariable* pVar) -{ - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - return; - } - - IFuncVariable* pFuncVar = LensFlareUtil::GetFuncVariable(pOptics, pVar->GetUserData().toInt()); - if (pFuncVar == NULL) - { - return; - } - - switch (pVar->GetType()) - { - case IVariable::INT: - { - int var(0); - pVar->Get(var); - if (pFuncVar->paramType == e_COLOR) - { - ColorF color(pFuncVar->GetColorF()); - color.a = (float)var / 255.0f; - pFuncVar->InvokeSetter((void*)&color); - } - else if (pFuncVar->paramType == e_INT) - { - if (LensFlareUtil::HaveParameterLowBoundary(pFuncVar->name.c_str())) - { - LensFlareUtil::BoundaryProcess(var); - } - pFuncVar->InvokeSetter((void*)&var); - if (pFuncVar->GetInt() != var) - { - pVar->Set(pFuncVar->GetInt()); - } - } - } - break; - case IVariable::BOOL: - { - if (pFuncVar->paramType == e_BOOL) - { - bool var; - pVar->Get(var); - pFuncVar->InvokeSetter((void*)&var); - } - } - break; - case IVariable::FLOAT: - { - if (pFuncVar->paramType == e_FLOAT) - { - float var; - pVar->Get(var); - pFuncVar->InvokeSetter((void*)&var); - } - } - break; - case IVariable::VECTOR2: - { - if (pFuncVar->paramType == e_VEC2) - { - Vec2 var; - pVar->Get(var); - pFuncVar->InvokeSetter((void*)&var); - } - } - break; - case IVariable::VECTOR: - { - Vec3 var; - pVar->Get(var); - if (pFuncVar->paramType == e_COLOR) - { - ColorF color(pFuncVar->GetColorF()); - color.r = var.x; - color.g = var.y; - color.b = var.z; - pFuncVar->InvokeSetter((void*)&color); - } - else if (pFuncVar->paramType == e_VEC3) - { - pFuncVar->InvokeSetter((void*)&var); - } - } - break; - case IVariable::VECTOR4: - { - if (pFuncVar->paramType == e_VEC4) - { - Vec4 var; - pVar->Get(var); - pFuncVar->InvokeSetter((void*)&var); - } - } - break; - case IVariable::STRING: - { - QString var; - pVar->Get(var); - if (pFuncVar->paramType == e_TEXTURE2D || pFuncVar->paramType == e_TEXTURE3D || pFuncVar->paramType == e_TEXTURE_CUBE) - { - var = var.trimmed(); - ITexture* pTexture = NULL; - if (!var.isEmpty()) - { - pTexture = GetIEditor()->GetRenderer()->EF_LoadTexture(var.toUtf8().data()); - } - pFuncVar->InvokeSetter((void*)pTexture); - if (pTexture) - { - pTexture->Release(); - } - } - } - break; - } - - UpdateLights(); -} - -bool CLensFlareElement::IsEnable() -{ - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - return false; - } - return pOptics->IsEnabled(); -} - -void CLensFlareElement::SetEnable(bool bEnable) -{ - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - return; - } - pOptics->SetEnabled(bEnable); - UpdateLights(); -} - -EFlareType CLensFlareElement::GetOpticsType() -{ - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - return eFT__Base__; - } - return pOptics->GetType(); -} - -bool CLensFlareElement::GetShortName(QString& outName) const -{ - QString fullName; - if (!GetName(fullName)) - { - return false; - } - int nPos = fullName.lastIndexOf('.'); - if (nPos == -1) - { - outName = fullName; - return true; - } - outName = fullName.right(fullName.length() - nPos - 1); - return true; -} - -void CLensFlareElement::UpdateLights() -{ - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - return; - } - if (GetLensFlareTree()) - { - if (GetLensFlareTree()->GetLensFlareItem()) - { - GetLensFlareTree()->GetLensFlareItem()->UpdateLights(pOptics); - } - } -} - -void CLensFlareElement::UpdateProperty(IOpticsElementBasePtr pOptics) -{ - std::vector funcs; - - if (CLensFlareElementTree* lensFlareTree = GetLensFlareTree(); lensFlareTree) - { - auto callbackItr = m_callbackCache.find(lensFlareTree); - if (callbackItr == m_callbackCache.end()) - { - IVariable::OnSetCallback callback = - AZStd::bind(&CLensFlareElementTree::OnInternalVariableChange, lensFlareTree, AZStd::placeholders::_1); - - auto result = m_callbackCache.insert(AZStd::make_pair(lensFlareTree, callback)); - callbackItr = result.first; - } - - funcs.push_back(&(callbackItr->second)); - } - - if (CLensFlareView* lensFlareView = GetLensFlareView(); lensFlareView) - { - auto callbackItr = m_callbackCache.find(lensFlareView); - if (callbackItr == m_callbackCache.end()) - { - IVariable::OnSetCallback callback = - AZStd::bind(&CLensFlareView::OnInternalVariableChange, lensFlareView, AZStd::placeholders::_1); - - auto result = m_callbackCache.insert(AZStd::make_pair(lensFlareView, callback)); - callbackItr = result.first; - } - - funcs.push_back(&(callbackItr->second)); - } - - if (CLensFlareLibrary* lensFlareLibrary = GetLensFlareLibrary(); lensFlareLibrary) - { - auto callbackItr = m_callbackCache.find(lensFlareLibrary); - if (callbackItr == m_callbackCache.end()) - { - IVariable::OnSetCallback callback = - AZStd::bind(&CLensFlareLibrary::OnInternalVariableChange, lensFlareLibrary, AZStd::placeholders::_1); - - auto result = m_callbackCache.insert(AZStd::make_pair(lensFlareLibrary, callback)); - callbackItr = result.first; - } - - funcs.push_back(&(callbackItr->second)); - } - - LensFlareUtil::SetVariablesTemplateFromOptics(pOptics, m_vars, funcs); -} - -CLensFlareElementTree* CLensFlareElement::GetLensFlareTree() const -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return NULL; - } - return pEditor->GetLensFlareElementTree(); -} - -CLensFlareView* CLensFlareElement::GetLensFlareView() const -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return NULL; - } - return pEditor->GetLensFlareView(); -} - -CLensFlareLibrary* CLensFlareElement::GetLensFlareLibrary() const -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return NULL; - } - return pEditor->GetCurrentLibrary(); -} - -CLensFlareElement* CLensFlareElement::GetParent() const -{ - return m_pParent; -} - -void CLensFlareElement::SetParent(CLensFlareElement* pParent) -{ - m_pParent = pParent; -} - -int CLensFlareElement::GetChildCount() const -{ - return m_children.size(); -} - -CLensFlareElement* CLensFlareElement::GetChildAt(int nPos) const -{ - if (nPos < 0 || nPos >= m_children.size()) - { - return nullptr; - } - return m_children[nPos]; -} - -void CLensFlareElement::AddChild(CLensFlareElement* pElement) -{ - pElement->SetParent(this); - m_children.push_back(pElement); -} - -void CLensFlareElement::InsertChild(int nPos, CLensFlareElement* pElement) -{ - pElement->SetParent(this); - m_children.insert(std::begin(m_children) + nPos, pElement); -} - -void CLensFlareElement::RemoveChild(int nPos) -{ - m_children.erase(std::begin(m_children) + nPos); -} - -void CLensFlareElement::SwapChildren(int nPos1, int nPos2) -{ - std::swap(m_children[nPos1], m_children[nPos2]); -} - -void CLensFlareElement::RemoveAllChildren() -{ - m_children.clear(); -} - -int CLensFlareElement::GetChildIndex(const CLensFlareElement* pElement) const -{ - auto it = std::find_if( - std::begin(m_children), - std::end(m_children), - [=](const LensFlareElementPtr& pChild) - { - return pChild.get() == pElement; - }); - - if (it != std::end(m_children)) - { - return std::distance(std::begin(m_children), it); - } - else - { - return -1; - } -} - -int CLensFlareElement::GetRow() const -{ - return m_pParent ? m_pParent->GetChildIndex(this) : 0; -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElement.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareElement.h deleted file mode 100644 index 9860fa597e..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElement.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREELEMENT_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREELEMENT_H -#pragma once - -#include "IFlares.h" - -#include "Util/Variable.h" - -class CLensFlareElementTree; -class CLensFlareView; -class CLensFlareLibrary; - -class CLensFlareElement - : public CRefCountBase -{ -public: - - typedef _smart_ptr LensFlareElementPtr; - typedef std::vector LensFlareElementList; - - CLensFlareElement(); - virtual ~CLensFlareElement(); - - CVarBlock* GetProperties() const - { - return m_vars; - } - - void OnInternalVariableChange(IVariable* pVar); - - bool IsEnable(); - void SetEnable(bool bEnable); - EFlareType GetOpticsType(); - - bool GetName(QString& outName) const - { - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - return false; - } - outName = pOptics->GetName(); - return true; - } - - bool GetShortName(QString& outName) const; - IOpticsElementBasePtr GetOpticsElement() const - { - return m_pOpticsElement; - } - void SetOpticsElement(IOpticsElementBasePtr pOptics) - { - m_pOpticsElement = pOptics; - UpdateProperty(m_pOpticsElement); - } - - CLensFlareElement* GetParent() const; - void SetParent(CLensFlareElement* pParent); - - int GetChildCount() const; - CLensFlareElement* GetChildAt(int nPos) const; - - void AddChild(CLensFlareElement* pElement); - void InsertChild(int nPos, CLensFlareElement* pElement); - - void RemoveChild(int nPos); - void RemoveAllChildren(); - - void SwapChildren(int nPos1, int nPos2); - - int GetChildIndex(const CLensFlareElement* pChild) const; - int GetRow() const; - -private: - - void UpdateLights(); - void UpdateProperty(IOpticsElementBasePtr pOptics); - - CLensFlareElementTree* GetLensFlareTree() const; - CLensFlareView* GetLensFlareView() const; - CLensFlareLibrary* GetLensFlareLibrary() const; - -private: - - IOpticsElementBasePtr m_pOpticsElement; - CVarBlockPtr m_vars; - - CLensFlareElement* m_pParent; - LensFlareElementList m_children; - - AZStd::map m_callbackCache; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREELEMENT_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.cpp deleted file mode 100644 index be687a5469..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.cpp +++ /dev/null @@ -1,1393 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareElementTree.h" - -// Qt -#include -#include -#include - -// Editor -#include "Clipboard.h" -#include "LensFlareItem.h" -#include "LensFlareManager.h" -#include "LensFlareUndo.h" -#include "LensFlareEditor.h" -#include "LensFlareLibrary.h" - - -template -static CLensFlareElement* FindLensFlareElement(CLensFlareElement* pRoot, Predicate pred) -{ - if (pred(pRoot)) - { - return pRoot; - } - - for (int i = 0, childCount = pRoot->GetChildCount(); i < childCount; i++) - { - if (CLensFlareElement* pElement = FindLensFlareElement(pRoot->GetChildAt(i), pred)) - { - return pElement; - } - } - - return nullptr; -} - -CLensFlareElementTree::CLensFlareElementTree(QWidget* pParent) - : QTreeView(pParent) - , m_model(new LensFlareElementTreeModel(this)) -{ - setHeaderHidden(true); - setContextMenuPolicy(Qt::CustomContextMenu); - setDragEnabled(true); - setAcceptDrops(true); - setDropIndicatorShown(true); - setDragDropMode(DragDrop); - - setModel(m_model.data()); - - connect(this, &QWidget::customContextMenuRequested, this, &CLensFlareElementTree::OnNotifyTreeRClick); - connect(selectionModel(), &QItemSelectionModel::selectionChanged, this, &CLensFlareElementTree::OnTvnSelchangedTree); - connect(model(), &QAbstractItemModel::dataChanged, this, &CLensFlareElementTree::OnDataChanged); - connect(model(), &QAbstractItemModel::rowsInserted, this, &CLensFlareElementTree::OnRowsInserted); - connect(model(), &QAbstractItemModel::rowsRemoved, this, &CLensFlareElementTree::OnRowsRemoved); - connect(model(), &QAbstractItemModel::modelReset, this, &QTreeView::expandAll); -} - -void CLensFlareElementTree::OnInternalVariableChange(IVariable* pVar) -{ - CLensFlareElement::LensFlareElementPtr pCurrentElement = GetCurrentLensFlareElement(); - if (pCurrentElement == NULL) - { - return; - } - pCurrentElement->OnInternalVariableChange(pVar); -} - -CLensFlareElement* CLensFlareElementTree::GetCurrentLensFlareElement() const -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return nullptr; - } - return selected.first().data(Qt::UserRole).value(); -} - -void CLensFlareElementTree::OnNotifyTreeRClick() -{ - CLensFlareElement* pElement = GetCurrentLensFlareElement(); - - // Copy, Cut and Clone can't be done about a Root item so those menus should be disable when the selected item is a root item. - bool bGrayed = false; - if (!pElement || pElement->GetOpticsType() == eFT_Root) - { - bGrayed = true; - } - - QMenu menu; - - QAction* actionDBFlareAddGroup = menu.addAction(tr("Add Group")); - connect(actionDBFlareAddGroup, &QAction::triggered, this, &CLensFlareElementTree::OnAddGroup); - - menu.addSeparator(); - - QAction* actionDBFlareCopy = menu.addAction(tr("Copy")); - connect(actionDBFlareCopy, &QAction::triggered, this, &CLensFlareElementTree::OnCopy); - - QAction* actionDBFlareCut = menu.addAction(tr("Cut")); - actionDBFlareCut->setEnabled(!bGrayed); - connect(actionDBFlareCut, &QAction::triggered, this, &CLensFlareElementTree::OnCut); - - QAction* actionDBFlarePaste = menu.addAction(tr("Paste")); - connect(actionDBFlarePaste, &QAction::triggered, this, &CLensFlareElementTree::OnPaste); - - QAction* actionDBFlareClone = menu.addAction(tr("Clone")); - connect(actionDBFlareClone, &QAction::triggered, this, &CLensFlareElementTree::OnClone); - - menu.addSeparator(); - - QAction* actionDBFlareRename = menu.addAction(tr("Rename\tF2")); - connect(actionDBFlareRename, &QAction::triggered, this, &CLensFlareElementTree::OnRenameItem); - - QAction* actionDBFlareRemove = menu.addAction(tr("Delete\tDel")); - connect(actionDBFlareRemove, &QAction::triggered, this, &CLensFlareElementTree::OnRemoveItem); - - QAction* actionDBFlareRemoveAll = menu.addAction(tr("Delete All")); - connect(actionDBFlareRemoveAll, &QAction::triggered, this, &CLensFlareElementTree::OnRemoveAll); - - menu.addSeparator(); - - QAction* actionDBFlareItemUp = menu.addAction(tr("Up")); - connect(actionDBFlareItemUp, &QAction::triggered, this, &CLensFlareElementTree::OnItemUp); - - QAction* actionDBFlareItemDown = menu.addAction(tr("Down")); - connect(actionDBFlareItemDown, &QAction::triggered, this, &CLensFlareElementTree::OnItemDown); - - menu.exec(QCursor::pos()); -} - -void CLensFlareElementTree::OnTvnSelchangedTree([[maybe_unused]] const QItemSelection& selected, const QItemSelection& deselected) -{ - QModelIndexList deselectedIndices = deselected.indexes(); - if (!deselectedIndices.isEmpty()) - { - CLensFlareElement* pPrevLensFlareElement = deselectedIndices.first().data(Qt::UserRole).value(); - ElementChanged(pPrevLensFlareElement); - } - - CallChangeListeners(); -} - -void CLensFlareElementTree::ElementChanged(CLensFlareElement* pPrevLensFlareElement) -{ - if (!pPrevLensFlareElement) - { - return; - } - QString itemName; - if (pPrevLensFlareElement->GetName(itemName)) - { - if (CUndo::IsRecording()) - { - CUndo::Record(new CUndoLensFlareElementSelection(m_model->GetLensFlareItem(), itemName)); - } - } -} - -void CLensFlareElementTree::OnDataChanged([[maybe_unused]] const QModelIndex& index) -{ - CallChangeListeners(); -} - -void CLensFlareElementTree::OnRowsInserted(const QModelIndex& parent, int first, [[maybe_unused]] int last) -{ - if (parent.isValid()) - { - expand(parent); - SelectItem(parent.model()->index(first, 0, parent)); - CallChangeListeners(); - } -} - -void CLensFlareElementTree::OnRowsRemoved(const QModelIndex& parent, int first, [[maybe_unused]] int last) -{ - if (parent.isValid()) - { - SelectItem(parent.model()->index(first, 0, parent)); - CallChangeListeners(); - } -} - -void CLensFlareElementTree::keyPressEvent(QKeyEvent* event) -{ - if (event->key() == Qt::Key_F2) - { - OnRenameItem(); - event->accept(); - return; - } - else if (event->matches(QKeySequence::Delete)) - { - OnRemoveItem(); - event->accept(); - return; - } - - QTreeView::keyPressEvent(event); -} - -XmlNodeRef CLensFlareElementTree::CreateXML(const char* type) const -{ - std::vector clipboardData; - if (GetClipboardList(type, clipboardData)) - { - return LensFlareUtil::CreateXMLFromClipboardData(type, "", false, clipboardData); - } - return NULL; -} - -void CLensFlareElementTree::UpdateClipboard(const char* type, bool bPasteAtSameLevel) -{ - std::vector clipboardData; - if (GetClipboardList(type, clipboardData)) - { - LensFlareUtil::UpdateClipboard(type, "", bPasteAtSameLevel, clipboardData); - } -} - -bool CLensFlareElementTree::GetClipboardList([[maybe_unused]] const char* type, std::vector& outList) const -{ - CLensFlareElement::LensFlareElementPtr pElement = GetCurrentLensFlareElement(); - if (pElement == NULL) - { - return false; - } - QString name; - if (!pElement->GetName(name)) - { - return false; - } - - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return false; - } - - CLensFlareItem* pLensFlareItem = pEditor->GetSelectedLensFlareItem(); - if (pLensFlareItem == NULL) - { - return false; - } - - outList.push_back(LensFlareUtil::SClipboardData(LENSFLARE_ELEMENT_TREE, pLensFlareItem->GetFullName(), name)); - - return true; -} - -void CLensFlareElementTree::OnAddGroup() -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - CUndo undo(tr("Add library item").toUtf8()); - m_model->AddElement(selected.first(), 0, eFT_Group); - GetIEditor()->GetLensFlareManager()->Modified(); -} - -void CLensFlareElementTree::OnCopy() -{ - UpdateClipboard(FLARECLIPBOARDTYPE_COPY, false); -} - -void CLensFlareElementTree::OnCut() -{ - Cut(false); -} - -void CLensFlareElementTree::Cut(bool bPasteAtSameLevel) -{ - UpdateClipboard(FLARECLIPBOARDTYPE_CUT, bPasteAtSameLevel); -} - -CLensFlareItem* CLensFlareElementTree::GetLensFlareItem() const -{ - return m_model->GetLensFlareItem(); -} - -void CLensFlareElementTree::OnPaste() -{ - CClipboard clipboard(this); - if (clipboard.IsEmpty()) - { - return; - } - - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - XmlNodeRef xmlNode = clipboard.Get(); - if (xmlNode == NULL) - { - return; - } - - CUndo undo(tr("Copy/Cut & Paste library item").toUtf8()); - m_model->Paste(selected.first(), xmlNode); -} - -void CLensFlareElementTree::OnClone() -{ - OnCopy(); - OnPaste(); -} - -void CLensFlareElementTree::OnRenameItem() -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - edit(selected.first()); -} - -void CLensFlareElementTree::OnRemoveItem() -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - QModelIndex index = selected.first(); - - // A root item must not be removed. - if (!index.parent().isValid()) - { - return; - } - - CLensFlareElement::LensFlareElementPtr pCurrentElement = m_model->GetLensFlareElement(index); - if (pCurrentElement == NULL) - { - return; - } - - QString name; - pCurrentElement->GetName(name); - - QString str = tr("Delete %1?").arg(name); - if (QMessageBox::question(this, tr("Delete Confirmation"), str) == QMessageBox::Yes) - { - CUndo undo(tr("Remove an optics element").toUtf8()); - m_model->removeRow(index.row(), index.parent()); - } -} - -void CLensFlareElementTree::OnRemoveAll() -{ - CUndo undo(tr("Remove All in FlareTreeCtrl").toUtf8()); - - if (QMessageBox::question(this, tr("Delete Confirmation"), tr("Do you want delete all?")) == QMessageBox::Yes) - { - m_model->RemoveAllElements(); - GetIEditor()->GetLensFlareManager()->Modified(); - } -} - -void CLensFlareElementTree::OnItemUp() -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - QModelIndex index = selected.first(); - int row = index.row(); - if (row == 0) - { - return; - } - - CUndo undo(tr("Copy/Cut & Paste library item").toUtf8()); - - CLensFlareElement* pElement = index.data(Qt::UserRole).value(); - m_model->MoveElement(pElement, row - 1, index.parent()); -} - -void CLensFlareElementTree::OnItemDown() -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - QModelIndex index = selected.first(); - int row = index.row(); - if (row == m_model->rowCount(index.parent()) - 1) - { - return; - } - - CUndo undo(tr("Copy/Cut & Paste library item").toUtf8()); - - CLensFlareElement* pElement = index.data(Qt::UserRole).value(); - m_model->MoveElement(pElement, row + 2, index.parent()); -} - -void CLensFlareElementTree::SelectItem(const QModelIndex& index) -{ - if (index.isValid()) - { - expand(index.parent()); - selectionModel()->select(index, QItemSelectionModel::ClearAndSelect); - } - else - { - selectionModel()->clear(); - } -} - -void CLensFlareElementTree::SelectTreeItemByName(const QString& name) -{ - SelectItem(m_model->GetTreeItemByName(name)); -} - -void CLensFlareElementTree::CallChangeListeners() -{ - CLensFlareElement* pElement = GetCurrentLensFlareElement(); - for (int i = 0, iSize(m_LensFlaresElementListeners.size()); i < iSize; ++i) - { - m_LensFlaresElementListeners[i]->OnLensFlareChangeElement(pElement); - } -} - -void CLensFlareElementTree::mousePressEvent(QMouseEvent* event) -{ - if (event->button() == Qt::LeftButton) - { - CUndo undo(tr("Changed Lens flares element").toUtf8()); - QTreeView::mousePressEvent(event); - } - else - { - QTreeView::mousePressEvent(event); - } -} - -void CLensFlareElementTree::InvalidateLensFlareItem() -{ - m_model->InvalidateLensFlareItem(); -} - -LensFlareElementTreeModel::LensFlareElementTreeModel(QObject* pParent) - : QAbstractItemModel(pParent) - , m_pRootElement(new CLensFlareElement) -{ - CLensFlareEditor::GetLensFlareEditor()->RegisterLensFlareItemChangeListener(this); -} - -LensFlareElementTreeModel::~LensFlareElementTreeModel() -{ - CLensFlareEditor::GetLensFlareEditor()->UnregisterLensFlareItemChangeListener(this); -} - -int LensFlareElementTreeModel::columnCount(const QModelIndex&) const -{ - return 1; -} - -QVariant LensFlareElementTreeModel::data(const QModelIndex& index, int role) const -{ - if (!index.isValid()) - { - return {}; - } - - auto pElement = static_cast(index.internalPointer()); - - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - { - QString shortName; - pElement->GetShortName(shortName); - return shortName; - } - - case Qt::CheckStateRole: - return pElement->IsEnable() ? Qt::Checked : Qt::Unchecked; - - case Qt::UserRole: - return QVariant::fromValue(pElement); - } - - return {}; -} - -void LensFlareElementTreeModel::EnableElement(CLensFlareElement* pLensFlareElement, bool bEnable) -{ - StoreUndo(); - pLensFlareElement->SetEnable(bEnable); -} - -void LensFlareElementTreeModel::RenameElement(CLensFlareElement* pLensFlareElement, const QString& newName) -{ - StoreUndo(); - IOpticsElementBasePtr pOptics = pLensFlareElement->GetOpticsElement(); - if (pOptics) - { - pOptics->SetName(newName.toUtf8().data()); - LensFlareUtil::UpdateOpticsName(pOptics); - } -} - -QModelIndex LensFlareElementTreeModel::GetRootItem() const -{ - if (m_pRootElement->GetChildCount() == 0) - { - return {}; - } - - auto pRootElement = m_pRootElement->GetChildAt(0); - assert(pRootElement->GetOpticsType() == eFT_Root); - - return createIndex(0, 0, pRootElement); -} - -bool LensFlareElementTreeModel::setData(const QModelIndex& index, const QVariant& value, int role) -{ - if (!index.isValid()) - { - return false; - } - - auto pElement = static_cast(index.internalPointer()); - - switch (role) - { - case Qt::CheckStateRole: - { - CUndo undo(tr("Update an enable checkbox for tree ctrl.").toUtf8()); - EnableElement(pElement, value.toInt() == Qt::Checked); - emit dataChanged(index, index); - return true; - } - - case Qt::EditRole: - { - QString text = value.toString(); - - CUndo undo(tr("Rename library item").toUtf8()); - - if (IsExistElement(text)) - { - QMessageBox::warning(0, tr("Warning"), tr("The identical name exists in a database")); - return false; - } - else if (text.contains(QLatin1Char('.'))) - { - QMessageBox::warning(0, tr("Warning"), tr("The name must not contain \".\"")); - return false; - } - else - { - CLensFlareElement* pLensFlareElement = GetLensFlareElement(index); - - QString prevName; - if (pLensFlareElement && pLensFlareElement->GetName(prevName)) - { - QString parentName(prevName); - int offset = parentName.lastIndexOf('.'); - if (offset == -1) - { - parentName = ""; - } - else - { - parentName.remove(offset + 1, parentName.length() - offset); - } - - if (index == GetRootItem()) - { - CLensFlareEditor* pLensFlareEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pLensFlareEditor) - { - CLensFlareItem* pLensFlareItem = pLensFlareEditor->GetSelectedLensFlareItem(); - if (pLensFlareItem) - { - QString candidateName = LensFlareUtil::ReplaceLastName(pLensFlareItem->GetName(), text); - if (pLensFlareEditor->IsExistTreeItem(candidateName, true)) - { - QMessageBox::warning(0, tr("Warning"), tr("The identical name exists in a database")); - return false; - } - pLensFlareEditor->RenameLensFlareItem(pLensFlareItem, pLensFlareItem->GetGroupName(), text); - } - } - else - { - QMessageBox::warning(0, tr("Warning"), tr("Renaming is not possible.")); - return false; - } - } - - RenameElement(pLensFlareElement, parentName + text); - emit dataChanged(index, index); - - GetIEditor()->GetLensFlareManager()->Modified(); - } - - return true; - } - } - } - - return false; -} - -Qt::ItemFlags LensFlareElementTreeModel::flags(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return Qt::ItemFlags(); - } - - auto pElement = index.data(Qt::UserRole).value(); - - Qt::ItemFlags flags = QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled; - - if (pElement->GetOpticsType() != eFT_Root) - { - flags |= Qt::ItemIsDragEnabled; - } - - return flags; -} - -QModelIndex LensFlareElementTreeModel::index(int row, int column, const QModelIndex& parent) const -{ - if (!hasIndex(row, column, parent)) - { - return {}; - } - - auto parentNode = GetLensFlareElement(parent); - auto childNode = parentNode->GetChildAt(row); - - if (childNode) - { - return createIndex(row, column, childNode); - } - else - { - return {}; - } -} - -QModelIndex LensFlareElementTreeModel::parent(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return {}; - } - - auto childNode = static_cast(index.internalPointer()); - auto parentNode = childNode->GetParent(); - - if (parentNode == m_pRootElement.get()) - { - return {}; - } - - return createIndex(parentNode->GetRow(), 0, parentNode); -} - -int LensFlareElementTreeModel::rowCount(const QModelIndex& parent) const -{ - if (parent.column() > 0) - { - return 0; - } - return GetLensFlareElement(parent)->GetChildCount(); -} - -bool LensFlareElementTreeModel::removeRows(int row, int count, const QModelIndex& parent) -{ - if (!parent.isValid()) - { - return false; - } - - auto pParent = static_cast(parent.internalPointer()); - - beginRemoveRows(parent, row, row + count - 1); - - for (int i = 0; i < count; i++) - { - CLensFlareElement* pChild = pParent->GetChildAt(row); - - IOpticsElementBasePtr pOptics = pChild->GetOpticsElement(); - if (pOptics) - { - LensFlareUtil::RemoveOptics(pOptics); - } - - pParent->RemoveChild(row); - } - - endRemoveRows(); - - GetIEditor()->GetLensFlareManager()->Modified(); // XXX - - if (m_pLensFlareItem) - { - m_pLensFlareItem->UpdateLights(); - } - - return true; -} - -QStringList LensFlareElementTreeModel::mimeTypes() const -{ - QStringList types; - types << QStringLiteral("application/x-o3de-flareelements"); - types << QStringLiteral("application/x-o3de-flaretypes"); - return types; -} - -QMimeData* LensFlareElementTreeModel::mimeData(const QModelIndexList& indexes) const -{ - QMimeData* data = new QMimeData(); - - QByteArray array; - - for (auto& index : indexes) - { - auto pElement = static_cast(index.data(Qt::UserRole).value()); - array.append(reinterpret_cast(&pElement), sizeof(CLensFlareElement*)); - } - - data->setData(QStringLiteral("application/x-o3de-flareelements"), array); - - return data; -} - -void LensFlareElementTreeModel::RemoveAllElements() -{ - QModelIndex index = GetRootItem(); - if (!index.isValid()) - { - return; - } - - auto pElement = index.data(Qt::UserRole).value(); - - beginResetModel(); - - pElement->RemoveAllChildren(); - pElement->GetOpticsElement()->RemoveAll(); - - endResetModel(); - - if (m_pLensFlareItem) - { - m_pLensFlareItem->UpdateLights(); - } -} - -bool LensFlareElementTreeModel::AddElement(const QModelIndex& parentIndex, int row, EFlareType flareType) -{ - if (!parentIndex.isValid()) - { - return false; - } - - auto pElement = GetLensFlareElement(parentIndex); - - int nIndex; - - if (LensFlareUtil::IsGroup(pElement->GetOpticsType())) - { - if (row != -1) - { - nIndex = row; - } - else - { - nIndex = pElement->GetChildCount(); - } - } - else - { - CLensFlareElement* pParentElement = GetLensFlareElement(parentIndex.parent()); - if (!pParentElement) - { - return false; - } - - if (!LensFlareUtil::IsGroup(pParentElement->GetOpticsType())) - { - return false; - } - - nIndex = LensFlareUtil::FindOpticsIndexUnderParentOptics(pElement->GetOpticsElement(), pParentElement->GetOpticsElement()); - if (nIndex == -1) - { - return false; - } - - pElement = pParentElement; - } - - CLensFlareElement::LensFlareElementPtr pNewElement = InsertAtomicElement(nIndex, flareType, pElement); - if (!pNewElement) - { - return false; - } - - if (m_pLensFlareItem) - { - m_pLensFlareItem->UpdateLights(); - } - - return true; -} - -CLensFlareElement::LensFlareElementPtr LensFlareElementTreeModel::InsertAtomicElement(int nIndex, EFlareType flareType, CLensFlareElement* pParentElement) -{ - IOpticsElementBasePtr pParent = pParentElement->GetOpticsElement(); - if (pParent == NULL) - { - return NULL; - } - - IOpticsElementBasePtr pNewOptics = gEnv->pOpticsManager->Create(flareType); - if (pNewOptics == NULL) - { - return NULL; - } - - if (nIndex < 0) - { - return NULL; - } - - CLensFlareElement::LensFlareElementPtr pElement = AddElement(pNewOptics, pParentElement); - if (pElement == NULL) - { - return NULL; - } - - pParent->InsertElement(nIndex, pNewOptics); - - emit beginInsertRows(createIndex(pParentElement->GetRow(), 0, pParentElement), nIndex, nIndex); - pParentElement->InsertChild(nIndex, pElement); - emit endInsertRows(); - - return pElement; -} - -void LensFlareElementTreeModel::MakeValidElementName(const QString& seedName, QString& outValidName) const -{ - if (!IsExistElement(seedName)) - { - outValidName = seedName; - return; - } - - int counter = 0; - do - { - QString numberString; - numberString = QString::number(counter); - QString candidateName = seedName + numberString; - if (!IsExistElement(candidateName)) - { - outValidName = candidateName; - return; - } - } while (++counter < 100000); // prevent from infinite loop -} - -bool LensFlareElementTreeModel::IsExistElement(const QString& name) const -{ - const auto predicate = [&](CLensFlareElement* pElement) - { - QString flareName; - return pElement->GetName(flareName) && !QString::compare(flareName, name, Qt::CaseInsensitive); - }; - auto pElement = ::FindLensFlareElement(m_pRootElement.get(), predicate); - return pElement != nullptr; -} - -CLensFlareElement::LensFlareElementPtr LensFlareElementTreeModel::AddElement(IOpticsElementBasePtr pOptics, CLensFlareElement* pParentElement) -{ - if (pOptics == NULL) - { - return NULL; - } - - IOpticsElementBasePtr pParent = pParentElement->GetOpticsElement(); - - CLensFlareElement* pLensFlareElement = NULL; - - if (pParent == NULL) - { - if (pOptics->GetType() != eFT_Root) - { - assert(0 && "CFlareManager::AddItem() - pOptics must be a root optics if the parent doesn't exist."); - return NULL; - } - } - else - { - if (!LensFlareUtil::IsGroup(pParent->GetType())) - { - return NULL; - } - - QString fullElementName; - if (!pParentElement->GetName(fullElementName)) - { - return NULL; - } - if (!fullElementName.isEmpty()) - { - fullElementName += "."; - } - fullElementName += LensFlareUtil::GetShortName(pOptics->GetName().c_str()).toLower(); - - QString validName; - MakeValidElementName(fullElementName, validName); - pOptics->SetName(validName.toUtf8().data()); - } - - pLensFlareElement = CreateElement(pOptics); - - if (LensFlareUtil::IsGroup(pOptics->GetType())) - { - for (int i = 0, iElementCount(pOptics->GetElementCount()); i < iElementCount; ++i) - { - CLensFlareElement::LensFlareElementPtr pChild = AddElement(pOptics->GetElementAt(i), pLensFlareElement); - pLensFlareElement->AddChild(pChild); - } - } - - GetIEditor()->GetLensFlareManager()->Modified(); - if (m_pLensFlareItem) - { - m_pLensFlareItem->UpdateLights(); - } - - return pLensFlareElement; -} - -bool LensFlareElementTreeModel::MoveElement(CLensFlareElement* pElement, int row, const QModelIndex& index) -{ - if (!index.isValid()) - { - return false; - } - - QModelIndex sourceParentIndex = parent(createIndex(0, 0, pElement)); - if (!sourceParentIndex.isValid()) - { - return false; - } - - QModelIndex targetParentIndex = index; - CLensFlareElement* pTargetParent = targetParentIndex.data(Qt::UserRole).value(); - - QString fullElementName; - if (!pTargetParent->GetName(fullElementName)) - { - return false; - } - if (!fullElementName.isEmpty()) - { - fullElementName += "."; - } - fullElementName += LensFlareUtil::GetShortName(pElement->GetOpticsElement()->GetName().c_str()).toLower(); - - QString validName; - MakeValidElementName(fullElementName, validName); - - int targetRow; - - if (!LensFlareUtil::IsGroup(pTargetParent->GetOpticsElement()->GetType())) - { - targetParentIndex = targetParentIndex.parent(); - pTargetParent = targetParentIndex.data(Qt::UserRole).value(); - targetRow = index.row(); - } - else - { - if (row != -1) - { - targetRow = row; - } - else - { - targetRow = pTargetParent->GetChildCount(); - } - } - - CLensFlareElement* pSourceParent = pElement->GetParent(); - int sourceRow = pElement->GetRow(); - - if (!beginMoveRows(sourceParentIndex, sourceRow, sourceRow, targetParentIndex, targetRow)) - { - return false; - } - - StoreUndo(); - - // insert before removing to increase reference count - - pTargetParent->InsertChild(targetRow, pElement); - pTargetParent->GetOpticsElement()->InsertElement(targetRow, pElement->GetOpticsElement()); - - if (pTargetParent == pSourceParent && targetRow < sourceRow) - { - ++sourceRow; - } - - pSourceParent->RemoveChild(sourceRow); - pSourceParent->GetOpticsElement()->Remove(sourceRow); - - pElement->GetOpticsElement()->SetName(validName.toUtf8().data()); - LensFlareUtil::UpdateOpticsName(pElement->GetOpticsElement()); - - endMoveRows(); - - return true; -} - -bool LensFlareElementTreeModel::dropMimeData(const QMimeData* data, [[maybe_unused]] Qt::DropAction action, int row, [[maybe_unused]] int column, const QModelIndex& parent) -{ - if (data->hasFormat(QStringLiteral("application/x-o3de-flaretypes"))) - { - // drop from atomic list - - QByteArray encoded = data->data(QStringLiteral("application/x-o3de-flaretypes")); - QDataStream stream(&encoded, QIODevice::ReadOnly); - - while (!stream.atEnd()) - { - int flareType; - stream >> flareType; - - CUndo undo(tr("Add Atomic Lens Flare Item").toUtf8()); - AddElement(parent, row, static_cast(flareType)); - } - - return true; - } - else if (data->hasFormat(QStringLiteral("application/x-o3de-flareelements"))) - { - QByteArray array = data->data("application/x-o3de-flareelements"); - - int count = array.size() / sizeof(CLensFlareElement*); - auto ppElements = reinterpret_cast(array.data()); - - CUndo undo(tr("Copy/Cut & Paste library item").toUtf8()); - - for (int i = 0; i < count; i++) - { - MoveElement(ppElements[i], row, parent); - } - - return true; - } - else - { - return false; - } -} - -CLensFlareElement* LensFlareElementTreeModel::FindLensFlareElement(IOpticsElementBasePtr pOptics) const -{ - return ::FindLensFlareElement(m_pRootElement.get(), [&](CLensFlareElement* pElement) - { - return pElement->GetOpticsElement() == pOptics; - }); -} - -Qt::DropActions LensFlareElementTreeModel::supportedDragActions() const -{ - return Qt::CopyAction | Qt::MoveAction; -} - -Qt::DropActions LensFlareElementTreeModel::supportedDropActions() const -{ - return Qt::CopyAction | Qt::MoveAction; -} - -void LensFlareElementTreeModel::UpdateLensFlareItem(CLensFlareItem* pLensFlareItem) -{ - m_pLensFlareItem = pLensFlareItem; - - m_pRootElement.reset(new CLensFlareElement); - - if (pLensFlareItem != NULL) - { - auto pChild = UpdateLensFlareElementsRecusively(m_pLensFlareItem->GetOptics()); - if (pChild) - { - m_pRootElement->AddChild(pChild); - } - } -} - -CLensFlareElement* LensFlareElementTreeModel::UpdateLensFlareElementsRecusively(IOpticsElementBasePtr pOptics) -{ - auto pElement = new CLensFlareElement; - pElement->SetOpticsElement(pOptics); - - for (int i = 0, iCount(pOptics->GetElementCount()); i < iCount; i++) - { - auto pChild = UpdateLensFlareElementsRecusively(pOptics->GetElementAt(i)); - if (pElement) - { - pElement->AddChild(pChild); - } - } - - return pElement; -} - -CLensFlareElement* LensFlareElementTreeModel::CreateElement(IOpticsElementBasePtr pOptics) -{ - StoreUndo(); - CLensFlareElement* pElement = new CLensFlareElement; - pElement->SetOpticsElement(pOptics); - return pElement; -} - -void LensFlareElementTreeModel::OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem) -{ - beginResetModel(); - UpdateLensFlareItem(pLensFlareItem); - endResetModel(); -} - -void LensFlareElementTreeModel::OnLensFlareDeleteItem([[maybe_unused]] CLensFlareItem* pLensFlareItem) -{ -} - -CLensFlareElement* LensFlareElementTreeModel::GetLensFlareElement(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return m_pRootElement.get(); - } - else - { - return static_cast(index.internalPointer()); - } -} - -void LensFlareElementTreeModel::Paste(const QModelIndex& hItem, XmlNodeRef xmlNode) -{ - if (!hItem.isValid()) - { - return; - } - - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return; - } - - QString type; - xmlNode->getAttr("Type", type); - - bool bPasteAtSameLevel = false; - xmlNode->getAttr("PasteAtSameLevel", bPasteAtSameLevel); - - QModelIndex hParentItem; - - IOpticsElementBasePtr pSelectedOptics = GetOpticsElementByTreeItem(hItem); - if (pSelectedOptics == NULL) - { - return; - } - - if (!LensFlareUtil::IsGroup(pSelectedOptics->GetType())) - { - hParentItem = hItem.parent(); - } - else - { - if (bPasteAtSameLevel) - { - hParentItem = hItem.parent(); - } - else - { - hParentItem = hItem; - } - } - - IOpticsElementBasePtr pParentOptics = GetOpticsElementByTreeItem(hParentItem); - if (pParentOptics == NULL) - { - return; - } - - for (int i = 0, iChildCount(xmlNode->getChildCount()); i < iChildCount; ++i) - { - LensFlareUtil::SClipboardData clipboardData; - clipboardData.FillThisFromXmlNode(xmlNode->getChild(i)); - - if (clipboardData.m_LensFlareFullPath == m_pLensFlareItem->GetFullName() && clipboardData.m_From == LENSFLARE_ITEM_TREE) - { - QString msg; - msg = tr("[%1] lens item can be pasted into the same item").arg(clipboardData.m_LensFlareFullPath); - CryMessageBox(msg.toUtf8().data(), "Warning", MB_OK); - continue; - } - - IOpticsElementBasePtr pSourceOptics = pEditor->FindOptics(clipboardData.m_LensFlareFullPath, clipboardData.m_LensOpticsPath); - if (pSourceOptics == NULL) - { - continue; - } - - CLensFlareItem* pSourceLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(clipboardData.m_LensFlareFullPath); - if (pSourceLensFlareItem == NULL) - { - continue; - } - - if (type == FLARECLIPBOARDTYPE_CUT) - { - if (m_pLensFlareItem->GetFullName() == clipboardData.m_LensFlareFullPath && LensFlareUtil::FindOptics(pSourceOptics, pSelectedOptics->GetName().c_str())) - { - QMessageBox::warning(0, tr("Warning"), tr("You can't paste this item here.")); - return; - } - } - - // if the copied optics type is root, the type should be converted to group type. - bool bForceConvertType = false; - if (pSourceOptics->GetType() == eFT_Root) - { - bForceConvertType = true; - } - - IOpticsElementBasePtr pNewOptics = LensFlareUtil::CreateOptics(pSourceOptics, bForceConvertType); - if (pNewOptics == NULL) - { - return; - } - - if (type == FLARECLIPBOARDTYPE_CUT) - { - if (pSourceLensFlareItem == m_pLensFlareItem) - { - QModelIndex hSourceItem = GetTreeItemByOpticsElement(pSourceOptics); - if (hSourceItem.isValid()) - { - removeRow(hSourceItem.row(), hSourceItem.parent()); - } - } - else if (clipboardData.m_From == LENSFLARE_ITEM_TREE) - { - CLensFlareLibrary* pLibrary = pEditor->GetCurrentLibrary(); - if (pLibrary) - { - QString lensFlareFullName = m_pLensFlareItem ? m_pLensFlareItem->GetFullName() : ""; - pLibrary->RemoveItem(pSourceLensFlareItem); - pEditor->ReloadItems(); - pSourceLensFlareItem->UpdateLights(); - pEditor->UpdateLensOpticsNames(pSourceLensFlareItem->GetFullName(), ""); - if (!lensFlareFullName.isEmpty()) - { - pEditor->SelectItemByName(lensFlareFullName); - } - } - - LensFlareUtil::RemoveOptics(pSourceOptics); - } - } - - CLensFlareElement* pParentElement = FindLensFlareElement(pParentOptics); - - // The children optics items were already added in a creation phase so we don't need to update the optics object. - CLensFlareElement::LensFlareElementPtr pNewElement = AddElement(pNewOptics, pParentElement); - assert(pNewElement); - if (!pNewElement) - { - return; - } - - int nInsertedPos; - if (hParentItem == hItem) - { - nInsertedPos = 0; - } - else - { - nInsertedPos = LensFlareUtil::FindOpticsIndexUnderParentOptics(pSelectedOptics, pParentOptics); - if (nInsertedPos > pParentOptics->GetElementCount() || nInsertedPos == -1) - { - nInsertedPos = pParentOptics->GetElementCount(); - } - } - - pParentOptics->InsertElement(nInsertedPos, pNewOptics); - LensFlareUtil::UpdateOpticsName(pNewOptics); - - emit beginInsertRows(createIndex(pParentElement->GetRow(), 0, pParentElement), nInsertedPos, nInsertedPos); - pParentElement->InsertChild(nInsertedPos, pNewElement); - emit endInsertRows(); - - // pSelectedLensFlareItem->UpdateLights(); - } -} - -IOpticsElementBasePtr LensFlareElementTreeModel::GetOpticsElementByTreeItem(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return nullptr; - } - return GetLensFlareElement(index)->GetOpticsElement(); -} - -QModelIndex LensFlareElementTreeModel::GetTreeItemByName(const QString& name) const -{ - auto pElement = ::FindLensFlareElement(m_pRootElement.get(), [&](CLensFlareElement* pElement) - { - QString flareName; - return pElement->GetName(flareName) && flareName == name; - }); - - if (!pElement) - { - return {}; - } - - return createIndex(pElement->GetRow(), 0, pElement); -} - -QModelIndex LensFlareElementTreeModel::GetTreeItemByOpticsElement(const IOpticsElementBasePtr pOptics) const -{ - auto pElement = FindLensFlareElement(pOptics); - if (!pElement) - { - return {}; - } - return createIndex(pElement->GetRow(), 0, pElement); -} - -void LensFlareElementTreeModel::InvalidateLensFlareItem() -{ - OnLensFlareChangeItem(nullptr); -} - -void LensFlareElementTreeModel::StoreUndo(const QString& undoDescription) -{ - if (CUndo::IsRecording()) - { - if (undoDescription.isEmpty()) - { - CUndo::Record(new CUndoLensFlareItem(GetLensFlareItem())); - } - else - { - CUndo::Record(new CUndoLensFlareItem(GetLensFlareItem(), undoDescription)); - } - } -} - -#include diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.h deleted file mode 100644 index d2b0051032..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.h +++ /dev/null @@ -1,197 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREELEMENTTREE_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREELEMENTTREE_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "LensFlareElement.h" -#include "LensFlareUtil.h" -#include "ILensFlareListener.h" - -#include -#include -#endif - -class CLensFlareItem; -class LensFlareElementTreeModel; -class QMouseEvent; - -class CLensFlareElementTree - : public QTreeView -{ - Q_OBJECT - -public: - - CLensFlareElementTree(QWidget* pParent = nullptr); - - void RegisterListener(ILensFlareChangeElementListener* pListener) - { - if (pListener) - { - m_LensFlaresElementListeners.push_back(pListener); - } - } - - void UnregisterListener(ILensFlareChangeElementListener* pListener) - { - if (pListener == NULL) - { - return; - } - std::vector::iterator ii = m_LensFlaresElementListeners.begin(); - for (; ii != m_LensFlaresElementListeners.end(); ) - { - if (*ii == pListener) - { - ii = m_LensFlaresElementListeners.erase(ii); - } - else - { - ++ii; - } - } - } - - CLensFlareElement::LensFlareElementPtr FindLensFlareElement(IOpticsElementBasePtr pElement) const; - - void OnInternalVariableChange(IVariable* pVar); - - CLensFlareElement* GetCurrentLensFlareElement() const; - void UpdateProperty(); - void UpdateClipboard(const char* type, bool bPasteAtSameLevel); - - void SelectTreeItemByName(const QString& name); - - CLensFlareItem* GetLensFlareItem() const; - void InvalidateLensFlareItem(); - -protected: - void CallChangeListeners(); - - void OnDataChanged(const QModelIndex& index); - void OnRowsInserted(const QModelIndex& index, int first, int last); - void OnRowsRemoved(const QModelIndex& index, int first, int last); - - void OnNotifyTreeRClick(); - void OnTvnSelchangedTree(const QItemSelection& selected, const QItemSelection& deselected); - - XmlNodeRef CreateXML(const char* type) const; - bool GetClipboardList(const char* type, std::vector& outList) const; - - //! Only the basic operations like following methods must have routine for undoing. - void ElementChanged(CLensFlareElement* pPrevLensFlareElement); - ///////////////////////////////////////////////////////////////////////////////////////// - - void OnAddGroup(); - void OnCopy(); - void OnCut(); - void OnPaste(); - void OnClone(); - void OnRenameItem(); - void OnRemoveItem(); - void OnRemoveAll(); - void OnItemUp(); - void OnItemDown(); - void mousePressEvent(QMouseEvent* event); - void keyPressEvent(QKeyEvent* event); - - void Cut(bool bPasteAtSameLevel); - -private: - void SelectItem(const QModelIndex& index); - - std::vector m_LensFlaresElementListeners; - - QScopedPointer m_model; -}; - -class LensFlareElementTreeModel - : public QAbstractItemModel - , public ILensFlareChangeItemListener -{ - Q_OBJECT - -public: - LensFlareElementTreeModel(QObject* pParent = nullptr); - ~LensFlareElementTreeModel(); - - int rowCount(const QModelIndex& parent = {}) const override; - int columnCount(const QModelIndex& parent = {}) const override; - - Qt::ItemFlags flags(const QModelIndex& index) const override; - QVariant data(const QModelIndex& index, int role) const override; - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); - - QModelIndex index(int row, int column, const QModelIndex& parent = {}) const override; - QModelIndex parent(const QModelIndex& index) const override; - - bool removeRows(int row, int count, const QModelIndex& parent = {}) override; - - QStringList mimeTypes() const override; - QMimeData* mimeData(const QModelIndexList& indexes) const override; - bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; - Qt::DropActions supportedDragActions() const override; - Qt::DropActions supportedDropActions() const override; - - CLensFlareElement* GetLensFlareElement(const QModelIndex& index) const; - - QModelIndex GetTreeItemByName(const QString& name) const; - - void Paste(const QModelIndex& index, XmlNodeRef xmlNode); - void Cut(const QModelIndex& index, bool bPasteAtSameLevel); - - CLensFlareItem* GetLensFlareItem() const - { - return m_pLensFlareItem; - } - - void InvalidateLensFlareItem(); - - void RemoveAllElements(); - bool AddElement(const QModelIndex& index, int row, EFlareType flareType); - - bool MoveElement(CLensFlareElement* pElement, int row, const QModelIndex& parentIndex); - -private: - QModelIndex GetRootItem() const; - IOpticsElementBasePtr GetOpticsElementByTreeItem(const QModelIndex& index) const; - - void OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem); - void OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem); - - void UpdateLensFlareItem(CLensFlareItem* pLensFlareItem); - CLensFlareElement* UpdateLensFlareElementsRecusively(IOpticsElementBasePtr pOptics); - CLensFlareElement* CreateElement(IOpticsElementBasePtr pOptics); - void Reload(); - - void MakeValidElementName(const QString& seedName, QString& outValidName) const; - bool IsExistElement(const QString& name) const; - CLensFlareElement::LensFlareElementPtr InsertAtomicElement(int nIndex, EFlareType flareType, CLensFlareElement* pParentElement); - CLensFlareElement::LensFlareElementPtr AddElement(IOpticsElementBasePtr pOptics, CLensFlareElement* pParentElement); - CLensFlareElement* FindLensFlareElement(IOpticsElementBasePtr pOptics) const; - - QModelIndex GetTreeItemByOpticsElement(const IOpticsElementBasePtr pOptics) const; - void EnableElement(CLensFlareElement* pLensFlareElement, bool bEnable); - void RenameElement(CLensFlareElement* pLensFlareElement, const QString& newName); - void StoreUndo(const QString& undoDescription = ""); - - CLensFlareElement::LensFlareElementPtr m_pRootElement; - CLensFlareItem* m_pLensFlareItem; -}; - -Q_DECLARE_METATYPE(CLensFlareElement*) - -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREELEMENTTREE_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItem.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareItem.cpp deleted file mode 100644 index e20f1ac7cb..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItem.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareItem.h" - -// Editor -#include "LensFlareUtil.h" -#include "LensFlareEditor.h" -#include "LensFlareUndo.h" -#include "Objects/EntityObject.h" - - -CLensFlareItem::CLensFlareItem() -{ - m_pOptics = NULL; - CreateOptics(); -} - -CLensFlareItem::~CLensFlareItem() -{ -} - -void CLensFlareItem::Serialize(SerializeContext& ctx) -{ - if (ctx.bLoading) - { - CreateOptics(); - LensFlareUtil::FillOpticsFromXML(m_pOptics, ctx.node); - - for (int i = 0, iChildCount(ctx.node->getChildCount()); i < iChildCount; ++i) - { - AddChildOptics(m_pOptics, ctx.node->getChild(i)); - } - - CBaseLibraryItem::Serialize(ctx); - } - else - { - CBaseLibraryItem::Serialize(ctx); - } -} - -void CLensFlareItem::AddChildOptics(IOpticsElementBasePtr pParentOptics, const XmlNodeRef& pNode) -{ - if (pNode == NULL) - { - return; - } - - if (pNode->getTag() && strcmp(pNode->getTag(), "FlareItem")) - { - return; - } - - IOpticsElementBasePtr pOptics = LensFlareUtil::CreateOptics(pNode); - if (pOptics == NULL) - { - return; - } - - pParentOptics->AddElement(pOptics); - - for (int i = 0, iChildCount(pNode->getChildCount()); i < iChildCount; ++i) - { - AddChildOptics(pOptics, pNode->getChild(i)); - } -} - -void CLensFlareItem::CreateOptics() -{ - m_pOptics = gEnv->pOpticsManager->Create(eFT_Root); -} - -XmlNodeRef CLensFlareItem::CreateXmlData() const -{ - XmlNodeRef pRootNode = NULL; - if (LensFlareUtil::CreateXmlData(m_pOptics, pRootNode)) - { - pRootNode->setAttr("Name", m_pOptics->GetName().c_str()); - return pRootNode; - } - return NULL; -} - -void CLensFlareItem::SetName(const QString& name) -{ - QString newNameWithGroup; - QString newFullName; - LensFlareUtil::GetExpandedItemNames(this, LensFlareUtil::GetGroupNameFromName(name), LensFlareUtil::GetShortName(name), newNameWithGroup, newFullName); - - if (CUndo::IsRecording()) - { - CUndo::Record(new CUndoRenameLensFlareItem(GetFullName(), newFullName)); - } - - CBaseLibraryItem::SetName(name); - - if (m_pOptics) - { - m_pOptics->SetName(GetShortName().toUtf8().data()); - } -} - -void CLensFlareItem::UpdateLights(IOpticsElementBasePtr pSrcOptics) -{ - QString srcFullOpticsName = GetFullName(); - bool bUpdateChildren = false; - if (pSrcOptics == NULL) - { - if (m_pOptics == NULL) - { - return; - } - pSrcOptics = m_pOptics; - bUpdateChildren = true; - } - - std::vector lightEntities; - LensFlareUtil::GetLightEntityObjects(lightEntities); - - for (int i = 0, iLightSize(lightEntities.size()); i < iLightSize; ++i) - { - CEntityObject* pLightEntity = lightEntities[i]; - if (pLightEntity == NULL) - { - continue; - } - - IOpticsElementBasePtr pTargetOptics = pLightEntity->GetOpticsElement(); - if (pTargetOptics == NULL) - { - continue; - } - - QString targetFullOpticsName(pTargetOptics->GetName().c_str()); - if (srcFullOpticsName != targetFullOpticsName) - { - continue; - } - - QString srcOpticsName(pSrcOptics->GetName().c_str()); - IOpticsElementBasePtr pFoundOptics = NULL; - if (LensFlareUtil::GetShortName(targetFullOpticsName) == srcOpticsName) - { - pFoundOptics = pTargetOptics; - } - else - { - pFoundOptics = LensFlareUtil::FindOptics(pTargetOptics, srcOpticsName); - } - - if (pFoundOptics == NULL) - { - continue; - } - if (pFoundOptics->GetType() != pSrcOptics->GetType()) - { - continue; - } - - LensFlareUtil::CopyOptics(pSrcOptics, pFoundOptics, bUpdateChildren); - } -} - -void CLensFlareItem::ReplaceOptics(IOpticsElementBasePtr pNewData) -{ - if (pNewData == NULL) - { - return; - } - if (pNewData->GetType() != eFT_Root) - { - return; - } - CreateOptics(); - LensFlareUtil::CopyOptics(pNewData, m_pOptics); - m_pOptics->SetName(GetFullName().toUtf8().data()); - UpdateLights(); - - CLensFlareEditor* pLensFlareEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pLensFlareEditor == NULL) - { - return; - } - if (this != pLensFlareEditor->GetSelectedLensFlareItem()) - { - return; - } - pLensFlareEditor->UpdateLensFlareItem(this); - pLensFlareEditor->RemovePropertyItems(); -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItem.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareItem.h deleted file mode 100644 index 6d1eedb5f9..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItem.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREITEM_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREITEM_H -#pragma once - -class IOpticsElementBase; -class CEntityObject; - -#include "BaseLibraryItem.h" -#include "Include/IDataBaseItem.h" - -class CLensFlareItem - : public CBaseLibraryItem -{ -public: - - CLensFlareItem(); - ~CLensFlareItem(); - - EDataBaseItemType GetType() const - { - return EDB_TYPE_FLARE; - } - - void SetName(const QString& name); - void Serialize(SerializeContext& ctx); - - void CreateOptics(); - - IOpticsElementBasePtr GetOptics() const - { - return m_pOptics; - } - - void ReplaceOptics(IOpticsElementBasePtr pNewData); - - XmlNodeRef CreateXmlData() const; - void UpdateLights(IOpticsElementBasePtr pSrcOptics = NULL); - -private: - - void GetLightEntityObjects(std::vector& outEntityLights) const; - static void AddChildOptics(IOpticsElementBasePtr pParentOptics, const XmlNodeRef& pNode); - - IOpticsElementBasePtr m_pOptics; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREITEM_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItemTree.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareItemTree.cpp deleted file mode 100644 index 34cb442a38..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItemTree.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareItemTree.h" - -// Editor -#include "LensFlareItem.h" -#include "ViewManager.h" -#include "Objects/EntityObject.h" - - -CLensFlareItemTree::CLensFlareItemTree(QWidget* pParent) - : QTreeView(pParent) -{ - setHeaderHidden(true); - setSelectionMode(QAbstractItemView::SingleSelection); - setContextMenuPolicy(Qt::CustomContextMenu); - setDragEnabled(true); - setAcceptDrops(true); - setDropIndicatorShown(true); - setDragDropMode(DragDrop); -} - -CLensFlareItemTree::~CLensFlareItemTree() -{ -} - -void CLensFlareItemTree::startDrag(Qt::DropActions supportedDropActions) -{ - QTreeView::startDrag(supportedDropActions); -} - -void CLensFlareItemTree::mousePressEvent(QMouseEvent* event) -{ - if (event->button() == Qt::LeftButton) - { - CUndo undo(tr("Changed lens flare item").toUtf8()); - QTreeView::mousePressEvent(event); - } - else - { - QTreeView::mousePressEvent(event); - } -} - -void CLensFlareItemTree::AssignLensFlareToLightEntity(CViewport* pViewport) const -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - CLensFlareItem* pLensFlareItem = static_cast(selected.first().data(Qt::UserRole).value()); - - QPoint viewportPos = QCursor::pos(); - pViewport->ScreenToClient(viewportPos); - HitContext hit; - if (!pViewport->HitTest(viewportPos, hit)) - { - return; - } - - if (hit.object && qobject_cast(hit.object)) - { - CEntityObject* pEntity = (CEntityObject*)hit.object; - if (pEntity->IsLight()) - { - CUndo undo(tr("Assign a lens flare item to a light entity").toUtf8()); - pEntity->ApplyOptics(pLensFlareItem->GetFullName(), pLensFlareItem->GetOptics()); - } - } -} - -#include diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItemTree.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareItemTree.h deleted file mode 100644 index 1139604163..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItemTree.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREITEMTREE_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREITEMTREE_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "LensFlareElement.h" -#include "ILensFlareListener.h" - -#include -#endif - -class QMouseEvent; -class CLensFlareItem; - -class CLensFlareItemTree - : public QTreeView -{ - Q_OBJECT - -public: - CLensFlareItemTree(QWidget* pParent = nullptr); - ~CLensFlareItemTree(); - -protected: - void startDrag(Qt::DropActions supportedDropActions) override; - void mousePressEvent(QMouseEvent* event) override; - -private: - - void AssignLensFlareToLightEntity(CViewport* pViewport) const; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREITEMTREE_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLibrary.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareLibrary.cpp deleted file mode 100644 index b575b4595c..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLibrary.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareLibrary.h" - -// Editor -#include "LensFlareItem.h" - - -bool CLensFlareLibrary::Save() -{ - return SaveLibrary("LensFlareLibrary"); -} - -bool CLensFlareLibrary::Load(const QString& filename) -{ - if (filename.isEmpty()) - { - return false; - } - SetFilename(filename); - XmlNodeRef root = XmlHelpers::LoadXmlFromFile(filename.toUtf8().data()); - if (!root) - { - return false; - } - Serialize(root, true); - return true; -} - -void CLensFlareLibrary::Serialize(XmlNodeRef& root, bool bLoading) -{ - if (bLoading) - { - RemoveAllItems(); - QString name = GetName(); - root->getAttr("Name", name); - SetName(name); - for (int i = 0; i < root->getChildCount(); i++) - { - XmlNodeRef itemNode = root->getChild(i); - CLensFlareItem* pLensFlareItem = new CLensFlareItem; - AddItem(pLensFlareItem); - CBaseLibraryItem::SerializeContext ctx(itemNode, bLoading); - pLensFlareItem->Serialize(ctx); - } - SetModified(false); - m_bNewLibrary = false; - } - else - { - root->setAttr("Name", GetName().toUtf8().data()); - - for (int i = 0; i < GetItemCount(); i++) - { - CLensFlareItem* pItem = (CLensFlareItem*)GetItem(i); - if(pItem) - { - CBaseLibraryItem::SerializeContext ctx(pItem->CreateXmlData(), bLoading); - root->addChild(ctx.node); - pItem->Serialize(ctx); - } - } - } -} - -IOpticsElementBasePtr CLensFlareLibrary::GetOpticsOfItem(const char* szflareName) -{ - IOpticsElementBasePtr pOptics = NULL; - for (int i = 0; i < GetItemCount(); i++) - { - CLensFlareItem* pItem = (CLensFlareItem*)GetItem(i); - - if (pItem->GetFullName() == szflareName) - { - pOptics = pItem->GetOptics(); - break; - } - } - - return pOptics; -} - - -void CLensFlareLibrary::OnInternalVariableChange([[maybe_unused]] IVariable* pVar) -{ - SetModified(true); -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLibrary.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareLibrary.h deleted file mode 100644 index 484ad3740a..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLibrary.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLARELIBRARY_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLARELIBRARY_H -#pragma once -#include "BaseLibrary.h" - -struct IVariable; - -class CRYEDIT_API CLensFlareLibrary - : public CBaseLibrary -{ -public: - CLensFlareLibrary(IBaseLibraryManager* pManager) - : CBaseLibrary(pManager) {}; - virtual bool Save(); - virtual bool Load(const QString& filename); - virtual void Serialize(XmlNodeRef& node, bool bLoading); - - IOpticsElementBasePtr GetOpticsOfItem(const char* szflareName); - - void OnInternalVariableChange(IVariable* pVar); -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLARELIBRARY_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLightEntityTree.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareLightEntityTree.cpp deleted file mode 100644 index 307364ea4f..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLightEntityTree.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareLightEntityTree.h" - -// Editor -#include "Viewport.h" -#include "Include/IObjectManager.h" -#include "Objects/SelectionGroup.h" -#include "LensFlareItem.h" -#include "LensFlareEditor.h" - - -CLensFlareLightEntityTree::CLensFlareLightEntityTree(QWidget* pParent) - : QTreeView(pParent) - , m_model(new LensFlareLightEntityModel) -{ - setHeaderHidden(true); - - setModel(m_model.data()); - - connect(this, &QTreeView::doubleClicked, this, &CLensFlareLightEntityTree::OnTvnItemDoubleClicked); -} - -CLensFlareLightEntityTree::~CLensFlareLightEntityTree() -{ -} - -void CLensFlareLightEntityTree::OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem) -{ - m_model->OnLensFlareChangeItem(pLensFlareItem); -} - -void CLensFlareLightEntityTree::OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem) -{ - m_model->OnLensFlareDeleteItem(pLensFlareItem); -} - -void CLensFlareLightEntityTree::OnTvnItemDoubleClicked(const QModelIndex& index) -{ - CEntityObject* pObject = index.data(Qt::UserRole).value(); - - if (!qobject_cast(pObject)) - { - return; - } - - CSelectionGroup* pSelection = GetIEditor()->GetObjectManager()->GetSelection(); - if (pSelection) - { - int iSelectionCount(pSelection->GetCount()); - if (iSelectionCount == 1) - { - if (pSelection->GetObject(0) == pObject) - { - CViewport* vp = GetIEditor()->GetActiveView(); - if (vp) - { - vp->CenterOnSelection(); - } - return; - } - } - } - - GetIEditor()->GetObjectManager()->ClearSelection(); - GetIEditor()->GetObjectManager()->SelectObject(pObject); -} - -LensFlareLightEntityModel::LensFlareLightEntityModel(QObject* pParent) - : QAbstractListModel(pParent) -{ - CLensFlareEditor::GetLensFlareEditor()->RegisterLensFlareItemChangeListener(this); - GetIEditor()->GetObjectManager()->AddObjectEventListener(this); -} - -LensFlareLightEntityModel::~LensFlareLightEntityModel() -{ - CLensFlareEditor::GetLensFlareEditor()->UnregisterLensFlareItemChangeListener(this); - GetIEditor()->GetObjectManager()->RemoveObjectEventListener(this); -} - -void LensFlareLightEntityModel::OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem) -{ - beginResetModel(); - - m_pLensFlareItem = pLensFlareItem; - m_lightEntities.clear(); - - if (m_pLensFlareItem) - { - std::vector lightEntities; - LensFlareUtil::GetLightEntityObjects(lightEntities); - - for (int i = 0, iEntitySize(lightEntities.size()); i < iEntitySize; ++i) - { - AddLightEntity(lightEntities[i]); - } - } - - endResetModel(); -} - -void LensFlareLightEntityModel::OnLensFlareDeleteItem([[maybe_unused]] CLensFlareItem* pLensFlareItem) -{ - beginResetModel(); - - m_lightEntities.clear(); - m_pLensFlareItem = NULL; - - endResetModel(); -} - -void LensFlareLightEntityModel::OnObjectEvent(CBaseObject* pObject, int nEvent) -{ - if (!qobject_cast(pObject)) - { - return; - } - - switch (nEvent) - { - case CBaseObject::ON_RENAME: - case CBaseObject::ON_DELETE: - { - auto it = std::find(std::begin(m_lightEntities), std::end(m_lightEntities), pObject); - if (it == std::end(m_lightEntities)) - { - return; - } - int row = std::distance(std::begin(m_lightEntities), it); - if (nEvent == CBaseObject::ON_RENAME) - { - emit dataChanged(index(row, 0), index(row, 0)); - } - else - { - beginRemoveRows({}, row, row); - m_lightEntities.erase(it); - endRemoveRows(); - } - } - break; - - case CBaseObject::ON_ADD: - if (AddLightEntity((CEntityObject*)pObject)) - { - int row = m_lightEntities.size() - 1; - beginInsertRows({}, row, row); - endInsertRows(); - } - break; - } -} - -bool LensFlareLightEntityModel::AddLightEntity(CEntityObject* pEntity) -{ - if (pEntity == NULL || m_pLensFlareItem == NULL) - { - return false; - } - - QString lensFlareName = pEntity->GetEntityPropertyString(CEntityObject::s_LensFlarePropertyName); - if (lensFlareName.isEmpty()) - { - return false; - } - - QString fullName = m_pLensFlareItem->GetFullName(); - if (fullName.isEmpty()) - { - return false; - } - - if (QString::compare(lensFlareName, fullName, Qt::CaseInsensitive)) - { - return false; - } - - m_lightEntities.push_back(pEntity); - - return true; -} - -int LensFlareLightEntityModel::rowCount(const QModelIndex&) const -{ - return m_lightEntities.size(); -} - -QVariant LensFlareLightEntityModel::data(const QModelIndex& index, int role) const -{ - const int row = index.row(); - - if (row < 0 || row >= m_lightEntities.size()) - { - return {}; - } - - auto pEntity = m_lightEntities[row]; - - switch (role) - { - case Qt::DisplayRole: - return pEntity->GetName(); - - case Qt::UserRole: - return QVariant::fromValue(pEntity); - } - - return {}; -} - -#include diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLightEntityTree.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareLightEntityTree.h deleted file mode 100644 index 21a271c08f..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLightEntityTree.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLARELIGHTENTITYTREE_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLARELIGHTENTITYTREE_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "ILensFlareListener.h" - -#include -#include -#include "IObjectManager.h" // for IObjectManager::EventListener -#include "Objects/EntityObject.h" -#endif - -class LensFlareLightEntityModel; - -class CLensFlareLightEntityTree - : public QTreeView -{ - Q_OBJECT - -public: - CLensFlareLightEntityTree(QWidget* pParent = nullptr); - ~CLensFlareLightEntityTree(); - - void OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem); - void OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem); - -protected: - void OnTvnItemDoubleClicked(const QModelIndex& index); - - QScopedPointer m_model; -}; - -class LensFlareLightEntityModel - : public QAbstractListModel - , public ILensFlareChangeItemListener - , public IObjectManager::EventListener -{ - Q_OBJECT - -public: - LensFlareLightEntityModel(QObject* pParent = nullptr); - ~LensFlareLightEntityModel(); - - int rowCount(const QModelIndex& parent = {}) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - - void OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem); - void OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem); - -protected: - void OnObjectEvent(CBaseObject* pObject, int nEvent) override; - - bool AddLightEntity(CEntityObject* pEntity); - - std::vector m_lightEntities; - _smart_ptr m_pLensFlareItem; -}; - -Q_DECLARE_METATYPE(CEntityObject*) - -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLARELIGHTENTITYTREE_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareManager.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareManager.cpp deleted file mode 100644 index c28832898f..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareManager.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareManager.h" - -// AzCore -#include -#include - -// Editor -#include "LensFlareEditor.h" -#include "LensFlareItem.h" -#include "LensFlareLibrary.h" -#include "LensFlareUtil.h" - - -////////////////////////////////////////////////////////////////////////// -// CLensFlareManager implementation. -////////////////////////////////////////////////////////////////////////// -CLensFlareManager::CLensFlareManager() - : CBaseLibraryManager() -{ - m_bUniqNameMap = true; - m_pLevelLibrary = (CBaseLibrary*)AddLibrary("Level", true); - AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect(); -} - -////////////////////////////////////////////////////////////////////////// -CLensFlareManager::~CLensFlareManager() -{ - AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); -} - -////////////////////////////////////////////////////////////////////////// -void CLensFlareManager::ClearAll() -{ - CBaseLibraryManager::ClearAll(); - - m_pLevelLibrary = (CBaseLibrary*)AddLibrary("Level", true); -} - -////////////////////////////////////////////////////////////////////////// -CBaseLibraryItem* CLensFlareManager::MakeNewItem() -{ - return new CLensFlareItem; -} - -////////////////////////////////////////////////////////////////////////// -CBaseLibrary* CLensFlareManager::MakeNewLibrary() -{ - return new CLensFlareLibrary(this); -} - -////////////////////////////////////////////////////////////////////////// -QString CLensFlareManager::GetRootNodeName() -{ - return "FlareLibs"; -} - -////////////////////////////////////////////////////////////////////////// -QString CLensFlareManager::GetLibsPath() -{ - if (m_libsPath.isEmpty()) - { - m_libsPath += FLARE_LIBS_PATH; - } - - return m_libsPath; -} - -////////////////////////////////////////////////////////////////////////// -bool CLensFlareManager::LoadFlareItemByName(const QString& fullItemName, IOpticsElementBasePtr pDestOptics) -{ - if (pDestOptics == NULL) - { - return false; - } - - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)LoadItemByName(fullItemName); - if (pLensFlareItem == NULL) - { - return false; - } - - LensFlareUtil::CopyOptics(pLensFlareItem->GetOptics(), pDestOptics, true); - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CLensFlareManager::Modified() -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return; - } - if (pEditor->GetCurrentLibrary()) - { - pEditor->GetCurrentLibrary()->SetModified(true); - } -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseLibrary* CLensFlareManager::LoadLibrary(const QString& filename, [[maybe_unused]] bool bReload) -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - - QString fileNameWithGameFolder(filename); - - fileNameWithGameFolder.replace('\\', '/'); - - int nGamePathLength = static_cast(Path::GetEditingGameDataFolder().size()); - QString gamePathName; - if (nGamePathLength < filename.length()) - { - gamePathName = filename.left(nGamePathLength); - } - if (gamePathName != Path::GetEditingGameDataFolder().c_str()) - { - fileNameWithGameFolder.insert(0, "/"); - fileNameWithGameFolder.insert(0, Path::GetEditingGameDataFolder().c_str()); - } - - int nLibraryIndex(-1); - bool bSameAsCurrentLibrary(false); - - for (int i = 0; i < m_libs.size(); i++) - { - if (QString::compare(fileNameWithGameFolder, m_libs[i]->GetFilename(), Qt::CaseInsensitive) == 0) - { - IDataBaseLibrary* pExistingLib = m_libs[i]; - for (int j = 0; j < pExistingLib->GetItemCount(); j++) - { - UnregisterItem((CBaseLibraryItem*)pExistingLib->GetItem(j)); - } - pExistingLib->RemoveAllItems(); - nLibraryIndex = i; - if (pEditor) - { - bSameAsCurrentLibrary = pEditor->GetCurrentLibrary() == pExistingLib; - } - break; - } - } - - TSmartPtr pLib = MakeNewLibrary(); - if (!pLib->Load(filename)) - { - Error(QObject::tr("Failed to Load Item Library: %1").arg(filename).toUtf8().data()); - return NULL; - } - - if (nLibraryIndex != -1) - { - m_libs[nLibraryIndex] = pLib; - if (bSameAsCurrentLibrary && pEditor) - { - pEditor->ResetElementTreeControl(); - pEditor->SelectLibrary(pLib, true); - } - } - else - { - m_libs.push_back(pLib); - } - - pLib->SetFilename(filename); - - return pLib; -} - - -bool CLensFlareManager::IsLensFlareLibraryXML(const char* fileSourceFilePath) -{ - if ((!fileSourceFilePath) || (!AZStd::wildcard_match("*.xml", fileSourceFilePath))) - { - return false; - } - - using namespace AZ::IO; - - bool isLensFlareLibrary = false; - - // we are forced to read the asset to discover its type since "xml" was the chosen extension. - SystemFile::SizeType fileSize = SystemFile::Length(fileSourceFilePath); - if (fileSize > 0) - { - AZStd::vector buffer(fileSize + 1); - buffer[fileSize] = 0; - if (!AZ::IO::SystemFile::Read(fileSourceFilePath, buffer.data(), fileSize)) - { - return false; - } - - AZ::rapidxml::xml_document* xmlDoc = azcreate(AZ::rapidxml::xml_document, (), AZ::SystemAllocator, "LensFlareLibrary Temp XML Reader"); - if (xmlDoc->parse(buffer.data())) - { - AZ::rapidxml::xml_node* xmlRootNode = xmlDoc->first_node(); - if (xmlRootNode) - { - if (azstricmp(xmlRootNode->name(), "LensFlareLibrary") == 0) - { - isLensFlareLibrary = true; - } - } - } - - azdestroy(xmlDoc, AZ::SystemAllocator, AZ::rapidxml::xml_document); - } - - return isLensFlareLibrary; -} - - -AzToolsFramework::AssetBrowser::SourceFileDetails CLensFlareManager::GetSourceFileDetails(const char* fullSourceFileName) -{ - if (IsLensFlareLibraryXML(fullSourceFileName)) - { - return AzToolsFramework::AssetBrowser::SourceFileDetails("Icons/AssetBrowser/LensFlare_16.png"); - } - return AzToolsFramework::AssetBrowser::SourceFileDetails(); -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareManager.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareManager.h deleted file mode 100644 index 9cc7c6fad2..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareManager.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREMANAGER_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREMANAGER_H -#pragma once - -#include "BaseLibraryManager.h" -#include - -class IOpticsElementBase; -class CLensFlareEditor; - -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING -class CRYEDIT_API CLensFlareManager - : public CBaseLibraryManager - , private AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler - -{ -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING -public: - CLensFlareManager(); - virtual ~CLensFlareManager(); - - void ClearAll(); - - virtual bool LoadFlareItemByName(const QString& fullItemName, IOpticsElementBasePtr pDestOptics); - void Modified(); - //! Path to libraries in this manager. - QString GetLibsPath(); - IDataBaseLibrary* LoadLibrary(const QString& filename, bool bReload = false); - - static bool IsLensFlareLibraryXML(const char* fullFilePath); - -private: - CBaseLibraryItem* MakeNewItem(); - CBaseLibrary* MakeNewLibrary(); - - //! Root node where this library will be saved. - QString GetRootNodeName(); - QString m_libsPath; - - //////////////////////////////////////////////////////////////////////////////////////////////////////////// - // AssetBrowser::AssetBrowserInteractionNotificationBus::Handler - AzToolsFramework::AssetBrowser::SourceFileDetails GetSourceFileDetails(const char* fullSourceFileName) override; - virtual AZ::s32 GetPriority() const override { return 1; } // get our priority in before others. - //////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -}; - -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREMANAGER_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareReferenceTree.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareReferenceTree.cpp deleted file mode 100644 index 3c628d1b34..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareReferenceTree.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" -#include "LensFlareReferenceTree.h" - -BEGIN_MESSAGE_MAP (CLensFlareReferenceTree, CXTTreeCtrl) -END_MESSAGE_MAP () - -CLensFlareReferenceTree::CLensFlareReferenceTree() -{ -} - -CLensFlareReferenceTree::~CLensFlareReferenceTree() -{ -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareReferenceTree.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareReferenceTree.h deleted file mode 100644 index 77ca781a30..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareReferenceTree.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREREFERENCETREE_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREREFERENCETREE_H -#pragma once - -class CLensFlareReferenceTree - : public CXTTreeCtrl -{ -public: - - CLensFlareReferenceTree(); - ~CLensFlareReferenceTree(); - -private: - - DECLARE_MESSAGE_MAP() -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREREFERENCETREE_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUndo.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareUndo.cpp deleted file mode 100644 index a6b35eba13..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUndo.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareUndo.h" - -// Editor -#include "LensFlareEditor.h" -#include "LensFlareItem.h" -#include "LensFlareManager.h" -#include "LensFlareElementTree.h" - - -void RestoreLensFlareItem(CLensFlareItem* pLensFlareItem, IOpticsElementBasePtr pOptics, const QString& flarePathName) -{ - pLensFlareItem->ReplaceOptics(pOptics); - - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor) - { - if (pOptics->GetType() == eFT_Root) - { - pEditor->RenameLensFlareItem(pLensFlareItem, pLensFlareItem->GetGroupName(), LensFlareUtil::GetShortName(flarePathName)); - pEditor->UpdateLensFlareItem(pLensFlareItem); - } - } -} - -void ActivateLensFlareItem(CLensFlareItem* pLensFlareItem, bool bRestoreSelectInfo, const QString& selectedFlareItemName) -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return; - } - if (pLensFlareItem == pEditor->GetLensFlareElementTree()->GetLensFlareItem()) - { - pEditor->UpdateLensFlareItem(pLensFlareItem); - if (bRestoreSelectInfo) - { - pEditor->SelectItemInLensFlareElementTreeByName(selectedFlareItemName); - } - } -} - -CUndoLensFlareItem::CUndoLensFlareItem(CLensFlareItem* pLensFlareItem, const QString& undoDescription) -{ - if (pLensFlareItem) - { - m_Undo.m_pOptics = LensFlareUtil::CreateOptics(pLensFlareItem->GetOptics()); - m_flarePathName = pLensFlareItem->GetFullName(); - m_Undo.m_bRestoreSelectInfo = false; - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor) - { - m_Undo.m_bRestoreSelectInfo = pEditor->GetSelectedLensFlareName(m_Undo.m_selectedFlareItemName); - } - m_undoDescription = undoDescription; - } -} - -CUndoLensFlareItem::~CUndoLensFlareItem() -{ -} - -void CUndoLensFlareItem::Undo(bool bUndo) -{ - if (bUndo) - { - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(m_flarePathName); - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor && pLensFlareItem) - { - m_Redo.m_bRestoreSelectInfo = false; - m_Redo.m_pOptics = LensFlareUtil::CreateOptics(pLensFlareItem->GetOptics()); - m_Redo.m_bRestoreSelectInfo = pEditor->GetSelectedLensFlareName(m_Redo.m_selectedFlareItemName); - } - } - Restore(m_Undo); -} - -void CUndoLensFlareItem::Redo() -{ - Restore(m_Redo); -} - -void CUndoLensFlareItem::Restore(const SData& data) -{ - if (data.m_pOptics == NULL) - { - return; - } - - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(m_flarePathName); - if (pLensFlareItem == NULL) - { - return; - } - RestoreLensFlareItem(pLensFlareItem, data.m_pOptics, m_flarePathName); - ActivateLensFlareItem(pLensFlareItem, data.m_bRestoreSelectInfo, data.m_selectedFlareItemName); -} - -CUndoRenameLensFlareItem::CUndoRenameLensFlareItem(const QString& oldFullName, const QString& newFullName) -{ - m_undo.m_oldFullItemName = oldFullName; - m_undo.m_newFullItemName = newFullName; -} - -void CUndoRenameLensFlareItem::Undo(bool bUndo) -{ - if (bUndo) - { - m_redo.m_oldFullItemName = m_undo.m_newFullItemName; - m_redo.m_newFullItemName = m_undo.m_oldFullItemName; - } - - Rename(m_undo); -} - -void CUndoRenameLensFlareItem::Redo() -{ - Rename(m_redo); -} - -void CUndoRenameLensFlareItem::Rename(const SUndoDataStruct& data) -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return; - } - - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(data.m_newFullItemName); - if (pLensFlareItem == NULL) - { - return; - } - - int nDotPos = data.m_oldFullItemName.indexOf("."); - if (nDotPos == -1) - { - return; - } - - QString shortName(LensFlareUtil::GetShortName(data.m_oldFullItemName)); - QString groupName(LensFlareUtil::GetGroupNameFromFullName(data.m_oldFullItemName)); - pEditor->RenameLensFlareItem(pLensFlareItem, groupName, shortName); - if (pLensFlareItem->GetOptics()) - { - pLensFlareItem->GetOptics()->SetName(shortName.toUtf8().data()); - LensFlareUtil::UpdateOpticsName(pLensFlareItem->GetOptics()); - } - pEditor->UpdateLensFlareItem(pLensFlareItem); -} - -CUndoLensFlareElementSelection::CUndoLensFlareElementSelection(CLensFlareItem* pLensFlareItem, const QString& flareTreeItemFullName, const QString& undoDescription) -{ - if (pLensFlareItem) - { - m_flarePathNameForUndo = pLensFlareItem->GetFullName(); - m_flareTreeItemFullNameForUndo = flareTreeItemFullName; - m_undoDescription = undoDescription; - } -} - -void CUndoLensFlareElementSelection::Undo(bool bUndo) -{ - if (bUndo) - { - m_flarePathNameForRedo = m_flarePathNameForUndo; - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor) - { - pEditor->GetSelectedLensFlareName(m_flareTreeItemFullNameForRedo); - } - } - - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(m_flarePathNameForUndo); - if (pLensFlareItem == NULL) - { - return; - } - ActivateLensFlareItem(pLensFlareItem, true, m_flareTreeItemFullNameForUndo); -} - -void CUndoLensFlareElementSelection::Redo() -{ - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(m_flarePathNameForRedo); - if (pLensFlareItem == NULL) - { - return; - } - ActivateLensFlareItem(pLensFlareItem, true, m_flareTreeItemFullNameForRedo); -} - -CUndoLensFlareItemSelectionChange::CUndoLensFlareItemSelectionChange(const QString& fullLensFlareItemName, const QString& undoDescription) -{ - m_FullLensFlareItemNameForUndo = fullLensFlareItemName; - m_undoDescription = undoDescription; -} - -void CUndoLensFlareItemSelectionChange::Undo(bool bUndo) -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return; - } - - if (bUndo) - { - QString currentFullName; - pEditor->GetFullSelectedFlareItemName(currentFullName); - m_FullLensFlareItemNameForRedo = currentFullName; - } - - pEditor->SelectLensFlareItem(m_FullLensFlareItemNameForUndo); -} - -void CUndoLensFlareItemSelectionChange::Redo() -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return; - } - pEditor->SelectLensFlareItem(m_FullLensFlareItemNameForRedo); -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUndo.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareUndo.h deleted file mode 100644 index cf8f76c321..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUndo.h +++ /dev/null @@ -1,143 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREUNDO_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREUNDO_H -#pragma once - -#include "Undo/IUndoObject.h" - -class CLensFlareItem; - -class CUndoLensFlareItem - : public IUndoObject -{ -public: - CUndoLensFlareItem(CLensFlareItem* pGroupItem, const QString& undoDescription = "Undo Lens Flare Tree"); - ~CUndoLensFlareItem(); - -protected: - int GetSize() - { - return sizeof(*this); - } - QString GetDescription() { return m_undoDescription; }; - void Undo(bool bUndo); - void Redo(); - -private: - - QString m_undoDescription; - - struct SData - { - SData() - { - m_pOptics = NULL; - } - - QString m_selectedFlareItemName; - bool m_bRestoreSelectInfo; - IOpticsElementBasePtr m_pOptics; - }; - - QString m_flarePathName; - SData m_Undo; - SData m_Redo; - - void Restore(const SData& data); -}; - -class CUndoRenameLensFlareItem - : public IUndoObject -{ -public: - - CUndoRenameLensFlareItem(const QString& oldFullName, const QString& newFullName); - -protected: - - int GetSize() - { - return sizeof(*this); - } - QString GetDescription() { return m_undoDescription; }; - void Undo(bool bUndo); - void Redo(); - -private: - - QString m_undoDescription; - - struct SUndoDataStruct - { - QString m_oldFullItemName; - QString m_newFullItemName; - }; - - void Rename(const SUndoDataStruct& data); - - SUndoDataStruct m_undo; - SUndoDataStruct m_redo; -}; - -class CUndoLensFlareElementSelection - : public IUndoObject -{ -public: - CUndoLensFlareElementSelection(CLensFlareItem* pLensFlareItem, const QString& flareTreeItemFullName, const QString& undoDescription = "Undo Lens Flare Element Tree"); - ~CUndoLensFlareElementSelection(){} - -protected: - int GetSize() - { - return sizeof(*this); - } - QString GetDescription() { return m_undoDescription; }; - void Undo(bool bUndo); - void Redo(); - -private: - - QString m_undoDescription; - - QString m_flarePathNameForUndo; - QString m_flareTreeItemFullNameForUndo; - - QString m_flarePathNameForRedo; - QString m_flareTreeItemFullNameForRedo; -}; - -class CUndoLensFlareItemSelectionChange - : public IUndoObject -{ -public: - CUndoLensFlareItemSelectionChange(const QString& fullLensFlareItemName, const QString& undoDescription = "Undo Lens Flare element selection"); - ~CUndoLensFlareItemSelectionChange(){} - -protected: - int GetSize() - { - return sizeof(*this); - } - QString GetDescription() { return m_undoDescription; }; - - void Undo(bool bUndo); - void Redo(); - -private: - QString m_undoDescription; - QString m_FullLensFlareItemNameForUndo; - QString m_FullLensFlareItemNameForRedo; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREUNDO_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUtil.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareUtil.cpp deleted file mode 100644 index e8ff29f987..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUtil.cpp +++ /dev/null @@ -1,1012 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareUtil.h" - -// Editor -#include "Clipboard.h" -#include "Objects/EntityObject.h" -#include "Objects/SelectionGroup.h" -#include "Include/IObjectManager.h" - - -namespace LensFlareUtil -{ - IOpticsElementBasePtr CreateOptics(const XmlNodeRef& xmlNode) - { - IOpticsElementBasePtr pOpticsElement = NULL; - - const char* typeName; - if (!xmlNode->getAttr("Type", &typeName)) - { - return NULL; - } - - bool bEnable(true); - xmlNode->getAttr("Enable", bEnable); - - EFlareType flareType; - if (!GetFlareType(typeName, flareType)) - { - return NULL; - } - - pOpticsElement = gEnv->pOpticsManager->Create(flareType); - if (pOpticsElement == NULL) - { - return NULL; - } - - pOpticsElement->SetEnabled(bEnable); - - if (!FillOpticsFromXML(pOpticsElement, xmlNode)) - { - return NULL; - } - - return pOpticsElement; - } - - IOpticsElementBasePtr CreateOptics(IOpticsElementBasePtr pOptics, bool bForceTypeToGroup) - { - if (pOptics == NULL) - { - return NULL; - } - IOpticsElementBasePtr pNewOptics = NULL; - if (bForceTypeToGroup) - { - if (pOptics->GetType() == eFT_Root) - { - pNewOptics = gEnv->pOpticsManager->Create(eFT_Group); - } - } - if (pNewOptics == NULL) - { - pNewOptics = gEnv->pOpticsManager->Create(pOptics->GetType()); - if (pNewOptics == NULL) - { - return NULL; - } - } - CopyOptics(pOptics, pNewOptics, true); - return pNewOptics; - } - - bool FillOpticsFromXML(IOpticsElementBasePtr pOpticsElement, const XmlNodeRef& xmlNode) - { - if (!pOpticsElement) - { - return false; - } - - const char* name; - if (!xmlNode->getAttr("Name", &name)) - { - return false; - } - - const char* typeName; - if (!xmlNode->getAttr("Type", &typeName)) - { - return false; - } - EFlareType flareType; - if (!GetFlareType(typeName, flareType)) - { - return false; - } - if (flareType != pOpticsElement->GetType()) - { - return false; - } - - pOpticsElement->SetName(name); - - bool bEnable(true); - xmlNode->getAttr("Enable", bEnable); - pOpticsElement->SetEnabled(bEnable); - - XmlNodeRef pParamNode = xmlNode->findChild("Params"); - if (pParamNode == NULL) - { - return false; - } - - LensFlareUtil::FillParams(pParamNode, pOpticsElement); - return true; - } - - bool CreateXmlData(IOpticsElementBasePtr pOptics, XmlNodeRef& pOutNode) - { - pOutNode = gEnv->pSystem->CreateXmlNode("FlareItem"); - - if (pOptics == NULL || pOutNode == NULL) - { - return false; - } - - QString typeName; - if (!GetFlareTypeName(typeName, pOptics)) - { - return false; - } - - pOutNode->setAttr("Name", pOptics->GetName().c_str()); - pOutNode->setAttr("Type", typeName.toUtf8().data()); - pOutNode->setAttr("Enable", pOptics->IsEnabled()); - - XmlNodeRef pParamNode = pOutNode->createNode("Params"); - - CVarBlockPtr pVar; - SetVariablesTemplateFromOptics(pOptics, pVar); - - pVar->Serialize(pParamNode, false); - pOutNode->addChild(pParamNode); - - for (int i = 0, iElementCount(pOptics->GetElementCount()); i < iElementCount; ++i) - { - XmlNodeRef pNode = NULL; - IOpticsElementBasePtr pChildOptics = pOptics->GetElementAt(i); - if (!CreateXmlData(pChildOptics, pNode)) - { - continue; - } - - pOutNode->addChild(pNode); - } - - return true; - } - - void SetVariablesTemplateFromOptics(IOpticsElementBasePtr pOptics, CVarBlockPtr& pRootVar, std::vector& funcs) - { - if (pOptics == NULL) - { - return; - } - - SetVariablesTemplateFromOptics(pOptics, pRootVar); - - for (int i = 0, iNumVariables(pRootVar->GetNumVariables()); i < iNumVariables; ++i) - { - IVariable* pVariable = pRootVar->GetVariable(i); - if (pVariable == NULL) - { - continue; - } - for (int k = 0, iNumVariables2(pVariable->GetNumVariables()); k < iNumVariables2; ++k) - { - IVariable* pChildVariable(pVariable->GetVariable(k)); - if (pChildVariable == NULL) - { - continue; - } - for (int ii = 0, iSize(funcs.size()); ii < iSize; ++ii) - { - pChildVariable->AddOnSetCallback(funcs[ii]); - } - } - } - } - - extern void SetVariablesTemplateFromOptics(IOpticsElementBasePtr pOptics, CVarBlockPtr& pRootVar) - { - if (pOptics == NULL) - { - return; - } - - AZStd::vector paramGroups = pOptics->GetEditorParamGroups(); - pRootVar = new CVarBlock; - - for (int i = 0; i < paramGroups.size(); ++i) - { - CSmartVariableArray variableArray; - FuncVariableGroup* pGroup = ¶mGroups[i]; - if (pGroup == NULL) - { - continue; - } - - QString displayGroupName(pGroup->GetHumanName()); - if (displayGroupName == "Common") - { - FlareInfoArray::Props flareInfo = FlareInfoArray::Get(); - int nTypeIndex = (int)pOptics->GetType(); - if (nTypeIndex >= 0 && nTypeIndex < flareInfo.size) - { - displayGroupName += " : "; - displayGroupName += flareInfo.p[nTypeIndex].name; - } - } - - AddVariable(pRootVar, variableArray, pGroup->GetName(), displayGroupName.toUtf8().data(), ""); - - for (int k = 0; k < pGroup->GetVariableCount(); ++k) - { - IFuncVariable* pFuncVar = pGroup->GetVariable(k); - bool bHardMinLimitation = false; - - const std::pair range(pFuncVar->GetMin(), pFuncVar->GetMax()); - - if (pFuncVar->paramType == e_FLOAT) - { - CSmartVariable floatVar; - AddVariable(variableArray, floatVar, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str()); - floatVar->SetLimits(range.first, range.second, 0, bHardMinLimitation, false); - floatVar->Set(pFuncVar->GetFloat()); - floatVar->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_INT) - { - CSmartVariable intVar; - AddVariable(variableArray, intVar, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str()); - - bHardMinLimitation = HaveParameterLowBoundary(pFuncVar->name.c_str()); - intVar->SetLimits(range.first, range.second, 0, bHardMinLimitation, false); - - intVar->Set(pFuncVar->GetInt()); - intVar->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_BOOL) - { - CSmartVariable boolVar; - AddVariable(variableArray, boolVar, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str()); - boolVar->Set(pFuncVar->GetBool()); - boolVar->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_VEC2) - { - CSmartVariable vec2Var; - AddVariable(variableArray, vec2Var, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str()); - vec2Var->SetLimits(range.first, range.second, 0, bHardMinLimitation, false); - vec2Var->Set(pFuncVar->GetVec2()); - vec2Var->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_VEC3) - { - CSmartVariable vec3Var; - AddVariable(variableArray, vec3Var, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str()); - vec3Var->SetLimits(range.first, range.second, 0, bHardMinLimitation, false); - vec3Var->Set(pFuncVar->GetVec3()); - vec3Var->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_VEC4) - { - CSmartVariable vec4Var; - AddVariable(variableArray, vec4Var, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str()); - vec4Var->SetLimits(range.first, range.second, 0, bHardMinLimitation, false); - vec4Var->Set(pFuncVar->GetVec4()); - vec4Var->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_COLOR) - { - CSmartVariable colorVar; - AddVariable(variableArray, colorVar, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str(), IVariable::DT_COLOR); - ColorF color(pFuncVar->GetColorF()); - Vec3 colorVec3(color.r, color.g, color.b); - colorVar->Set(colorVec3); - colorVar->SetUserData(MakeFuncKey(i, k)); - - CSmartVariable alphaVar; - QString alphaName(pFuncVar->name.c_str()); - alphaName += ".alpha"; - QString alphaHumanName(pFuncVar->humanName.c_str()); - alphaHumanName += " [alpha]"; - AddVariable(variableArray, alphaVar, alphaName.toUtf8().data(), alphaHumanName.toUtf8().data(), pFuncVar->description.c_str()); - alphaVar->SetLimits(0, 255, 0, bHardMinLimitation, false); - alphaVar->Set(color.a * 255.0f); - alphaVar->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_MATRIX33) - { - // Reserved part - // This part is for future because Matrix33 type is suppose to be provided in a renderer side - } - else if (pFuncVar->paramType == e_TEXTURE2D || pFuncVar->paramType == e_TEXTURE3D || pFuncVar->paramType == e_TEXTURE_CUBE) - { - CSmartVariable textureVar; - ITexture* pTexture = pFuncVar->GetTexture(); - if (pTexture) - { - QString textureName = pTexture->GetName(); - textureVar->Set(textureName); - } - AddVariable(variableArray, textureVar, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str(), IVariable::DT_TEXTURE); - textureVar->SetUserData(MakeFuncKey(i, k)); - } - } - } - } - - void AddOptics(IOpticsElementBasePtr pParentOptics, const XmlNodeRef& xmlNode) - { - if (xmlNode == NULL) - { - return; - } - - if (strcmp(xmlNode->getTag(), "FlareItem")) - { - return; - } - - IOpticsElementBasePtr pOptics = CreateOptics(xmlNode); - if (pOptics == NULL) - { - return; - } - pParentOptics->AddElement(pOptics); - - for (int i = 0, iChildCount(xmlNode->getChildCount()); i < iChildCount; ++i) - { - AddOptics(pOptics, xmlNode->getChild(i)); - } - } - - void CopyVariable(IFuncVariable* pSrcVar, IFuncVariable* pDestVar) - { - if (!pSrcVar || !pDestVar) - { - return; - } - - if (pSrcVar->paramType != pDestVar->paramType) - { - return; - } - - if (pSrcVar->paramType == e_FLOAT) - { - float value = pSrcVar->GetFloat(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_BOOL) - { - bool value = pSrcVar->GetBool(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_INT) - { - int value = pSrcVar->GetInt(); - if (HaveParameterLowBoundary(pSrcVar->name.c_str())) - { - BoundaryProcess(value); - } - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_VEC2) - { - Vec2 value = pSrcVar->GetVec2(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_VEC3) - { - Vec3 value = pSrcVar->GetVec3(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_VEC4) - { - Vec4 value = pSrcVar->GetVec4(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_COLOR) - { - ColorF value = pSrcVar->GetColorF(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_MATRIX33) - { - Matrix33 value = pSrcVar->GetMatrix33(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_TEXTURE2D || pSrcVar->paramType == e_TEXTURE3D || pSrcVar->paramType == e_TEXTURE_CUBE) - { - ITexture* value = pSrcVar->GetTexture(); - pDestVar->InvokeSetter((void*)value); - } - } - - void CopyOpticsAboutSameOpticsType(IOpticsElementBasePtr pSrcOptics, IOpticsElementBasePtr pDestOptics) - { - if (pSrcOptics->GetType() != pDestOptics->GetType()) - { - return; - } - - AZStd::vector srcVarGroups = pSrcOptics->GetEditorParamGroups(); - AZStd::vector destVarGroups = pDestOptics->GetEditorParamGroups(); - - if (srcVarGroups.size() != destVarGroups.size()) - { - return; - } - - pDestOptics->SetEnabled(pSrcOptics->IsEnabled()); - - for (int i = 0, iVarGroupSize(srcVarGroups.size()); i < iVarGroupSize; ++i) - { - FuncVariableGroup srcVarGroup = srcVarGroups[i]; - FuncVariableGroup destVarGroup = destVarGroups[i]; - - if (srcVarGroup.GetVariableCount() != destVarGroup.GetVariableCount()) - { - continue; - } - - for (int k = 0, iVarSize(srcVarGroup.GetVariableCount()); k < iVarSize; ++k) - { - IFuncVariable* pSrcVar = srcVarGroup.GetVariable(k); - IFuncVariable* pDestVar = destVarGroup.GetVariable(k); - CopyVariable(pSrcVar, pDestVar); - } - } - } - - bool FindGroupByName(AZStd::vector& groupList, const QString& name, int& outIndex) - { - for (int i = 0, iVarGroupSize(groupList.size()); i < iVarGroupSize; ++i) - { - if (name == groupList[i].GetName()) - { - outIndex = i; - return true; - } - } - return false; - } - - void CopyOpticsAboutDifferentOpticsType(IOpticsElementBasePtr pSrcOptics, IOpticsElementBasePtr pDestOptics) - { - if (pSrcOptics->GetType() == pDestOptics->GetType()) - { - return; - } - - AZStd::vector srcVarGroups = pSrcOptics->GetEditorParamGroups(); - AZStd::vector destVarGroups = pDestOptics->GetEditorParamGroups(); - - pDestOptics->SetEnabled(pSrcOptics->IsEnabled()); - - for (int i = 0, iVarGroupSize(destVarGroups.size()); i < iVarGroupSize; ++i) - { - FuncVariableGroup destVarGroup = destVarGroups[i]; - int nIndex = 0; - if (!FindGroupByName(srcVarGroups, destVarGroup.GetName(), nIndex)) - { - continue; - } - FuncVariableGroup srcVarGroup = srcVarGroups[nIndex]; - - for (int k = 0, iVarSize(destVarGroup.GetVariableCount()); k < iVarSize; ++k) - { - IFuncVariable* pDestVar = destVarGroup.GetVariable(k); - IFuncVariable* pSrcVar = srcVarGroup.FindVariable(pDestVar->name.c_str()); - CopyVariable(pSrcVar, pDestVar); - } - } - } - - void CopyOptics(IOpticsElementBasePtr pSrcOptics, IOpticsElementBasePtr pDestOptics, bool bReculsiveCopy) - { - if (pSrcOptics->GetType() == pDestOptics->GetType()) - { - CopyOpticsAboutSameOpticsType(pSrcOptics, pDestOptics); - } - else - { - CopyOpticsAboutDifferentOpticsType(pSrcOptics, pDestOptics); - } - - if (bReculsiveCopy) - { - pDestOptics->RemoveAll(); - for (int i = 0, iChildCount(pSrcOptics->GetElementCount()); i < iChildCount; ++i) - { - IOpticsElementBasePtr pSrcChildOptics = pSrcOptics->GetElementAt(i); - IOpticsElementBasePtr pNewOptics = gEnv->pOpticsManager->Create(pSrcChildOptics->GetType()); - if (pNewOptics == NULL) - { - continue; - } - pNewOptics->SetName(pSrcChildOptics->GetName().c_str()); - CopyOptics(pSrcChildOptics, pNewOptics, bReculsiveCopy); - pDestOptics->AddElement(pNewOptics); - } - } - } - - CEntityObject* GetSelectedLightEntity() - { - CBaseObject* pSelectedObj = GetIEditor()->GetSelectedObject(); - if (pSelectedObj == NULL) - { - return NULL; - } - if (!qobject_cast(pSelectedObj)) - { - return NULL; - } - CEntityObject* pEntity = (CEntityObject*)pSelectedObj; - if (!pEntity->IsLight()) - { - return NULL; - } - return pEntity; - } - - void GetSelectedLightEntities(std::vector& outLightEntities) - { - CSelectionGroup* pSelectionGroup = GetIEditor()->GetSelection(); - if (pSelectionGroup == NULL) - { - return; - } - int nSelectionCount = pSelectionGroup->GetCount(); - outLightEntities.reserve(nSelectionCount); - for (int i = 0; i < nSelectionCount; ++i) - { - CBaseObject* pSelectedObj = pSelectionGroup->GetObject(i); - if (!qobject_cast(pSelectedObj)) - { - continue; - } - CEntityObject* pEntity = (CEntityObject*)pSelectedObj; - if (!pEntity->IsLight()) - { - continue; - } - outLightEntities.push_back(pEntity); - } - } - - IOpticsElementBasePtr GetSelectedLightOptics() - { - CEntityObject* pEntity = GetSelectedLightEntity(); - if (pEntity == NULL) - { - return NULL; - } - IOpticsElementBasePtr pEntityOptics = pEntity->GetOpticsElement(); - if (pEntityOptics == NULL) - { - return NULL; - } - return pEntityOptics; - } - - IOpticsElementBasePtr FindOptics(IOpticsElementBasePtr pStartOptics, const QString& name) - { - if (pStartOptics == NULL) - { - return NULL; - } - - if (!QString::compare(pStartOptics->GetName().c_str(), name)) - { - return pStartOptics; - } - - for (int i = 0, iElementCount(pStartOptics->GetElementCount()); i < iElementCount; ++i) - { - IOpticsElementBasePtr pFoundOptics = FindOptics(pStartOptics->GetElementAt(i), name); - if (pFoundOptics) - { - return pFoundOptics; - } - } - - return NULL; - } - - void RemoveOptics(IOpticsElementBasePtr pOptics) - { - if (pOptics == NULL) - { - return; - } - - IOpticsElementBasePtr pParent = pOptics->GetParent(); - if (pParent == NULL) - { - return; - } - - for (int i = 0, iElementCount(pParent->GetElementCount()); i < iElementCount; ++i) - { - if (pOptics == pParent->GetElementAt(i)) - { - pParent->Remove(i); - break; - } - } - } - - void ChangeOpticsRootName(IOpticsElementBasePtr pOptics, const QString& newRootName) - { - if (pOptics == NULL) - { - return; - } - - QString opticsName = pOptics->GetName().c_str(); - QString opticsRootName; - - int nPos = opticsName.indexOf("."); - if (nPos == -1) - { - opticsRootName = opticsName; - } - else - { - opticsRootName = opticsName.left(nPos); - } - - opticsName.replace(opticsRootName, newRootName); - pOptics->SetName(opticsName.toUtf8().data()); - - for (int i = 0, iElementSize(pOptics->GetElementCount()); i < iElementSize; ++i) - { - ChangeOpticsRootName(pOptics->GetElementAt(i), newRootName); - } - } - - void UpdateClipboard(const QString& type, const QString& groupName, bool bPasteAtSameLevel, std::vector& dataList) - { - XmlNodeRef rootNode = CreateXMLFromClipboardData(type, groupName, bPasteAtSameLevel, dataList); - CClipboard clipboard(nullptr); - clipboard.Put(rootNode); - } - - XmlNodeRef CreateXMLFromClipboardData(const QString& type, const QString& groupName, bool bPasteAtSameLevel, std::vector& dataList) - { - XmlNodeRef rootNode = gEnv->pSystem->CreateXmlNode(); - rootNode->setTag("FlareDB"); - rootNode->setAttr("Type", type.toUtf8().data()); - rootNode->setAttr("GroupName", groupName.toUtf8().data()); - rootNode->setAttr("PasteAtSameLevel", bPasteAtSameLevel); - - for (int i = 0, iDataSize(dataList.size()); i < iDataSize; ++i) - { - XmlNodeRef xmlNode = gEnv->pSystem->CreateXmlNode(); - xmlNode->setTag("Data"); - dataList[i].FillXmlNode(xmlNode); - rootNode->addChild(xmlNode); - } - - return rootNode; - } - - void UpdateOpticsName(IOpticsElementBasePtr pOptics) - { - if (pOptics == NULL) - { - return; - } - - IOpticsElementBasePtr pParent = pOptics->GetParent(); - if (pParent) - { - QString oldName = pOptics->GetName().c_str(); - QString parentName = pParent->GetName().c_str(); - QString updatedName = parentName + QString(".") + GetShortName(oldName); - pOptics->SetName(updatedName.toUtf8().data()); - } - - for (int i = 0, iElementCount(pOptics->GetElementCount()); i < iElementCount; ++i) - { - UpdateOpticsName(pOptics->GetElementAt(i)); - } - } - - QString ReplaceLastName(const QString& fullName, const QString& shortName) - { - int nPos = fullName.lastIndexOf('.'); - if (nPos == -1) - { - return shortName; - } - QString newName = fullName.left(nPos + 1); - newName += shortName; - return newName; - } - - IFuncVariable* GetFuncVariable(IOpticsElementBasePtr pOptics, int nFuncKey) - { - if (pOptics == NULL) - { - return NULL; - } - - int nGroupIndex = (nFuncKey & 0xFFFF0000) >> 16; - int nVarIndex = (nFuncKey & 0x0000FFFF); - - AZStd::vector paramGroups = pOptics->GetEditorParamGroups(); - - if (nGroupIndex >= paramGroups.size()) - { - return NULL; - } - - FuncVariableGroup* pGroup = ¶mGroups[nGroupIndex]; - if (pGroup == NULL) - { - return NULL; - } - - if (nVarIndex >= pGroup->GetVariableCount()) - { - return NULL; - } - - return pGroup->GetVariable(nVarIndex); - } - - void GetLightEntityObjects(std::vector& outEntityLights) - { - std::vector pEntityObjects; - GetIEditor()->GetObjectManager()->FindObjectsOfType(&CEntityObject::staticMetaObject, pEntityObjects); - for (int i = 0, iObjectSize(pEntityObjects.size()); i < iObjectSize; ++i) - { - CEntityObject* pEntity = (CEntityObject*)pEntityObjects[i]; - if (pEntity == NULL) - { - continue; - } - if (pEntity->CheckFlags(OBJFLAG_DELETED)) - { - continue; - } - if (!pEntity->IsLight()) - { - continue; - } - outEntityLights.push_back(pEntity); - } - } - - void OutputOpticsDebug(IOpticsElementBasePtr pOptics) - { - QString opticsName; - opticsName = QStringLiteral("Optics Name : %1\n").arg(pOptics->GetName().c_str()); - OutputDebugString(opticsName.toUtf8().data()); - - AZStd::vector groupArray(pOptics->GetEditorParamGroups()); - for (int i = 0, iGroupCount(groupArray.size()); i < iGroupCount; ++i) - { - FuncVariableGroup* pGroup = &groupArray[i]; - - QString groupStr; - groupStr = QStringLiteral("\tGroup : %1\n").arg(pGroup->GetName()); - OutputDebugString(groupStr.toUtf8().data()); - - for (int k = 0, iParamCount(pGroup->GetVariableCount()); k < iParamCount; ++k) - { - IFuncVariable* pVar = pGroup->GetVariable(k); - if (pVar == NULL) - { - continue; - } - QString str; - if (pVar->paramType == e_FLOAT) - { - str = QStringLiteral("\t\t%1 : %2\n").arg(pVar->name.c_str()).arg(pVar->GetFloat()); - } - else if (pVar->paramType == e_INT) - { - str = QStringLiteral("\t\t%1 : %2\n").arg(pVar->name.c_str()).arg(pVar->GetInt()); - } - else if (pVar->paramType == e_BOOL) - { - str = QStringLiteral("\t\t%1 : %2\n").arg(pVar->name.c_str(), pVar->GetBool() ? "TRUE" : "FALSE"); - } - else if (pVar->paramType == e_VEC2) - { - str = QStringLiteral("\t\t%1 : %2,%3\n").arg(pVar->name.c_str()).arg(pVar->GetVec2().x).arg(pVar->GetVec2().y); - } - else if (pVar->paramType == e_VEC3) - { - str = QStringLiteral("\t\t%1 : %2,%3,%4\n").arg(pVar->name.c_str()).arg(pVar->GetVec3().x).arg(pVar->GetVec3().y).arg(pVar->GetVec3().z); - } - else if (pVar->paramType == e_VEC4) - { - str = QStringLiteral("\t\t%1 : %2,%3,%4,%5\n").arg(pVar->name.c_str()).arg(pVar->GetVec4().x).arg(pVar->GetVec4().y).arg(pVar->GetVec4().z); - } - else if (pVar->paramType == e_COLOR) - { - str = QStringLiteral("\t\t%1 : %2,%3,%4,%5\n").arg(pVar->name.c_str()).arg(pVar->GetColorF().r).arg(pVar->GetColorF().g).arg(pVar->GetColorF().b).arg(pVar->GetColorF().a); - } - else if (pVar->paramType == e_TEXTURE2D || pVar->paramType == e_TEXTURE3D || pVar->paramType == e_TEXTURE_CUBE) - { - if (pVar->GetTexture()) - { - str = QStringLiteral("\t\t%1 : %2\n").arg(pVar->name.c_str(), pVar->GetTexture()->GetName()); - } - else - { - str = QStringLiteral("\t\t%1 : NULL\n").arg(pVar->name.c_str()); - } - } - OutputDebugString(str.toUtf8().data()); - } - } - - for (int i = 0, iChildCount(pOptics->GetElementCount()); i < iChildCount; ++i) - { - OutputOpticsDebug(pOptics->GetElementAt(i)); - } - } - - void FillParams(XmlNodeRef& paramNode, IOpticsElementBase* pOptics) - { - if (pOptics == NULL) - { - return; - } - AZStd::vector groupArray(pOptics->GetEditorParamGroups()); - for (int i = 0, iGroupCount(paramNode->getChildCount()); i < iGroupCount; ++i) - { - XmlNodeRef groupNode = paramNode->getChild(i); - if (groupNode == NULL) - { - continue; - } - - int nGroupIndex(0); - if (!FindGroup(groupNode->getTag(), pOptics, nGroupIndex)) - { - continue; - } - - FuncVariableGroup* pGroup = &groupArray[nGroupIndex]; - for (int k = 0, iParamCount(pGroup->GetVariableCount()); k < iParamCount; ++k) - { - IFuncVariable* pVar = pGroup->GetVariable(k); - if (pVar == NULL) - { - continue; - } - - if (pVar->paramType == e_FLOAT) - { - float fValue(0); - if (groupNode->getAttr(pVar->name.c_str(), fValue)) - { - pVar->InvokeSetter((void*)&fValue); - } - } - else if (pVar->paramType == e_INT) - { - int nValue(0); - if (groupNode->getAttr(pVar->name.c_str(), nValue)) - { - pVar->InvokeSetter((void*)&nValue); - } - } - else if (pVar->paramType == e_BOOL) - { - bool bValue(false); - if (groupNode->getAttr(pVar->name.c_str(), bValue)) - { - pVar->InvokeSetter((void*)&bValue); - } - } - else if (pVar->paramType == e_VEC2) - { - Vec2 vec2Value; - if (groupNode->getAttr(pVar->name.c_str(), vec2Value)) - { - pVar->InvokeSetter((void*)&vec2Value); - } - } - else if (pVar->paramType == e_VEC3) - { - Vec3 vec3Value; - if (groupNode->getAttr(pVar->name.c_str(), vec3Value)) - { - pVar->InvokeSetter((void*)&vec3Value); - } - } - else if (pVar->paramType == e_VEC4) - { - const char* strVec4Value; - if (groupNode->getAttr(pVar->name.c_str(), &strVec4Value)) - { - Vec4 vec4Value; - ExtractVec4FromString(strVec4Value, vec4Value); - pVar->InvokeSetter((void*)&vec4Value); - } - } - else if (pVar->paramType == e_COLOR) - { - Vec3 vec3Value; - if (!groupNode->getAttr(pVar->name.c_str(), vec3Value)) - { - continue; - } - string alphaStr = string(pVar->name.c_str()) + ".alpha"; - int alpha; - if (!groupNode->getAttr(alphaStr.c_str(), alpha)) - { - continue; - } - ColorF color; - color.r = vec3Value.x; - color.g = vec3Value.y; - color.b = vec3Value.z; - color.a = (float)alpha / 255.0f; - pVar->InvokeSetter((void*)&color); - } - else if (pVar->paramType == e_MATRIX33) - { - //reserved - } - else if (pVar->paramType == e_TEXTURE2D || pVar->paramType == e_TEXTURE3D || pVar->paramType == e_TEXTURE_CUBE) - { - const char* textureName; - if (!groupNode->getAttr(pVar->name.c_str(), &textureName)) - { - continue; - } - ITexture* pTexture = NULL; - if (textureName && strlen(textureName) > 0) - { - pTexture = gEnv->pRenderer->EF_LoadTexture(textureName); - } - pVar->InvokeSetter((void*)pTexture); - if (pTexture) - { - pTexture->Release(); - } - } - } - } - } - - void GetExpandedItemNames(CBaseLibraryItem* item, const QString& groupName, const QString& itemName, QString& outNameWithGroup, QString& outFullName) - { - QString name; - if (!groupName.isEmpty()) - { - name = groupName + "."; - } - name += itemName; - QString fullName = name; - if (item->GetLibrary()) - { - fullName = item->GetLibrary()->GetName() + "." + name; - } - outNameWithGroup = name; - outFullName = fullName; - } - - QModelIndex GetTreeItemByHitTest(QTreeView& treeCtrl) - { - return treeCtrl.indexAt(treeCtrl.mapFromGlobal(QCursor::pos())); - } - - int FindOpticsIndexUnderParentOptics(IOpticsElementBasePtr pOptics, IOpticsElementBasePtr pParentOptics) - { - for (int i = 0, iElementSize(pParentOptics->GetElementCount()); i < iElementSize; ++i) - { - if (pParentOptics->GetElementAt(i) == pOptics) - { - return i + 1; - } - } - return -1; - } -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUtil.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareUtil.h deleted file mode 100644 index d9fb3e380c..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUtil.h +++ /dev/null @@ -1,363 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREUTIL_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREUTIL_H -#pragma once - -#include -#include - -#include "Util/Variable.h" - -#include "IFlares.h" -class CEntityObject; - -class QTreeView; - -#define LENSFLARE_ELEMENT_TREE "LensFlareElementTree" -#define LENSFLARE_ITEM_TREE "LensFlareItemTree" -#define FLARECLIPBOARDTYPE_COPY "Copy" -#define FLARECLIPBOARDTYPE_CUT "Cut" - -namespace LensFlareUtil -{ - inline bool IsElement(EFlareType type) - { - return type != eFT__Base__ && type != eFT_Root && type != eFT_Group; - } - inline bool IsGroup(EFlareType type) - { - return type == eFT_Root || type == eFT_Group; - } - inline bool IsValidFlare(EFlareType type) - { - return type >= eFT__Base__ && type < eFT_Max; - } - - inline void AddVariable(CVariableBase& varArray, CVariableBase& var, const char* varName, const char* humanVarName, const char* description, char dataType = IVariable::DT_SIMPLE) - { - if (varName) - { - var.SetName(varName); - } - if (humanVarName) - { - var.SetHumanName(humanVarName); - } - if (description) - { - var.SetDescription(description); - } - var.SetDataType(dataType); - varArray.AddVariable(&var); - } - - inline void AddVariable(CVarBlock* vars, CVariableBase& var, const char* varName, const char* humanVarName, const char* description, unsigned char dataType = IVariable::DT_SIMPLE) - { - if (varName) - { - var.SetName(varName); - } - if (humanVarName) - { - var.SetHumanName(humanVarName); - } - if (description) - { - var.SetDescription(description); - } - var.SetDataType(dataType); - vars->AddVariable(&var); - } - - inline bool GetFlareType(const QString& typeName, EFlareType& outType) - { - FlareInfoArray::Props array = FlareInfoArray::Get(); - for (size_t i = 0; i < array.size; ++i) - { - if (typeName == array.p[i].name) - { - outType = array.p[i].type; - return true; - } - } - return false; - } - - inline bool GetFlareTypeName(QString& outTypeName, IOpticsElementBasePtr pOptics) - { - if (pOptics == NULL) - { - return false; - } - - const FlareInfoArray::Props array = FlareInfoArray::Get(); - for (size_t i = 0; i < array.size; ++i) - { - if (array.p[i].type == pOptics->GetType()) - { - outTypeName = array.p[i].name; - return true; - } - } - - return false; - } - - inline QString GetShortName(const QString& name) - { - int nPos = name.lastIndexOf('.'); - if (nPos == -1) - { - return name; - } - return name.right(name.length() - nPos - 1); - } - - inline QString GetGroupNameFromName(const QString& name) - { - int nPos = name.lastIndexOf('.'); - if (nPos == -1) - { - return name; - } - return name.left(nPos); - } - - inline QString GetGroupNameFromFullName(const QString& fullItemName) - { - int nLastDotPos = fullItemName.lastIndexOf('.'); - if (nLastDotPos == -1) - { - return fullItemName; - } - - QString name = GetGroupNameFromName(fullItemName); - - int nFirstDotPos = name.indexOf('.'); - if (nFirstDotPos == -1) - { - return name; - } - - return name.right(name.length() - nFirstDotPos - 1); - } - - inline bool HaveParameterLowBoundary(const QString& paramName) - { - if (!QString::compare(paramName, "Noiseseed", Qt::CaseInsensitive) || !QString::compare(paramName, "translation", Qt::CaseInsensitive) || !QString::compare(paramName, "position", Qt::CaseInsensitive) || !QString::compare(paramName, "rotation", Qt::CaseInsensitive)) - { - return false; - } - return true; - } - - inline int MakeFuncKey(int nGroupIndex, int nVarIndex) - { - return (nGroupIndex << 16) | nVarIndex; - } - - template - inline void BoundaryProcess(T& fValue) - { - if (fValue < 0) - { - fValue = 0; - } - } - - inline void BoundaryProcess(Vec2& v) - { - if (v.x < 0) - { - v.x = 0; - } - if (v.y < 0) - { - v.y = 0; - } - } - - inline void BoundaryProcess(Vec3& v) - { - if (v.x < 0) - { - v.x = 0; - } - if (v.y < 0) - { - v.y = 0; - } - if (v.z < 0) - { - v.z = 0; - } - } - - inline void BoundaryProcess(Vec4& v) - { - if (v.x < 0) - { - v.x = 0; - } - if (v.y < 0) - { - v.y = 0; - } - if (v.z < 0) - { - v.z = 0; - } - if (v.w < 0) - { - v.w = 0; - } - } - - inline bool ExtractVec4FromString(const string& buffer, Vec4& outVec4) - { - int nCount(0); - string copiedBuffer(buffer); - int commaPos(0); - while (nCount < 4 || commaPos != -1) - { - commaPos = copiedBuffer.find(","); - string strV; - if (commaPos == -1) - { - strV = copiedBuffer; - } - else - { - strV = copiedBuffer.Left(commaPos); - strV += ","; - } - copiedBuffer.replace(0, commaPos + 1, ""); - outVec4[nCount++] = (float)atof(strV.c_str()); - } - return nCount == 4; - } - - void FillParams(XmlNodeRef& paramNode, IOpticsElementBase* pOptics); - - inline bool FindGroup(const char* groupName, IOpticsElementBase* pOptics, int& nOutGroupIndex) - { - if (groupName == NULL) - { - return false; - } - - AZStd::vector groupArray = pOptics->GetEditorParamGroups(); - for (int i = 0, iCount(groupArray.size()); i < iCount; ++i) - { - if (!_stricmp(groupArray[i].GetName(), groupName)) - { - nOutGroupIndex = i; - return true; - } - } - return false; - } - - struct SClipboardData - { - SClipboardData(){} - ~SClipboardData(){} - SClipboardData(const QString& from, const QString& lensFlareFullPath, const QString& lensOpticsPath) - : m_From(from) - , m_LensFlareFullPath(lensFlareFullPath) - , m_LensOpticsPath(lensOpticsPath) - { - } - - void FillXmlNode(XmlNodeRef node) - { - if (node == NULL) - { - return; - } - node->setAttr("From", m_From.toUtf8().data()); - node->setAttr("FlareFullPath", m_LensFlareFullPath.toUtf8().data()); - node->setAttr("OpticsPath", m_LensOpticsPath.toUtf8().data()); - } - - void FillThisFromXmlNode(XmlNodeRef node) - { - if (node == NULL) - { - return; - } - node->getAttr("From", m_From); - node->getAttr("FlareFullPath", m_LensFlareFullPath); - node->getAttr("OpticsPath", m_LensOpticsPath); - } - - QString m_From; - QString m_LensFlareFullPath; - QString m_LensOpticsPath; - }; - - struct SDragAndDropInfo - { - SDragAndDropInfo() - { - m_XMLContents = NULL; - m_bDragging = false; - } - ~SDragAndDropInfo() - { - Reset(); - } - void Reset() - { - m_XMLContents = NULL; - m_bDragging = false; - } - bool m_bDragging; - XmlNodeRef m_XMLContents; - }; - - inline SDragAndDropInfo& GetDragDropInfo() - { - static SDragAndDropInfo dragDropInfo; - return dragDropInfo; - } - - int FindOpticsIndexUnderParentOptics(IOpticsElementBasePtr pOptics, IOpticsElementBasePtr pParentOptics); - bool IsPointInWindow(const QWidget* pWindow, const QPoint& screenPos); - QModelIndex GetTreeItemByHitTest(QTreeView& treeCtrl); - QPoint GetDragCursorPos(QWidget* pWnd, const QPoint& point); - void GetExpandedItemNames(CBaseLibraryItem* item, const QString& groupName, const QString& itemName, QString& outNameWithGroup, QString& outFullName); - void GetSelectedLightEntities(std::vector& outLightEntities); - void GetLightEntityObjects(std::vector& outEntityLights); - IFuncVariable* GetFuncVariable(IOpticsElementBasePtr pOptics, int nFuncKey); - QString ReplaceLastName(const QString& fullName, const QString& shortName); - void UpdateOpticsName(IOpticsElementBasePtr pOptics); - XmlNodeRef CreateXMLFromClipboardData(const QString& type, const QString& groupName, bool bPasteAtSameLevel, std::vector& dataList); - void UpdateClipboard(const QString& type, const QString& groupName, bool bPasteAtSameLevel, std::vector& dataList); - void ChangeOpticsRootName(IOpticsElementBasePtr pOptics, const QString& newRootName); - void RemoveOptics(IOpticsElementBasePtr pOptics); - IOpticsElementBasePtr FindOptics(IOpticsElementBasePtr pStartOptics, const QString& name); - CEntityObject* GetSelectedLightEntity(); - IOpticsElementBasePtr GetSelectedLightOptics(); - IOpticsElementBasePtr CreateOptics(const XmlNodeRef& xmlNode); - IOpticsElementBasePtr CreateOptics(IOpticsElementBasePtr pOptics, bool bForceTypeToGroup = false); - bool FillOpticsFromXML(IOpticsElementBasePtr pOptics, const XmlNodeRef& xmlNode); - bool CreateXmlData(IOpticsElementBasePtr pOptics, XmlNodeRef& pOutNode); - void SetVariablesTemplateFromOptics(IOpticsElementBasePtr pOptics, CVarBlockPtr& pRootVar, std::vector& funcs); - void SetVariablesTemplateFromOptics(IOpticsElementBasePtr pOptics, CVarBlockPtr& pRootVar); - void CopyOptics(IOpticsElementBasePtr pSrcOptics, IOpticsElementBasePtr pDestOptics, bool bReculsiveCopy = true); - void OutputOpticsDebug(IOpticsElementBasePtr pOptics); -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREUTIL_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareView.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareView.cpp deleted file mode 100644 index 05248b32f5..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareView.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareView.h" - -// Editor -#include "LensFlareItem.h" -#include "LensFlareEditor.h" -#include "Objects/EntityObject.h" -#include "Material/MaterialManager.h" - - -CLensFlareView::CLensFlareView(QWidget* parent, Qt::WindowFlags f) - : CPreviewModelCtrl(parent, f) -{ - InitDialog(); -} - -CLensFlareView::~CLensFlareView() -{ - CLensFlareEditor::GetLensFlareEditor()->UnregisterLensFlareItemChangeListener(this); -} - -void CLensFlareView::InitDialog() -{ - CLensFlareEditor::GetLensFlareEditor()->RegisterLensFlareItemChangeListener(this); - - SetClearColor(ColorF(0, 0, 0, 0)); - SetGrid(true); - SetAxis(true); - EnableUpdate(true); - m_pLensFlareMaterial = GetIEditor()->GetMaterialManager()->LoadMaterial(CEntityObject::s_LensFlareMaterialName); - m_InitCameraPos = m_camera.GetPosition(); -} - -void CLensFlareView::RenderObject(_smart_ptr pMaterial, [[maybe_unused]] SRenderingPassInfo& passInfo) -{ - if (m_pLensFlareItem) - { - IOpticsElementBasePtr pOptics = m_pLensFlareItem->GetOptics(); - if (pOptics && m_pLensFlareMaterial) - { - _smart_ptr pMaterial = m_pLensFlareMaterial->GetMatInfo(); - if (pMaterial) - { - m_pRenderer->ForceUpdateGlobalShaderParameters(); - m_pRenderer->SetViewport(1, 1, m_pRenderer->GetWidth(), m_pRenderer->GetHeight()); - SShaderItem& shaderItem = pMaterial->GetShaderItem(); - SLensFlareRenderParam param; - param.pCamera = &m_camera; - param.pShader = shaderItem.m_pShader; - pOptics->Render(¶m, Vec3(0, 0, 0)); - } - } - } -} - -void CLensFlareView::OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem) -{ - if (m_pLensFlareItem != pLensFlareItem) - { - m_pLensFlareItem = pLensFlareItem; - Update(true); - m_bHaveAnythingToRender = m_pLensFlareItem != NULL; - } -} - -void CLensFlareView::OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem) -{ - if (m_pLensFlareItem == pLensFlareItem) - { - m_pLensFlareItem = NULL; - Update(); - m_bHaveAnythingToRender = false; - } -} - -void CLensFlareView::OnInternalVariableChange([[maybe_unused]] IVariable* pVar) -{ - Update(); -} - -void CLensFlareView::OnLensFlareChangeElement([[maybe_unused]] CLensFlareElement* pLensFlareElement) -{ - Update(); -} - -void CLensFlareView::OnEditorNotifyEvent(EEditorNotifyEvent event) -{ - switch (event) - { - case eNotify_OnCloseScene: - ReleaseObject(); - break; - } -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareView.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareView.h deleted file mode 100644 index f514211046..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareView.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREVIEW_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREVIEW_H -#pragma once - -#include "ILensFlareListener.h" -#include "Controls/PreviewModelCtrl.h" - -class CLensFlareView - : public CPreviewModelCtrl - , public ILensFlareChangeItemListener - , public ILensFlareChangeElementListener -{ -public: - explicit CLensFlareView(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); - ~CLensFlareView(); - - void OnInternalVariableChange(IVariable* pVar); - void OnEditorNotifyEvent(EEditorNotifyEvent event); - -protected: - - void InitDialog(); - void ProcessKeys(){} - void RenderObject(_smart_ptr pMaterial, SRenderingPassInfo& passInfo); - - void OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem); - void OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem); - void OnLensFlareChangeElement(CLensFlareElement* pLensFlareElement); - -private: - - QPoint m_prevPoint; - Vec3 m_InitCameraPos; - - _smart_ptr m_pLensFlareMaterial; - _smart_ptr m_pLensFlareItem; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREVIEW_H diff --git a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h index 27ac7e8a46..45810da2cf 100644 --- a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h @@ -96,7 +96,6 @@ public: MOCK_METHOD0(GetIEditorMaterialManager, IEditorMaterialManager* ()); MOCK_METHOD0(GetIconManager, IIconManager* ()); MOCK_METHOD0(GetMusicManager, CMusicManager* ()); - MOCK_METHOD0(GetLensFlareManager, CLensFlareManager* ()); MOCK_METHOD2(GetTerrainElevation, float(float , float )); MOCK_METHOD0(GetVegetationMap, class CVegetationMap* ()); MOCK_METHOD0(GetEditorQtApplication, Editor::EditorQtApplication* ()); diff --git a/Code/Sandbox/Editor/LyViewPaneNames.h b/Code/Sandbox/Editor/LyViewPaneNames.h index 3ea793b9c7..fdbf8bf90c 100644 --- a/Code/Sandbox/Editor/LyViewPaneNames.h +++ b/Code/Sandbox/Editor/LyViewPaneNames.h @@ -44,7 +44,6 @@ namespace LyViewPane static const char* const TerrainTool = "Terrain Tool"; static const char* const TerrainTextureLayers = "Terrain Texture Layers"; static const char* const ParticleEditor = "Particle Editor"; - static const char* const LensFlareEditor = "Lens Flare Editor"; static const char* const TimeOfDayEditor = "Time Of Day"; static const char* const AudioControlsEditor = "Audio Controls Editor"; static const char* const SubstanceEditor = "Substance Editor"; diff --git a/Code/Sandbox/Editor/MainWindow.cpp b/Code/Sandbox/Editor/MainWindow.cpp index 0ac7da33a7..96f4da7312 100644 --- a/Code/Sandbox/Editor/MainWindow.cpp +++ b/Code/Sandbox/Editor/MainWindow.cpp @@ -91,7 +91,6 @@ AZ_POP_DISABLE_WARNING #include "TrackView/TrackViewDialog.h" #include "ErrorReportDialog.h" -#include "LensFlareEditor/LensFlareEditor.h" #include "TimeOfDayDialog.h" #include "Dialogs/PythonScriptsDialog.h" @@ -1657,7 +1656,6 @@ void MainWindow::RegisterStdViewClasses() if (!AZ::Interface::Get()) { - CLensFlareEditor::RegisterViewClass(); CTimeOfDayDialog::RegisterViewClass(); } #ifdef ThumbnailDemo diff --git a/Code/Sandbox/Editor/Objects/EntityObject.cpp b/Code/Sandbox/Editor/Objects/EntityObject.cpp index 8beda36013..82d45f8ae5 100644 --- a/Code/Sandbox/Editor/Objects/EntityObject.cpp +++ b/Code/Sandbox/Editor/Objects/EntityObject.cpp @@ -29,18 +29,11 @@ #include "Include/IObjectManager.h" #include "Objects/ObjectManager.h" #include "ViewManager.h" -#include "LensFlareEditor/LensFlareManager.h" -#include "LensFlareEditor/LensFlareUtil.h" -#include "LensFlareEditor/LensFlareLibrary.h" #include "AnimationContext.h" #include "HitContext.h" #include "Objects/SelectionGroup.h" -const char* CEntityObject::s_LensFlarePropertyName("flare_Flare"); -const char* CEntityObject::s_LensFlareMaterialName("EngineAssets/Materials/lens_optics"); - - ////////////////////////////////////////////////////////////////////////// //! Undo Entity Link class CUndoEntityLink @@ -1976,60 +1969,6 @@ IOpticsElementBasePtr CEntityObject::GetOpticsElement() return pLight->GetLensOpticsElement(); } -////////////////////////////////////////////////////////////////////////// -void CEntityObject::SetOpticsElement(IOpticsElementBase* pOptics) -{ - CDLight* pLight = GetLightProperty(); - if (pLight == NULL) - { - return; - } - pLight->SetLensOpticsElement(pOptics); - if (GetEntityPropertyBool("bFlareEnable") && pOptics) - { - CBaseObject::SetMaterial(s_LensFlareMaterialName); - } - else - { - SetMaterial(NULL); - } -} - -////////////////////////////////////////////////////////////////////////// -void CEntityObject::ApplyOptics(const QString& opticsFullName, IOpticsElementBasePtr pOptics) -{ - if (pOptics == NULL) - { - CDLight* pLight = GetLightProperty(); - if (pLight) - { - pLight->SetLensOpticsElement(NULL); - } - SetFlareName(""); - SetMaterial(NULL); - } - else - { - int nOpticsIndex(0); - if (!gEnv->pOpticsManager->Load(opticsFullName.toUtf8().data(), nOpticsIndex)) - { - IOpticsElementBasePtr pNewOptics = gEnv->pOpticsManager->Create(eFT_Root); - if (!gEnv->pOpticsManager->AddOptics(pNewOptics, opticsFullName.toUtf8().data(), nOpticsIndex)) - { - CDLight* pLight = GetLightProperty(); - if (pLight) - { - pLight->SetLensOpticsElement(NULL); - SetMaterial(NULL); - } - return; - } - LensFlareUtil::CopyOptics(pOptics, pNewOptics); - } - SetFlareName(opticsFullName); - } -} - ////////////////////////////////////////////////////////////////////////// void CEntityObject::SetOpticsName(const QString& opticsFullName) { @@ -2040,19 +1979,8 @@ void CEntityObject::SetOpticsName(const QString& opticsFullName) { pLight->SetLensOpticsElement(NULL); } - SetFlareName(""); SetMaterial(NULL); } - else - { - if (GetOpticsElement()) - { - if (gEnv->pOpticsManager->Rename(GetOpticsElement()->GetName(), opticsFullName.toUtf8().data())) - { - SetFlareName(opticsFullName); - } - } - } } ////////////////////////////////////////////////////////////////////////// @@ -2080,27 +2008,6 @@ CDLight* CEntityObject::GetLightProperty() const return NULL; } -////////////////////////////////////////////////////////////////////////// -bool CEntityObject::GetValidFlareName(QString& outFlareName) const -{ - IVariable* pFlareVar(m_pProperties->FindVariable(s_LensFlarePropertyName)); - if (!pFlareVar) - { - return false; - } - - QString flareName; - pFlareVar->Get(flareName); - if (flareName.isEmpty() || flareName == "@root") - { - return false; - } - - outFlareName = flareName; - - return true; -} - ////////////////////////////////////////////////////////////////////////// void CEntityObject::PreInitLightProperty() { @@ -2108,42 +2015,6 @@ void CEntityObject::PreInitLightProperty() { return; } - - QString flareFullName; - if (GetValidFlareName(flareFullName)) - { - bool bEnableOptics = GetEntityPropertyBool("bFlareEnable"); - if (bEnableOptics) - { - CLensFlareManager* pLensManager = GetIEditor()->GetLensFlareManager(); - CLensFlareLibrary* pLevelLib = (CLensFlareLibrary*)pLensManager->GetLevelLibrary(); - IOpticsElementBasePtr pLevelOptics = pLevelLib->GetOpticsOfItem(flareFullName.toUtf8().data()); - if (pLevelLib && pLevelOptics) - { - int nOpticsIndex(0); - IOpticsElementBasePtr pNewOptics = GetOpticsElement(); - if (pNewOptics == NULL) - { - pNewOptics = gEnv->pOpticsManager->Create(eFT_Root); - } - - if (gEnv->pOpticsManager->AddOptics(pNewOptics, flareFullName.toUtf8().data(), nOpticsIndex)) - { - LensFlareUtil::CopyOptics(pLevelOptics, pNewOptics); - SetOpticsElement(pNewOptics); - } - else - { - CDLight* pLight = GetLightProperty(); - if (pLight) - { - pLight->SetLensOpticsElement(NULL); - SetMaterial(NULL); - } - } - } - } - } } ////////////////////////////////////////////////////////////////////////// @@ -2153,26 +2024,6 @@ void CEntityObject::UpdateLightProperty() { return; } - - QString flareName; - if (GetValidFlareName(flareName)) - { - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - pOptics = gEnv->pOpticsManager->Create(eFT_Root); - } - bool bEnableOptics = GetEntityPropertyBool("bFlareEnable"); - if (bEnableOptics && GetIEditor()->GetLensFlareManager()->LoadFlareItemByName(flareName, pOptics)) - { - pOptics->SetName(flareName.toUtf8().data()); - SetOpticsElement(pOptics); - } - else - { - SetOpticsElement(NULL); - } - } } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/Objects/EntityObject.h b/Code/Sandbox/Editor/Objects/EntityObject.h index 9964cbd72f..941094c755 100644 --- a/Code/Sandbox/Editor/Objects/EntityObject.h +++ b/Code/Sandbox/Editor/Objects/EntityObject.h @@ -221,10 +221,7 @@ public: IVariable* GetLightVariable(const char* name) const; IOpticsElementBasePtr GetOpticsElement(); - void SetOpticsElement(IOpticsElementBase* pOptics); - void ApplyOptics(const QString& opticsFullName, IOpticsElementBasePtr pOptics); void SetOpticsName(const QString& opticsFullName); - bool GetValidFlareName(QString& outFlareName) const; void PreInitLightProperty(); void UpdateLightProperty(); @@ -236,9 +233,6 @@ public: static void StoreUndoEntityLink(CSelectionGroup* pGroup); - static const char* s_LensFlarePropertyName; - static const char* s_LensFlareMaterialName; - void RegisterListener(IEntityObjectListener* pListener); void UnregisterListener(IEntityObjectListener* pListener); @@ -322,11 +316,6 @@ protected: void AdjustLightProperties(CVarBlockPtr& properties, const char* pSubBlock); IVariable* FindVariableInSubBlock(CVarBlockPtr& properties, IVariable* pSubBlockVar, const char* pVarName); - void SetFlareName(const QString& name) - { - SetEntityPropertyString(s_LensFlarePropertyName, name); - } - unsigned int m_bLoadFailed : 1; unsigned int m_bCalcPhysics : 1; unsigned int m_bDisplayBBox : 1; diff --git a/Code/Sandbox/Editor/Platform/Mac/editor_mac.cmake b/Code/Sandbox/Editor/Platform/Mac/editor_mac.cmake index 484974745d..62523369e7 100644 --- a/Code/Sandbox/Editor/Platform/Mac/editor_mac.cmake +++ b/Code/Sandbox/Editor/Platform/Mac/editor_mac.cmake @@ -9,13 +9,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_bundle_resources( - TARGET Editor - FILES - ${CMAKE_SOURCE_DIR}/Code/Tools/RC/Config/rc/xmlfilter.txt - ${CMAKE_SOURCE_DIR}/Code/Tools/RC/Config/rc/rc.ini -) - # Set resources directory for app icons target_sources(Editor PRIVATE ${CMAKE_CURRENT_LIST_DIR}/Images.xcassets) set_target_properties(Editor PROPERTIES diff --git a/Code/Sandbox/Editor/Style/resources.qrc b/Code/Sandbox/Editor/Style/resources.qrc index aa32f29555..aec7e2cf68 100644 --- a/Code/Sandbox/Editor/Style/resources.qrc +++ b/Code/Sandbox/Editor/Style/resources.qrc @@ -4,6 +4,5 @@ EditorPreferencesDialog.qss LayoutConfigDialog.qss GraphicsSettingsDialog.qss - LensFlareEditor.qss diff --git a/Code/Sandbox/Editor/Util/Variable.h b/Code/Sandbox/Editor/Util/Variable.h index ab43d24e94..20c18d4409 100644 --- a/Code/Sandbox/Editor/Util/Variable.h +++ b/Code/Sandbox/Editor/Util/Variable.h @@ -163,7 +163,7 @@ struct IVariable DT_LIGHT_ANIMATION, // Light Animation Node in the global Light Animation Set DT_PARTICLE_EFFECT, DT_GEOM_CACHE, // Geometry cache - DT_FLARE, + DT_DEPRECATED, // formerly DT_FLARE DT_AUDIO_TRIGGER, DT_AUDIO_SWITCH, DT_AUDIO_SWITCH_STATE, diff --git a/Code/Sandbox/Editor/Util/VariablePropertyType.cpp b/Code/Sandbox/Editor/Util/VariablePropertyType.cpp index 5a3029807b..c80461182d 100644 --- a/Code/Sandbox/Editor/Util/VariablePropertyType.cpp +++ b/Code/Sandbox/Editor/Util/VariablePropertyType.cpp @@ -58,7 +58,6 @@ namespace Prop { IVariable::DT_USERITEMCB, "User", ePropertyUser, -1 }, { IVariable::DT_SEQUENCE_ID, "SequenceId", ePropertySequenceId, -1 }, { IVariable::DT_LIGHT_ANIMATION, "LightAnimation", ePropertyLightAnimation, -1 }, - { IVariable::DT_FLARE, "Flare", ePropertyFlare, 7 }, { IVariable::DT_PARTICLE_EFFECT, "ParticleEffect", ePropertyParticleName, 3 }, { IVariable::DT_GEOM_CACHE, "Geometry Cache", ePropertyGeomCache, 5 }, { IVariable::DT_AUDIO_TRIGGER, "Audio Trigger", ePropertyAudioTrigger, 6 }, diff --git a/Code/Sandbox/Editor/Util/VariablePropertyType.h b/Code/Sandbox/Editor/Util/VariablePropertyType.h index 86fc8e9c0f..76379c1bc0 100644 --- a/Code/Sandbox/Editor/Util/VariablePropertyType.h +++ b/Code/Sandbox/Editor/Util/VariablePropertyType.h @@ -50,7 +50,7 @@ enum PropertyType ePropertyUser, ePropertySequenceId, ePropertyLightAnimation, - ePropertyFlare, + ePropertyDeprecated1, // formerly ePropertyFlare ePropertyParticleName, ePropertyGeomCache, ePropertyAudioTrigger, diff --git a/Code/Sandbox/Editor/editor_files.cmake b/Code/Sandbox/Editor/editor_files.cmake index 50521d23aa..9acfb2aaf8 100644 --- a/Code/Sandbox/Editor/editor_files.cmake +++ b/Code/Sandbox/Editor/editor_files.cmake @@ -13,6 +13,5 @@ set(FILES main.cpp Style/Editor.qss Style/resources.qrc - Style/LensFlareEditor.qss EditorCryEdit.rc ) diff --git a/Code/Sandbox/Editor/editor_lib_files.cmake b/Code/Sandbox/Editor/editor_lib_files.cmake index 80ec582d19..e6337796d6 100644 --- a/Code/Sandbox/Editor/editor_lib_files.cmake +++ b/Code/Sandbox/Editor/editor_lib_files.cmake @@ -545,9 +545,6 @@ set(FILES Geometry/TriMesh.h AboutDialog.h AboutDialog.ui - DatabaseFrameWnd.h - DatabaseFrameWnd.ui - DatabaseFrameWnd.qrc DocMultiArchive.h EditMode/DeepSelection.h FBXExporterDialog.h @@ -571,31 +568,6 @@ set(FILES WipFeaturesDlg.qrc LevelIndependentFileMan.cpp LevelIndependentFileMan.h - LensFlareEditor/ILensFlareListener.h - LensFlareEditor/LensFlareAtomicList.cpp - LensFlareEditor/LensFlareAtomicList.h - LensFlareEditor/LensFlareEditor.cpp - LensFlareEditor/LensFlareEditor.h - LensFlareEditor/LensFlareElement.cpp - LensFlareEditor/LensFlareElement.h - LensFlareEditor/LensFlareElementTree.cpp - LensFlareEditor/LensFlareElementTree.h - LensFlareEditor/LensFlareItem.cpp - LensFlareEditor/LensFlareItem.h - LensFlareEditor/LensFlareItemTree.cpp - LensFlareEditor/LensFlareItemTree.h - LensFlareEditor/LensFlareLibrary.cpp - LensFlareEditor/LensFlareLibrary.h - LensFlareEditor/LensFlareLightEntityTree.cpp - LensFlareEditor/LensFlareLightEntityTree.h - LensFlareEditor/LensFlareManager.cpp - LensFlareEditor/LensFlareManager.h - LensFlareEditor/LensFlareUndo.cpp - LensFlareEditor/LensFlareUndo.h - LensFlareEditor/LensFlareUtil.cpp - LensFlareEditor/LensFlareUtil.h - LensFlareEditor/LensFlareView.cpp - LensFlareEditor/LensFlareView.h LogFileImpl.cpp LogFileImpl.h MatEditPreviewDlg.cpp @@ -706,7 +678,6 @@ set(FILES GraphicsSettingsDialog.cpp graphicssettingsdialog.ui AboutDialog.cpp - DatabaseFrameWnd.cpp ErrorReportTableModel.h ErrorReportTableModel.cpp EditMode/DeepSelection.cpp diff --git a/Code/Tools/AssetBundler/CMakeLists.txt b/Code/Tools/AssetBundler/CMakeLists.txt index 41b95fd2ae..c99ffaef6b 100644 --- a/Code/Tools/AssetBundler/CMakeLists.txt +++ b/Code/Tools/AssetBundler/CMakeLists.txt @@ -13,9 +13,13 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() +include(${CMAKE_CURRENT_SOURCE_DIR}/Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) + +# AssetBundlerBatch - CLI Application ly_add_target( - NAME AssetBundler.Static STATIC + NAME AssetBundlerBatch.Static STATIC NAMESPACE AZ + AUTOMOC FILES_CMAKE assetbundlerbatch_files.cmake INCLUDE_DIRECTORIES @@ -23,6 +27,9 @@ ly_add_target( . BUILD_DEPENDENCIES PUBLIC + 3rdParty::Qt::Core + 3rdParty::Qt::Gui + 3rdParty::Qt::Widgets AZ::AzToolsFramework ${additional_dependencies} ) @@ -32,12 +39,41 @@ ly_add_target( NAMESPACE AZ FILES_CMAKE assetbundlerbatch_exe_files.cmake + COMPILE_DEFINITIONS + PRIVATE + AB_BATCH_MODE INCLUDE_DIRECTORIES PRIVATE . BUILD_DEPENDENCIES PRIVATE - AZ::AssetBundler.Static + AZ::AssetBundlerBatch.Static +) + +# AssetBundler - Qt GUI Application +ly_add_target( + NAME AssetBundler ${PAL_TRAIT_BUILD_ASSETBUNDLER_APPLICATION_TYPE} + NAMESPACE AZ + AUTOMOC + AUTOUIC + AUTORCC + FILES_CMAKE + assetbundlergui_files.cmake + assetbundler_exe_files.cmake + Platform/${PAL_PLATFORM_NAME}/assetbundlergui_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + INCLUDE_DIRECTORIES + PUBLIC + Platform/${PAL_PLATFORM_NAME} + PRIVATE + . + BUILD_DEPENDENCIES + PUBLIC + 3rdParty::Qt::Core + 3rdParty::Qt::Gui + 3rdParty::Qt::Widgets + AZ::AzToolsFramework + AZ::AssetBundlerBatch.Static + ${additional_dependencies} ) if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) @@ -53,7 +89,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) BUILD_DEPENDENCIES PRIVATE AZ::AzTest - AZ::AssetBundler.Static + AZ::AssetBundlerBatch.Static AZ::AzFrameworkTestShared ) diff --git a/cmake/3rdParty/Platform/Linux/dyad_linux.cmake b/Code/Tools/AssetBundler/Platform/Linux/PAL_linux.cmake similarity index 86% rename from cmake/3rdParty/Platform/Linux/dyad_linux.cmake rename to Code/Tools/AssetBundler/Platform/Linux/PAL_linux.cmake index ae9e3d99d7..d0d27a99ac 100644 --- a/cmake/3rdParty/Platform/Linux/dyad_linux.cmake +++ b/Code/Tools/AssetBundler/Platform/Linux/PAL_linux.cmake @@ -9,4 +9,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -set(DYAD_LIBS ${BASE_PATH}/lib/linux_$,debug,release>/libdyad.a) \ No newline at end of file +set (PAL_TRAIT_BUILD_ASSETBUNDLER_APPLICATION_TYPE APPLICATION) + diff --git a/cmake/3rdParty/Platform/Windows/dyad_windows.cmake b/Code/Tools/AssetBundler/Platform/Linux/assetbundlergui_linux_files.cmake similarity index 85% rename from cmake/3rdParty/Platform/Windows/dyad_windows.cmake rename to Code/Tools/AssetBundler/Platform/Linux/assetbundlergui_linux_files.cmake index 8f008ba54e..23bbefccdc 100644 --- a/cmake/3rdParty/Platform/Windows/dyad_windows.cmake +++ b/Code/Tools/AssetBundler/Platform/Linux/assetbundlergui_linux_files.cmake @@ -9,4 +9,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -set(DYAD_LIBS ${BASE_PATH}/lib/x64_v140_$,Debug,Release>/libdyad.lib) +set(FILES + source/utils/GUIApplicationManager_Linux.cpp +) \ No newline at end of file diff --git a/Code/Sandbox/Editor/Style/LensFlareEditor.qss b/Code/Tools/AssetBundler/Platform/Linux/source/utils/GUIApplicationManager_Linux.cpp similarity index 67% rename from Code/Sandbox/Editor/Style/LensFlareEditor.qss rename to Code/Tools/AssetBundler/Platform/Linux/source/utils/GUIApplicationManager_Linux.cpp index 58d99c9f92..7af09214cb 100644 --- a/Code/Sandbox/Editor/Style/LensFlareEditor.qss +++ b/Code/Tools/AssetBundler/Platform/Linux/source/utils/GUIApplicationManager_Linux.cpp @@ -10,8 +10,12 @@ * */ -#DatabaseFrameWnd QToolBar -{ - border-bottom: 2px solid #111111; -} +#include +namespace Platform +{ + AzQtComponents::WindowDecorationWrapper::Option GetWindowDecorationWrapperOption() + { + return AzQtComponents::WindowDecorationWrapper::OptionDisabled; + } +} \ No newline at end of file diff --git a/Code/Tools/AssetBundler/Platform/Mac/PAL_mac.cmake b/Code/Tools/AssetBundler/Platform/Mac/PAL_mac.cmake new file mode 100644 index 0000000000..d0d27a99ac --- /dev/null +++ b/Code/Tools/AssetBundler/Platform/Mac/PAL_mac.cmake @@ -0,0 +1,13 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set (PAL_TRAIT_BUILD_ASSETBUNDLER_APPLICATION_TYPE APPLICATION) + diff --git a/Code/Tools/AssetBundler/Platform/Mac/assetbundlergui_mac_files.cmake b/Code/Tools/AssetBundler/Platform/Mac/assetbundlergui_mac_files.cmake new file mode 100644 index 0000000000..a8a116ac79 --- /dev/null +++ b/Code/Tools/AssetBundler/Platform/Mac/assetbundlergui_mac_files.cmake @@ -0,0 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + source/utils/GUIApplicationManager_OSX.cpp +) \ No newline at end of file diff --git a/Code/CryEngine/CryFont/CryFont_precompiled.cpp b/Code/Tools/AssetBundler/Platform/Mac/source/utils/GUIApplicationManager_OSX.cpp similarity index 67% rename from Code/CryEngine/CryFont/CryFont_precompiled.cpp rename to Code/Tools/AssetBundler/Platform/Mac/source/utils/GUIApplicationManager_OSX.cpp index 235fe8e053..7af09214cb 100644 --- a/Code/CryEngine/CryFont/CryFont_precompiled.cpp +++ b/Code/Tools/AssetBundler/Platform/Mac/source/utils/GUIApplicationManager_OSX.cpp @@ -9,6 +9,13 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -// Original file Copyright Crytek GMBH or its affiliates, used under license. -#include "CryFont_precompiled.h" +#include + +namespace Platform +{ + AzQtComponents::WindowDecorationWrapper::Option GetWindowDecorationWrapperOption() + { + return AzQtComponents::WindowDecorationWrapper::OptionDisabled; + } +} \ No newline at end of file diff --git a/Code/Tools/AssetBundler/Platform/Windows/PAL_windows.cmake b/Code/Tools/AssetBundler/Platform/Windows/PAL_windows.cmake new file mode 100644 index 0000000000..d0d27a99ac --- /dev/null +++ b/Code/Tools/AssetBundler/Platform/Windows/PAL_windows.cmake @@ -0,0 +1,13 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set (PAL_TRAIT_BUILD_ASSETBUNDLER_APPLICATION_TYPE APPLICATION) + diff --git a/Code/Tools/AssetBundler/Platform/Windows/assetbundlergui_windows_files.cmake b/Code/Tools/AssetBundler/Platform/Windows/assetbundlergui_windows_files.cmake new file mode 100644 index 0000000000..f9e1ffda8d --- /dev/null +++ b/Code/Tools/AssetBundler/Platform/Windows/assetbundlergui_windows_files.cmake @@ -0,0 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + source/utils/GUIApplicationManager_Win.cpp +) \ No newline at end of file diff --git a/Code/CryEngine/CryFont/NullFont.cpp b/Code/Tools/AssetBundler/Platform/Windows/source/utils/GUIApplicationManager_Win.cpp similarity index 65% rename from Code/CryEngine/CryFont/NullFont.cpp rename to Code/Tools/AssetBundler/Platform/Windows/source/utils/GUIApplicationManager_Win.cpp index bddca1bbed..99e254a774 100644 --- a/Code/CryEngine/CryFont/NullFont.cpp +++ b/Code/Tools/AssetBundler/Platform/Windows/source/utils/GUIApplicationManager_Win.cpp @@ -9,16 +9,13 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -// Original file Copyright Crytek GMBH or its affiliates, used under license. -// Description : Dummy font implementation (dedicated server) +#include -#include "CryFont_precompiled.h" - -#if defined(USE_NULLFONT) - -#include "NullFont.h" - -CNullFont CCryNullFont::ms_nullFont; - -#endif // USE_NULLFONT +namespace Platform +{ + AzQtComponents::WindowDecorationWrapper::Option GetWindowDecorationWrapperOption() + { + return AzQtComponents::WindowDecorationWrapper::OptionAutoAttach; + } +} \ No newline at end of file diff --git a/cmake/3rdParty/Finddyad.cmake b/Code/Tools/AssetBundler/assetbundler_exe_files.cmake similarity index 84% rename from cmake/3rdParty/Finddyad.cmake rename to Code/Tools/AssetBundler/assetbundler_exe_files.cmake index 179ce45bce..976405c4f7 100644 --- a/cmake/3rdParty/Finddyad.cmake +++ b/Code/Tools/AssetBundler/assetbundler_exe_files.cmake @@ -9,8 +9,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_external_target( - NAME dyad - VERSION 0.2.0-17-amazon - INCLUDE_DIRECTORIES src +set(FILES + source/main.cpp + source/AssetBundler.rc ) diff --git a/Code/Tools/AssetBundler/assetbundlergui_files.cmake b/Code/Tools/AssetBundler/assetbundlergui_files.cmake new file mode 100644 index 0000000000..7ac5d34eb3 --- /dev/null +++ b/Code/Tools/AssetBundler/assetbundlergui_files.cmake @@ -0,0 +1,70 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + source/models/AssetBundlerAbstractFileTableModel.h + source/models/AssetBundlerAbstractFileTableModel.cpp + source/models/AssetBundlerFileTableFilterModel.h + source/models/AssetBundlerFileTableFilterModel.cpp + source/models/AssetListFileTableModel.h + source/models/AssetListFileTableModel.cpp + source/models/AssetListTableModel.cpp + source/models/AssetListTableModel.h + source/models/BundleFileListModel.h + source/models/BundleFileListModel.cpp + source/models/RulesFileTableModel.h + source/models/RulesFileTableModel.cpp + source/models/SeedListFileTableModel.h + source/models/SeedListFileTableModel.cpp + source/models/SeedListTableModel.h + source/models/SeedListTableModel.cpp + source/ui/style/AssetBundler.qrc + source/ui/style/AssetBundler.qss + source/ui/style/AssetBundlerConfig.ini + source/ui/style/AssetBundler-Icon-256x256@x2.ico + source/ui/AddSeedDialog.h + source/ui/AddSeedDialog.cpp + source/ui/AddSeedDialog.ui + source/ui/AssetBundlerTabWidget.h + source/ui/AssetBundlerTabWidget.cpp + source/ui/AssetListTabWidget.h + source/ui/AssetListTabWidget.cpp + source/ui/AssetListTabWidget.ui + source/ui/BundleListTabWidget.h + source/ui/BundleListTabWidget.cpp + source/ui/BundleListTabWidget.ui + source/ui/ComparisonDataWidget.h + source/ui/ComparisonDataWidget.cpp + source/ui/ComparisonDataWidget.ui + source/ui/EditSeedDialog.h + source/ui/EditSeedDialog.cpp + source/ui/EditSeedDialog.ui + source/ui/GenerateBundlesModal.h + source/ui/GenerateBundlesModal.cpp + source/ui/GenerateBundlesModal.ui + source/ui/MainWindow.h + source/ui/MainWindow.cpp + source/ui/MainWindow.ui + source/ui/NewFileDialog.h + source/ui/NewFileDialog.cpp + source/ui/NewFileDialog.ui + source/ui/PlatformSelectionWidget.h + source/ui/PlatformSelectionWidget.cpp + source/ui/PlatformSelectionWidget.ui + source/ui/RulesTabWidget.h + source/ui/RulesTabWidget.cpp + source/ui/RulesTabWidget.ui + source/ui/SeedTabWidget.h + source/ui/SeedTabWidget.cpp + source/ui/SeedTabWidget.ui + source/utils/GUIApplicationManager.h + source/utils/GUIApplicationManager.cpp +) diff --git a/Code/Tools/AssetBundler/source/AssetBundler.rc b/Code/Tools/AssetBundler/source/AssetBundler.rc new file mode 100644 index 0000000000..a3116a384f --- /dev/null +++ b/Code/Tools/AssetBundler/source/AssetBundler.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "ui\\style\\AssetBundler-Icon-256x256@x2.ico" diff --git a/Code/Tools/AssetBundler/source/main.cpp b/Code/Tools/AssetBundler/source/main.cpp index f1b782ff44..be152d6bf3 100644 --- a/Code/Tools/AssetBundler/source/main.cpp +++ b/Code/Tools/AssetBundler/source/main.cpp @@ -10,17 +10,48 @@ * */ +#if defined(AB_BATCH_MODE) #include +#else +#include +#include +#endif + +#if defined(AZ_TESTS_ENABLED) +#include +DECLARE_AZ_UNIT_TEST_MAIN(); +#endif int main(int argc, char* argv[]) { +#if defined(AZ_TESTS_ENABLED) + INVOKE_AZ_UNIT_TEST_MAIN(); +#endif + AZ::AllocatorInstance::Create(); int runSuccess = 0; + { - AssetBundler::ApplicationManager applicationManger(&argc, &argv); - applicationManger.Init(); - runSuccess = applicationManger.Run() ? 0 : 1; + //This nested scope is necessary as the applicationManager needs to have its destructor called BEFORE you destroy the allocators + +#if defined(AB_BATCH_MODE) + AssetBundler::ApplicationManager applicationManager(&argc, &argv); +#else + // Must be called before using any Qt, or the app won't be able to locate Qt libs + AzQtComponents::PrepareQtPaths(); + AssetBundler::GUIApplicationManager applicationManager(&argc, &argv); +#endif + if (!applicationManager.Init()) + { + AZ_Error("AssetBundler", false, "AssetBundler initialization failed"); + runSuccess = 1; + } + else + { + runSuccess = applicationManager.Run() ? 0 : 1; + } } + AZ::AllocatorInstance::Destroy(); return runSuccess; } diff --git a/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.cpp b/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.cpp new file mode 100644 index 0000000000..c2aac4e943 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.cpp @@ -0,0 +1,233 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include + +#include + +namespace AssetBundler +{ + const char* DateTimeFormat = "hh:mm:ss MMM dd, yyyy"; + + AssetBundlerAbstractFileTableModel::AssetBundlerAbstractFileTableModel(QObject* parent) + : QAbstractTableModel(parent) + { + } + + void AssetBundlerAbstractFileTableModel::Reload(const char* fileExtension, const QSet& watchedFolders, const QSet& watchedFiles, const AZStd::unordered_map& pathToProjectNameMap) + { + AZStd::vector keysToRemove = m_fileListKeys; + + // Reload all the files in the watched folders + QString filter = QString("*.%1").arg(fileExtension); + + QSetIterator itr(watchedFolders); + while (itr.hasNext()) + { + QDir filesDir(itr.next()); + filesDir.setNameFilters({ filter }); + for (const QString& fileNameAndExtension : filesDir.entryList(QDir::Files)) + { + AZStd::string absolutePath = filesDir.absoluteFilePath(fileNameAndExtension).toUtf8().data(); + AZStd::string projectName; + if (pathToProjectNameMap.contains(absolutePath)) + { + projectName = pathToProjectNameMap.at(absolutePath); + } + + // If a project name is already specified, then the associated file is a default file + LoadFile(absolutePath, projectName, !projectName.empty()); + keysToRemove.erase(AZStd::remove(keysToRemove.begin(), keysToRemove.end(), AssetBundler::GenerateKeyFromAbsolutePath(absolutePath)), keysToRemove.end()); + } + } + + // Reload all the watched files + for (const QString& filePath : watchedFiles) + { + AZStd::string absolutePath = filePath.toUtf8().data(); + if (AZ::IO::FileIOBase::GetInstance()->Exists(absolutePath.c_str())) + { + AZStd::string projectName = pathToProjectNameMap.at(absolutePath); + + // If a project name is already specified, then the associated file is a default file + LoadFile(absolutePath, projectName, !projectName.empty()); + keysToRemove.erase(AZStd::remove(keysToRemove.begin(), keysToRemove.end(), AssetBundler::GenerateKeyFromAbsolutePath(absolutePath)), keysToRemove.end()); + } + } + + //Remove nonexistant files from the model + for (const AZStd::string& key : keysToRemove) + { + DeleteFileByKey(key); + } + } + + void AssetBundlerAbstractFileTableModel::ReloadFiles(const AZStd::vector& absoluteFilePathList, AZStd::unordered_map pathToProjectNameMap) + { + for (const AZStd::string& absoluteFilePath : absoluteFilePathList) + { + if (!AZ::IO::FileIOBase::GetInstance()->Exists(absoluteFilePath.c_str())) + { + // File is not present on-disk, make sure to remove it from the model + DeleteFileByKey(AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath)); + continue; + } + + // If a project name is already specified, then the associated file is a default file + AZStd::string projectName = pathToProjectNameMap[absoluteFilePath]; + LoadFile(absoluteFilePath, projectName, !projectName.empty()); + } + } + + bool AssetBundlerAbstractFileTableModel::Save(const QModelIndex& selectedIndex) + { + if (!selectedIndex.isValid() || m_keysWithUnsavedChanges.empty()) + { + // There is nothing to save + return true; + } + + AZStd::string key = GetFileKey(selectedIndex); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + // Save the file + if (!WriteToDisk(key)) + { + return false; + } + + // Update the display + m_keysWithUnsavedChanges.erase(key); + QModelIndex topLeftIndex = index(selectedIndex.row(), 0); + QModelIndex bottomRightIndex = index(selectedIndex.row(), columnCount() - 1); + emit dataChanged(topLeftIndex, bottomRightIndex, { Qt::DisplayRole, Qt::FontRole }); + + return true; + } + + bool AssetBundlerAbstractFileTableModel::SaveAll() + { + if (!HasUnsavedChanges()) + { + // No need to update all of the elements if we are not changing anything + return true; + } + + bool hasSaveErrors = false; + + // Save every file with unsaved changes + AZStd::unordered_set keysWithErrors; + for (const AZStd::string& key : m_keysWithUnsavedChanges) + { + if (!WriteToDisk(key)) + { + // Error has already been thrown + hasSaveErrors = true; + keysWithErrors.emplace(key); + } + } + + m_keysWithUnsavedChanges = keysWithErrors; + + // Update the display of all elements + QModelIndex firstIndex = index(0, 0); + QModelIndex lastIndex = index(rowCount() - 1, columnCount() - 1); + emit dataChanged(firstIndex, lastIndex, { Qt::DisplayRole, Qt::FontRole }); + + return !hasSaveErrors; + } + + bool AssetBundlerAbstractFileTableModel::HasUnsavedChanges() const + { + return !m_keysWithUnsavedChanges.empty(); + } + + int AssetBundlerAbstractFileTableModel::rowCount(const QModelIndex& /*parent*/) const + { + return static_cast(m_fileListKeys.size()); + } + + AZStd::string AssetBundlerAbstractFileTableModel::GetFileKey(const QModelIndex& index) const + { + int row = index.row(); + int col = index.column(); + if (row >= rowCount() || row < 0 || col >= columnCount() || col < 0) + { + AZ_Error("AssetBundler", false, "Selected index (%i, %i) is out of range.", row, col); + return {}; + } + + return m_fileListKeys.at(row); + } + + const AZStd::vector& AssetBundlerAbstractFileTableModel::GetAllFileKeys() const + { + return m_fileListKeys; + } + + int AssetBundlerAbstractFileTableModel::GetIndexRowByKey(const AZStd::string& key) const + { + auto it = AZStd::find(m_fileListKeys.begin(), m_fileListKeys.end(), key); + return it == m_fileListKeys.end() ? -1 : static_cast(AZStd::distance(m_fileListKeys.begin(), it)); + } + + void AssetBundlerAbstractFileTableModel::AddFileKey(const AZStd::string& key) + { + if (AZStd::find(m_fileListKeys.begin(), m_fileListKeys.end(), key) != m_fileListKeys.end()) + { + // Key already exists. This could happen when we update existing entires. + return; + } + + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + m_fileListKeys.push_back(key); + endInsertRows(); + } + + bool AssetBundlerAbstractFileTableModel::RemoveFileKey(const QModelIndex& index) + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + int row = index.row(); + beginRemoveRows(QModelIndex(), row, row); + + m_fileListKeys.erase(m_fileListKeys.begin() + row); + m_keysWithUnsavedChanges.erase(key); + + endRemoveRows(); + + return true; + } + + bool AssetBundlerAbstractFileTableModel::DeleteFileByKey(const AZStd::string& key) + { + int indexRow = GetIndexRowByKey(key); + if (indexRow >= 0) + { + return DeleteFile(index(indexRow, 0)); + } + + return false; + } +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.h b/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.h new file mode 100644 index 0000000000..cfe3e3f241 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.h @@ -0,0 +1,111 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +namespace AssetBundler +{ + + extern const char* DateTimeFormat; + + //! Provides an abstract model that can be subclassed to create table models used to store information about files found on-disk. + class AssetBundlerAbstractFileTableModel + : public QAbstractTableModel + { + public: + + enum DataRoles + { + SortRole = Qt::UserRole + 1, + }; + + explicit AssetBundlerAbstractFileTableModel(QObject* parent = nullptr); + virtual ~AssetBundlerAbstractFileTableModel() {} + + ////////////////////////////////////////////////////////////////////////// + // Pure virtual functions + virtual AZStd::vector CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms, const QString& project = QString()) = 0; + virtual bool DeleteFile(const QModelIndex& index) = 0; + virtual void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) = 0; + virtual bool WriteToDisk(const AZStd::string& key) = 0; + + //! Returns the absolute path of the file at the given index on success, returns an empty string on failure. + virtual AZStd::string GetFileAbsolutePath(const QModelIndex& index) const = 0; + + virtual int GetFileNameColumnIndex() const = 0; + virtual int GetTimeStampColumnIndex() const = 0; + ////////////////////////////////////////////////////////////////////////// + + //! Reload all the data based on the watched folders and files + virtual void Reload(const char* fileExtension, const QSet& watchedFolders, const QSet& watchedFiles = QSet(), const AZStd::unordered_map& pathToProjectNameMap = AZStd::unordered_map()); + + virtual void ReloadFiles(const AZStd::vector& absoluteFilePathList, AZStd::unordered_map pathToProjectNameMap = AZStd::unordered_map()); + + bool Save(const QModelIndex& selectedIndex); + + bool SaveAll(); + + bool HasUnsavedChanges() const; + + ////////////////////////////////////////////////////////////////////////// + // QAbstractTableModel overrides + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + ////////////////////////////////////////////////////////////////////////// + + protected: + //! Verifies input index is in range and returns the associated key. + //! Throws an error and returns an empty string if the input index is out of range. + AZStd::string GetFileKey(const QModelIndex& index) const; + + //! Returns an ordered list of every file key in the model. + //! If a proxy model is not used, the order of this list will also be the display order. + const AZStd::vector& GetAllFileKeys() const; + + //! Get the index row if the file info is stored in the model + //! Returns -1 if the file key doesn't exist. + int GetIndexRowByKey(const AZStd::string& key) const; + + //! Adds input key to the end of the list of all keys and notifies the view that a row has been added. + //! When subclassing, instantiate all data associated with this key so the view can update properly. + void AddFileKey(const AZStd::string& key); + + //! Verifies input index, signals to the view that rows will be removed, and removes the key found at the input index. + //! When subclassing, be sure to remove all data associated with the key at this index before calling this function. + //! Returns true if the index is successfully removed, and false on failure + bool RemoveFileKey(const QModelIndex& index); + + //! Delete a file from the disk and remove it from the model by its key + bool DeleteFileByKey(const AZStd::string& key); + + AZStd::unordered_set m_keysWithUnsavedChanges; + + private: + //! When subclassing: store file information in a map, and add the keys to this vector. + //! Provides a 1:1 mapping between a QModelIndex::row value and a key. + AZStd::vector m_fileListKeys; + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/AssetBundlerFileTableFilterModel.cpp b/Code/Tools/AssetBundler/source/models/AssetBundlerFileTableFilterModel.cpp new file mode 100644 index 0000000000..f9a24392a2 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetBundlerFileTableFilterModel.cpp @@ -0,0 +1,62 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include "AssetBundlerFileTableFilterModel.h" + +#include + +#include + +namespace AssetBundler +{ + AssetBundlerFileTableFilterModel::AssetBundlerFileTableFilterModel(QObject* parent, int displayNameCol, int dateTimeCol) + : QSortFilterProxyModel(parent) + , m_displayNameCol(displayNameCol) + , m_dateTimeCol(dateTimeCol) + { + } + + void AssetBundlerFileTableFilterModel::FilterChanged(const QString& newFilter) + { + setFilterRegExp(newFilter.toLower()); + invalidateFilter(); + } + + bool AssetBundlerFileTableFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const + { + // Override the default implemention since we want to define custom rules here + QModelIndex index = sourceModel()->index(sourceRow, m_displayNameCol, sourceParent); + QRegExp filter(filterRegExp()); + + return sourceModel()->data(index).toString().toLower().contains(filter); + } + + bool AssetBundlerFileTableFilterModel::lessThan(const QModelIndex& left, const QModelIndex& right) const + { + // Any column displaying a DateTime string needs to be compared as a DateTime object to ensure + // proper sorting + if (left.column() != m_dateTimeCol || right.column() != m_dateTimeCol) + { + return QSortFilterProxyModel::lessThan(left, right); + } + + QVariant leftTime = sourceModel()->data(left, AssetBundlerAbstractFileTableModel::SortRole); + QVariant rightTime = sourceModel()->data(right, AssetBundlerAbstractFileTableModel::SortRole); + + if (leftTime.type() != QVariant::DateTime || rightTime.type() != QVariant::DateTime) + { + return QSortFilterProxyModel::lessThan(left, right); + } + + return leftTime.toDateTime() < rightTime.toDateTime(); + } +} diff --git a/Code/Tools/AssetBundler/source/models/AssetBundlerFileTableFilterModel.h b/Code/Tools/AssetBundler/source/models/AssetBundlerFileTableFilterModel.h new file mode 100644 index 0000000000..89f33c065a --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetBundlerFileTableFilterModel.h @@ -0,0 +1,34 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +namespace AssetBundler +{ + class AssetBundlerFileTableFilterModel + : public QSortFilterProxyModel + { + public: + AssetBundlerFileTableFilterModel(QObject* parent, int displayNameCol, int dateTimeCol = -1); + + void FilterChanged(const QString& newFilter); + + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; + bool lessThan(const QModelIndex& left, const QModelIndex& right) const override; + + int m_displayNameCol = 0; + int m_dateTimeCol = -1; + }; +} diff --git a/Code/Tools/AssetBundler/source/models/AssetListFileTableModel.cpp b/Code/Tools/AssetBundler/source/models/AssetListFileTableModel.cpp new file mode 100644 index 0000000000..e4bb7b6ca2 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetListFileTableModel.cpp @@ -0,0 +1,251 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace AssetBundler +{ + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // AssetListFileInfo + ////////////////////////////////////////////////////////////////////////////////////////////////// + AssetListFileInfo::AssetListFileInfo(const AZStd::string& absolutePath, const QString& fileName, const AZStd::string& platform) + : m_absolutePath(absolutePath) + , m_fileName(fileName) + , m_platform(QString(platform.c_str())) + { + AzFramework::StringFunc::Path::Normalize(m_absolutePath); + + // Modification time will either give us the time the file was last overwritten + // (or the time it was created if it has never been overwritten) + QFileInfo fileInfo(m_absolutePath.c_str()); + m_fileCreationTime = fileInfo.fileTime(QFileDevice::FileModificationTime); + + // Load the contents of the asset list file into memory + m_assetListModel.reset(new AssetListTableModel(nullptr, absolutePath, platform)); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // AssetListFileTableModel + ////////////////////////////////////////////////////////////////////////////////////////////////// + AssetListFileTableModel::AssetListFileTableModel() + : AssetBundlerAbstractFileTableModel() + { + } + + QSharedPointer AssetListFileTableModel::GetAssetListFileContents(const QModelIndex& index) + { + auto assetListFileInfoOutcome = GetAssetFileInfo(index); + if (!assetListFileInfoOutcome.IsSuccess()) + { + return QSharedPointer(); + } + + return assetListFileInfoOutcome.GetValue()->m_assetListModel; + } + + bool AssetListFileTableModel::DeleteFile(const QModelIndex& index) + { + auto assetFileInfoOutcome = GetAssetFileInfo(index); + if (!assetFileInfoOutcome.IsSuccess()) + { + return false; + } + + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(assetFileInfoOutcome.GetValue()->m_absolutePath); + if (m_assetListFileInfoMap.find(key) == m_assetListFileInfoMap.end()) + { + return false; + } + + AssetListFileInfoPtr assetFileInfo = m_assetListFileInfoMap[key]; + + // Remove file from disk + const char* absolutePath = assetFileInfo->m_absolutePath.c_str(); + if (AZ::IO::FileIOBase::GetInstance()->Exists(absolutePath)) + { + if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(absolutePath)) + { + return false; + } + + auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(absolutePath); + if (!deleteResult) + { + return false; + } + } + + // Remove file from model + m_assetListFileInfoMap.erase(key); + RemoveFileKey(index); + + return true; + } + + void AssetListFileTableModel::LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& /*projectName*/, bool /*isDefaultFile*/) + { + AZStd::string fullFileName; + AzFramework::StringFunc::Path::GetFullFileName(absoluteFilePath.c_str(), fullFileName); + + // Get the file name without the platform for display purposes + AZStd::string baseFileName; + AZStd::string platformIdentifier; + AzToolsFramework::SplitFilename(fullFileName, baseFileName, platformIdentifier); + + // Read the AssetListFile into memory and store it + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath); + m_assetListFileInfoMap[key].reset(new AssetListFileInfo(absoluteFilePath, QString(baseFileName.c_str()), platformIdentifier)); + AddFileKey(key); + } + + bool AssetListFileTableModel::WriteToDisk(const AZStd::string& /*key*/) + { + return true; + } + + AZStd::string AssetListFileTableModel::GetFileAbsolutePath(const QModelIndex& index) const + { + auto assetFileInfoOutcome = GetAssetFileInfo(index); + if (!assetFileInfoOutcome.IsSuccess()) + { + // Error has already been thrown + return AZStd::string(); + } + return assetFileInfoOutcome.GetValue()->m_absolutePath; + } + + int AssetListFileTableModel::GetFileNameColumnIndex() const + { + return Column::ColumnFileName; + } + + int AssetListFileTableModel::GetTimeStampColumnIndex() const + { + return Column::ColumnFileCreationTime; + } + + int AssetListFileTableModel::columnCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : Column::Max; + } + + QVariant AssetListFileTableModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case Column::ColumnFileName: + return QString(tr("Asset List File")); + case Column::ColumnPlatform: + return QString(tr("Platform")); + case Column::ColumnFileCreationTime: + return QString(tr("Creation Time")); + default: + break; + } + } + + return QVariant(); + } + + QVariant AssetListFileTableModel::data(const QModelIndex& index, int role) const + { + auto assetListFileInfoOutcome = GetAssetFileInfo(index); + if (!assetListFileInfoOutcome.IsSuccess()) + { + return QVariant(); + } + + int col = index.column(); + + switch (role) + { + case Qt::DisplayRole: + [[fallthrough]]; + case SortRole: + { + if (col == Column::ColumnFileName) + { + return assetListFileInfoOutcome.GetValue()->m_fileName; + } + else if (col == Column::ColumnPlatform) + { + return assetListFileInfoOutcome.GetValue()->m_platform; + } + else if (col == Column::ColumnFileCreationTime) + { + if (role == SortRole) + { + return assetListFileInfoOutcome.GetValue()->m_fileCreationTime; + } + else + { + return assetListFileInfoOutcome.GetValue()->m_fileCreationTime.toString(DateTimeFormat); + } + } + else + { + // Returning an empty QString will ensure the checkboxes do not have any text displayed next to them + return QString(); + } + } + case Qt::FontRole: + { + if (col == Column::ColumnFileName) + { + QFont boldFont; + boldFont.setBold(true); + return boldFont; + } + } + default: + break; + } + + return QVariant(); + } + + AZ::Outcome AssetListFileTableModel::GetAssetFileInfo(const QModelIndex& index) const + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return AZ::Failure(); + } + + if (m_assetListFileInfoMap.find(key) != m_assetListFileInfoMap.end()) + { + return AZ::Success(m_assetListFileInfoMap.at(key)); + } + else + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot find Asset List File Info"); + return AZ::Failure(); + } + } + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/AssetListFileTableModel.h b/Code/Tools/AssetBundler/source/models/AssetListFileTableModel.h new file mode 100644 index 0000000000..61f1455130 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetListFileTableModel.h @@ -0,0 +1,88 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +#include +#include + +namespace AssetBundler +{ + class AssetListTableModel; + + struct AssetListFileInfo + { + /** + * Stores information about an Asset List File on disk. + * + * @param absolutePath The absolute path of the Asset List File + * @param fileName The name of the Asset List File. This does not include the platform ID + * @param platform The platform for the Asset List File + */ + AssetListFileInfo(const AZStd::string& absolutePath, const QString& fileName, const AZStd::string& platform); + + AZStd::string m_absolutePath; + QDateTime m_fileCreationTime; + /// Use QString for display purpose. This can help to avoid losts of string conversion + QString m_fileName; + QString m_platform; + + QSharedPointer m_assetListModel; + }; + + using AssetListFileInfoPtr = AZStd::shared_ptr; + /// Stores AssetListFileInfo, using the absolute path (without the drive letter) of the Asset List file as the key + using AssetListFileInfoMap = AZStd::unordered_map; + + class AssetListFileTableModel + : public AssetBundlerAbstractFileTableModel + { + public: + explicit AssetListFileTableModel(); + virtual ~AssetListFileTableModel() {} + + QSharedPointer GetAssetListFileContents(const QModelIndex& index); + + ////////////////////////////////////////////////////////////////////////// + // AssetBundlerAbstractFileTableModel overrides + AZStd::vector CreateNewFiles(const AZStd::string& /*absoluteFilePath*/, const AzFramework::PlatformFlags& /*platforms*/, const QString& /*project*/) override { return {}; } + bool DeleteFile(const QModelIndex& index) override; + void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) override; + bool WriteToDisk(const AZStd::string& key) override; + AZStd::string GetFileAbsolutePath(const QModelIndex& index) const override; + int GetFileNameColumnIndex() const override; + int GetTimeStampColumnIndex() const override; + + ////////////////////////////////////////////////////////////////////////// + // QAbstractListModel overrides + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; + ////////////////////////////////////////////////////////////////////////// + + enum Column + { + ColumnFileName, + ColumnPlatform, + ColumnFileCreationTime, + Max + }; + + private: + AZ::Outcome GetAssetFileInfo(const QModelIndex& index) const; + + AssetListFileInfoMap m_assetListFileInfoMap; + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/AssetListTableModel.cpp b/Code/Tools/AssetBundler/source/models/AssetListTableModel.cpp new file mode 100644 index 0000000000..cec057d38b --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetListTableModel.cpp @@ -0,0 +1,129 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include + +#include + +namespace AssetBundler +{ + ////////////////////////////////////////////////////////////////////////////////////////////////// + // AssetListTableModel + ////////////////////////////////////////////////////////////////////////////////////////////////// + AssetListTableModel::AssetListTableModel(QObject* parent, const AZStd::string& absolutePath, const AZStd::string& platform) + : QAbstractTableModel(parent) + { + m_seedListManager.reset(new AzToolsFramework::AssetSeedManager()); + + if (absolutePath.empty() || platform.empty()) + { + return; + } + + AZ::Outcome outcome = m_seedListManager->LoadAssetFileInfo(absolutePath); + if (!outcome.IsSuccess()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Failed to load the asset file info for %s", absolutePath.c_str()); + return; + } + + m_assetFileInfoList = outcome.TakeValue(); + m_platformId = static_cast(AzFramework::PlatformHelper::GetPlatformIndexFromName(platform.c_str())); + } + + int AssetListTableModel::rowCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : static_cast(m_assetFileInfoList.m_fileInfoList.size()); + } + + int AssetListTableModel::columnCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : Column::Max; + } + + QVariant AssetListTableModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case Column::ColumnAssetName: + return QString("Asset Name"); + case Column::ColumnRelativePath: + return QString("Relative Path"); + case Column::ColumnAssetId: + return QString("Asset ID"); + default: + break; + } + } + + return QVariant(); + } + + QVariant AssetListTableModel::data(const QModelIndex& index, int role) const + { + auto assetFileInfoOutcome = GetAssetFileInfo(index); + if (!assetFileInfoOutcome.IsSuccess()) + { + return QVariant(); + } + + switch (role) + { + case Qt::DisplayRole: + { + switch (index.column()) + { + case Column::ColumnAssetName: + { + AZStd::string fileName = assetFileInfoOutcome.GetValue().m_assetRelativePath; + AzFramework::StringFunc::Path::GetFullFileName(fileName.c_str(), fileName); + + return fileName.c_str(); + } + case Column::ColumnRelativePath: + { + return assetFileInfoOutcome.GetValue().m_assetRelativePath.c_str(); + } + case Column::ColumnAssetId: + { + AZStd::string assetIdStr; + assetFileInfoOutcome.GetValue().m_assetId.ToString(assetIdStr); + + return assetIdStr.c_str(); + } + default: + break; + } + } + default: + break; + } + + return QVariant(); + } + + AZ::Outcome AssetListTableModel::GetAssetFileInfo(const QModelIndex& index) const + { + int row = index.row(); + int col = index.column(); + if (row >= rowCount() || row < 0 || col >= columnCount() || col < 0) + { + return AZ::Failure(AZStd::string::format("Selected index (%i, %i) is out of range", row, col)); + } + + return AZ::Success(m_assetFileInfoList.m_fileInfoList.at(row)); + } +} diff --git a/Code/Tools/AssetBundler/source/models/AssetListTableModel.h b/Code/Tools/AssetBundler/source/models/AssetListTableModel.h new file mode 100644 index 0000000000..94500f520f --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetListTableModel.h @@ -0,0 +1,54 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include + +#include + +namespace AssetBundler +{ + class AssetListTableModel + : public QAbstractTableModel + { + public: + explicit AssetListTableModel(QObject* parent = nullptr, const AZStd::string& absolutePath = AZStd::string(), const AZStd::string& platform = ""); + virtual ~AssetListTableModel() {} + + AZStd::shared_ptr GetSeedListManager() { return m_seedListManager; } + + ////////////////////////////////////////////////////////////////////////// + // QAbstractListModel overrides + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; + ////////////////////////////////////////////////////////////////////////// + + enum Column + { + ColumnAssetName, + ColumnRelativePath, + ColumnAssetId, + Max + }; + + private: + AZ::Outcome GetAssetFileInfo(const QModelIndex& index) const; + + AZStd::shared_ptr m_seedListManager; + AzToolsFramework::AssetFileInfoList m_assetFileInfoList; + AzFramework::PlatformId m_platformId; + }; +} diff --git a/Code/Tools/AssetBundler/source/models/BundleFileListModel.cpp b/Code/Tools/AssetBundler/source/models/BundleFileListModel.cpp new file mode 100644 index 0000000000..d7c0e93279 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/BundleFileListModel.cpp @@ -0,0 +1,236 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include +#include + +#include + +#include + + +namespace AssetBundler +{ + BundleFileInfo::BundleFileInfo(const AZStd::string& absolutePath) + : m_absolutePath(absolutePath) + , m_compressedSize(0u) + { + AzFramework::StringFunc::Path::Normalize(m_absolutePath); + + AZStd::string fileNameStr; + if (AzFramework::StringFunc::Path::GetFileName(m_absolutePath.c_str(), fileNameStr)) + { + m_fileName = QString(fileNameStr.c_str()); + } + else + { + AZ_Error("AssetBundler", false, "Failed to get file name from %s", m_absolutePath.c_str()); + } + + // Modification time will either give us the time the file was last overwritten + // (or the time it was created if it has never been overwritten) + QFileInfo fileInfo(m_absolutePath.c_str()); + m_fileCreationTime = fileInfo.fileTime(QFileDevice::FileModificationTime); + } + + BundleFileListModel::BundleFileListModel() + : AssetBundlerAbstractFileTableModel() + { + } + + bool BundleFileListModel::DeleteFile(const QModelIndex& index) + { + AZStd::string fileKey = GetFileKey(index); + if (fileKey.empty()) + { + // Error has already been thrown + return false; + } + + auto bundleFileInfoIt = m_bundleFileInfoMap.find(fileKey); + if (bundleFileInfoIt == m_bundleFileInfoMap.end()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to find Bundle Info with key ( %s )", fileKey.c_str()); + return false; + } + + BundleFileInfoPtr bundleFileInfo = bundleFileInfoIt->second; + + // Remove file from disk + const char* absolutePath = bundleFileInfo->m_absolutePath.c_str(); + if (AZ::IO::FileIOBase::GetInstance()->Exists(absolutePath)) + { + if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(absolutePath)) + { + AZ_Error(AssetBundler::AppWindowName, false, "File (%s) is Read-Only. Please check your version control and try again.", absolutePath); + return false; + } + + auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(absolutePath); + if (!deleteResult) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to delete: %s", absolutePath); + return false; + } + } + + // Remove file from Model + m_bundleFileInfoMap.erase(fileKey); + RemoveFileKey(index); + + return true; + } + + int BundleFileListModel::columnCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : Column::Max; + } + + QVariant BundleFileListModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case Column::ColumnFileName: + return QString(tr("Name")); + case Column::ColumnFileCreationTime: + return QString(tr("Creation Time")); + default: + break; + } + } + return QVariant(); + } + + QVariant BundleFileListModel::data(const QModelIndex& index, int role) const + { + auto bundleInfoOutcome = GetBundleInfo(index); + if (!bundleInfoOutcome.IsSuccess()) + { + return QVariant(); + } + + int col = index.column(); + + switch (role) + { + case Qt::DisplayRole: + [[fallthrough]]; + case SortRole: + { + if (col == Column::ColumnFileName) + { + return bundleInfoOutcome.GetValue()->m_fileName; + } + else if (col == Column::ColumnFileCreationTime) + { + if (role == SortRole) + { + return bundleInfoOutcome.GetValue()->m_fileCreationTime; + } + else + { + return bundleInfoOutcome.GetValue()->m_fileCreationTime.toString(DateTimeFormat); + } + } + } + default: + break; + } + + return QVariant(); + } + + AZStd::string BundleFileListModel::GetFileAbsolutePath(const QModelIndex& index) const + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return key; + } + + return m_bundleFileInfoMap.at(key)->m_absolutePath; + } + + int BundleFileListModel::GetFileNameColumnIndex() const + { + return Column::ColumnFileName; + } + + int BundleFileListModel::GetTimeStampColumnIndex() const + { + return Column::ColumnFileCreationTime; + } + + void BundleFileListModel::LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& /*projectName*/, bool /*isDefaultFile*/) + { + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath); + + BundleFileInfo* newInfo = new BundleFileInfo(absoluteFilePath); + + QFile bundleFile(absoluteFilePath.c_str()); + if (bundleFile.open(QIODevice::ReadOnly)) + { + newInfo->m_compressedSize = bundleFile.size(); + bundleFile.close(); + } + else + { + AZ_Error("AssetBundler", false, "Failed to open file at %s", absoluteFilePath.c_str()); + } + + auto manifest = AzToolsFramework::AssetBundleComponent::GetManifestFromBundle(absoluteFilePath); + if (manifest != nullptr) + { + for (auto& bundleName : manifest->GetDependentBundleNames()) + { + newInfo->m_relatedBundles.push_back(bundleName.c_str()); + } + } + else + { + AZ_Error("AssetBundler", false, "Failed to get manifest from bundle at %s", absoluteFilePath.c_str()); + } + + m_bundleFileInfoMap[key].reset(newInfo); + // Add it to the list that gets displayed by AssetBundlerAbstractFileTableModel. Make sure that + // AddFileKey is called after m_bundleFileInfoMap is reset since the filterAcceptsRow funtion + // of the filter model will be called when a new row is inserted and it could cause a crash + // without valid data being set + AddFileKey(key); + } + + AZ::Outcome BundleFileListModel::GetBundleInfo(const QModelIndex& index) const + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return AZ::Failure(); + } + + if (m_bundleFileInfoMap.find(key) != m_bundleFileInfoMap.end()) + { + return AZ::Success(m_bundleFileInfoMap.at(key)); + } + else + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot find Bundle File Info"); + return AZ::Failure(); + } + } + +} diff --git a/Code/Tools/AssetBundler/source/models/BundleFileListModel.h b/Code/Tools/AssetBundler/source/models/BundleFileListModel.h new file mode 100644 index 0000000000..13e5838c57 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/BundleFileListModel.h @@ -0,0 +1,74 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include + +#include + +#include + +namespace AssetBundler +{ + + struct BundleFileInfo + { + AZStd::string m_absolutePath; + QString m_fileName; + QDateTime m_fileCreationTime; + AZ::u64 m_compressedSize; + QStringList m_relatedBundles; + + BundleFileInfo(const AZStd::string& absolutePath); + }; + + using BundleFileInfoPtr = AZStd::shared_ptr; + using BundleFileInfoMap = AZStd::unordered_map; + + class BundleFileListModel + : public AssetBundlerAbstractFileTableModel + { + public: + explicit BundleFileListModel(); + virtual ~BundleFileListModel() {} + + AZStd::vector CreateNewFiles(const AZStd::string& /*absoluteFilePath*/, const AzFramework::PlatformFlags& /*platforms*/, const QString& /*project*/) override { return {}; } + bool DeleteFile(const QModelIndex& index) override; + void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) override; + bool WriteToDisk(const AZStd::string& /*key*/) override { return true; } + + AZStd::string GetFileAbsolutePath(const QModelIndex& index) const override; + int GetFileNameColumnIndex() const override; + int GetTimeStampColumnIndex() const override; + + AZ::Outcome GetBundleInfo(const QModelIndex& index) const; + + ////////////////////////////////////////////////////////////////////////// + // QAbstractTableModel overrides + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; + ////////////////////////////////////////////////////////////////////////// + + enum Column + { + ColumnFileName, + ColumnFileCreationTime, + Max + }; + + private: + BundleFileInfoMap m_bundleFileInfoMap; + }; +} diff --git a/Code/Tools/AssetBundler/source/models/RulesFileTableModel.cpp b/Code/Tools/AssetBundler/source/models/RulesFileTableModel.cpp new file mode 100644 index 0000000000..c7ae384d6e --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/RulesFileTableModel.cpp @@ -0,0 +1,305 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include +#include +#include +#include + +#include +#include + +namespace AssetBundler +{ + RulesFileInfo::RulesFileInfo(const AZStd::string& absolutePath, const QString& fileName, bool loadFromFile) + : m_absolutePath(absolutePath) + , m_fileName(fileName) + { + AzFramework::StringFunc::Path::Normalize(m_absolutePath); + m_comparisonSteps = AZStd::make_shared(); + + if (loadFromFile) + { + auto outcome = AzToolsFramework::AssetFileInfoListComparison::Load(m_absolutePath); + if (!outcome.IsSuccess()) + { + AZ_Error("AssetBundler", false, outcome.GetError().c_str()); + return; + } + m_comparisonSteps = AZStd::make_unique(outcome.TakeValue()); + + QFileInfo fileInfo(m_absolutePath.c_str()); + m_fileModificationTime = fileInfo.fileTime(QFileDevice::FileModificationTime); + } + else + { + m_fileModificationTime = QDateTime::currentDateTime(); + } + } + + bool RulesFileInfo::SaveRulesFile() + { + if (!m_comparisonSteps->Save(m_absolutePath)) + { + return false; + } + + m_hasUnsavedChanges = false; + m_fileModificationTime = QDateTime::currentDateTime(); + return true; + } + + + + RulesFileTableModel::RulesFileTableModel() + : AssetBundlerAbstractFileTableModel() + { + } + + AZStd::vector RulesFileTableModel::CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& /*platforms*/, const QString& /*project*/) + { + if (absoluteFilePath.empty()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Input file path is empty"); + return {}; + } + + // Create a platform-specific file path + if (AZ::IO::FileIOBase::GetInstance()->Exists(absoluteFilePath.c_str())) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot Create New File: (%s) already exists", absoluteFilePath.c_str()); + return {}; + } + + // Get the file name without the extension for display purposes + AZStd::string fileName = absoluteFilePath; + AzToolsFramework::RemovePlatformIdentifier(fileName); + AzFramework::StringFunc::Path::GetFileName(fileName.c_str(), fileName); + + // Create a Rules File and save it to disk + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath); + RulesFileInfoPtr newRulesFile = AZStd::make_shared(absoluteFilePath, QString(fileName.c_str()), false); + + if (!newRulesFile->SaveRulesFile()) + { + return {}; + } + + // Add the new file to the model + m_rulesFileInfoMap[key] = newRulesFile; + AddFileKey(key); + return { absoluteFilePath }; + } + + bool RulesFileTableModel::DeleteFile(const QModelIndex& index) + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + RulesFileInfoPtr rulesFileInfo = m_rulesFileInfoMap[key]; + + // Remove file from disk + if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(rulesFileInfo->m_absolutePath.c_str())) + { + AZ_Error(AssetBundler::AppWindowName, false, "File (%s) is Read-Only. Please check your version control and try again.", rulesFileInfo->m_absolutePath.c_str()); + return false; + } + + auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(rulesFileInfo->m_absolutePath.c_str()); + if (!deleteResult) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to delete: %s", rulesFileInfo->m_absolutePath.c_str()); + return false; + } + + // Remove file from model + m_rulesFileInfoMap.erase(key); + RemoveFileKey(index); + + return true; + } + + void RulesFileTableModel::LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& /*projectName*/, bool /*isDefaultFile*/) + { + // Get the file name without the extension for display purposes + AZStd::string fileName(absoluteFilePath); + AzFramework::StringFunc::Path::GetFileName(fileName.c_str(), fileName); + + // Read the Rules file into memory and store it + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath); + auto fileInfoIt = m_rulesFileInfoMap.find(key); + if (fileInfoIt != m_rulesFileInfoMap.end() && fileInfoIt->second->m_hasUnsavedChanges) + { + AZ_Warning(AssetBundler::AppWindowName, false, "Rules File %s has unsaved changes and couldn't be reloaded", absoluteFilePath.c_str()); + return; + } + + m_rulesFileInfoMap[key] = AZStd::make_shared(absoluteFilePath, QString(fileName.c_str()), true); + AddFileKey(key); + } + + bool RulesFileTableModel::WriteToDisk(const AZStd::string& key) + { + auto rulesFileIt = m_rulesFileInfoMap.find(key); + return rulesFileIt != m_rulesFileInfoMap.end() && rulesFileIt->second->SaveRulesFile(); + } + + AZStd::string RulesFileTableModel::GetFileAbsolutePath(const QModelIndex& index) const + { + RulesFileInfoPtr rulesFileInfo = GetRulesFileInfoPtr(index); + if (!rulesFileInfo) + { + return AZStd::string(); + } + + return rulesFileInfo->m_absolutePath; + } + + int RulesFileTableModel::GetFileNameColumnIndex() const + { + return Column::ColumnFileName; + } + + int RulesFileTableModel::GetTimeStampColumnIndex() const + { + return Column::ColumnFileModificationTime; + } + + AZStd::shared_ptr RulesFileTableModel::GetComparisonSteps(const QModelIndex& index) const + { + RulesFileInfoPtr rulesFileInfo = GetRulesFileInfoPtr(index); + if (!rulesFileInfo) + { + return nullptr; + } + + return rulesFileInfo->m_comparisonSteps; + } + + bool RulesFileTableModel::MarkFileChanged(const QModelIndex& index) + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + m_rulesFileInfoMap[key]->m_hasUnsavedChanges = true; + + // Update display so the user knows there are unsaved changes + m_keysWithUnsavedChanges.emplace(key); + QModelIndex changedIndex = QAbstractTableModel::index(index.row(), Column::ColumnFileName); + emit dataChanged(changedIndex, changedIndex, { Qt::DisplayRole, Qt::FontRole }); + + return true; + } + + int RulesFileTableModel::columnCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : Column::Max; + } + + QVariant RulesFileTableModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case Column::ColumnFileName: + return QString(tr("Name")); + case Column::ColumnFileModificationTime: + return QString(tr("Modification Time")); + default: + break; + } + } + + return QVariant(); + } + + QVariant RulesFileTableModel::data(const QModelIndex& index, int role) const + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + return QVariant(); + } + + RulesFileInfoPtr rulesFileInfo = m_rulesFileInfoMap.at(key); + + int col = index.column(); + bool hasUnsavedChanges = rulesFileInfo->m_hasUnsavedChanges; + + switch (role) + { + case Qt::DisplayRole: + [[fallthrough]]; + case SortRole: + { + if (col == Column::ColumnFileName) + { + QString displayName = rulesFileInfo->m_fileName; + if (hasUnsavedChanges) + { + displayName.append("*"); + } + return displayName; + } + else if (col == Column::ColumnFileModificationTime) + { + if (role == SortRole) + { + return rulesFileInfo->m_fileModificationTime; + } + else + { + return rulesFileInfo->m_fileModificationTime.toString(DateTimeFormat); + } + } + break; + } + case Qt::FontRole: + { + if (col == Column::ColumnFileName && hasUnsavedChanges) + { + QFont boldFont; + boldFont.setBold(true); + return boldFont; + } + break; + } + default: + break; + } + + return QVariant(); + } + + RulesFileInfoPtr RulesFileTableModel::GetRulesFileInfoPtr(const QModelIndex& index) const + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + return nullptr; + } + + return m_rulesFileInfoMap.at(key); + } + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/RulesFileTableModel.h b/Code/Tools/AssetBundler/source/models/RulesFileTableModel.h new file mode 100644 index 0000000000..a9931a9819 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/RulesFileTableModel.h @@ -0,0 +1,88 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include + +#include + +#include + +namespace AssetBundler +{ + + //! Stores information about a Rules file on disk. + struct RulesFileInfo + { + RulesFileInfo(const AZStd::string& absolutePath, const QString& fileName, bool loadFromFile); + + bool SaveRulesFile(); + + AZStd::string m_absolutePath; + QString m_fileName; + QDateTime m_fileModificationTime; + bool m_hasUnsavedChanges = false; + + AZStd::shared_ptr m_comparisonSteps; + }; + + using RulesFileInfoPtr = AZStd::shared_ptr; + using RulesFileInfoMap = AZStd::unordered_map; + + + class RulesFileTableModel + : public AssetBundlerAbstractFileTableModel + { + public: + RulesFileTableModel(); + virtual ~RulesFileTableModel() {} + + AZStd::vector CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms = AzFramework::PlatformFlags::Platform_NONE, const QString& project = QString()) override; + + bool DeleteFile(const QModelIndex& index) override; + + void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) override; + + bool WriteToDisk(const AZStd::string& key) override; + + AZStd::string GetFileAbsolutePath(const QModelIndex& index) const override; + + int GetFileNameColumnIndex() const override; + + int GetTimeStampColumnIndex() const override; + + AZStd::shared_ptr GetComparisonSteps(const QModelIndex& index) const; + + bool MarkFileChanged(const QModelIndex& index); + + ////////////////////////////////////////////////////////////////////////// + // QAbstractTableModel overrides + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; + ////////////////////////////////////////////////////////////////////////// + + enum Column + { + ColumnFileName, + ColumnFileModificationTime, + Max + }; + + private: + RulesFileInfoMap m_rulesFileInfoMap; + + RulesFileInfoPtr GetRulesFileInfoPtr(const QModelIndex& index) const; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/SeedListFileTableModel.cpp b/Code/Tools/AssetBundler/source/models/SeedListFileTableModel.cpp new file mode 100644 index 0000000000..1e7ec36bac --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/SeedListFileTableModel.cpp @@ -0,0 +1,601 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace AssetBundler +{ + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // SeedListFileInfo + ////////////////////////////////////////////////////////////////////////////////////////////////// + SeedListFileInfo::SeedListFileInfo( + const AZStd::string& absolutePath, + const QString& fileName, + const QString& project, + bool loadFromFile, + bool isDefaultSeedList, + const AZStd::vector& defaultSeeds, + const AzFramework::PlatformFlags& platforms) + : m_absolutePath(absolutePath) + , m_fileName(fileName) + , m_project(project) + , m_isDefaultSeedList(isDefaultSeedList) + { + AzFramework::StringFunc::Path::Normalize(m_absolutePath); + + // Load the contents of the seed file into memory + if (loadFromFile) + { + m_seedListModel.reset(new SeedListTableModel(nullptr, absolutePath)); + QFileInfo fileInfo(m_absolutePath.c_str()); + m_fileModificationTime = fileInfo.fileTime(QFileDevice::FileModificationTime); + } + else + { + m_seedListModel.reset(new SeedListTableModel(nullptr, "", defaultSeeds, platforms)); + m_fileModificationTime = QDateTime::currentDateTime(); + } + } + + bool SeedListFileInfo::SaveSeedFile() + { + if (m_seedListModel->Save(m_absolutePath)) + { + m_fileModificationTime = QDateTime::currentDateTime(); + return true; + } + return false; + } + + bool SeedListFileInfo::HasUnsavedChanges() + { + return m_seedListModel->HasUnsavedChanges(); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // SeedListFileTableModel + ////////////////////////////////////////////////////////////////////////////////////////////////// + + SeedListFileTableModel::SeedListFileTableModel(SeedTabWidget* parentSeedTabWidget) + : AssetBundlerAbstractFileTableModel() + , m_seedTabWidget(parentSeedTabWidget) + { + m_inMemoryDefaultSeedList.reset(new SeedListFileInfo("", "", "", false)); + } + + SeedListFileTableModel::~SeedListFileTableModel() + { + m_seedTabWidget = nullptr; + } + + void SeedListFileTableModel::AddDefaultSeedsToInMemoryList(const AZStd::vector& defaultSeeds, const char* projectName, const AzFramework::PlatformFlags& platforms) + { + m_inMemoryDefaultSeedList.reset(new SeedListFileInfo(m_inMemoryDefaultSeedListKey, tr("DefaultSeeds"), QString(projectName), false, true, defaultSeeds, platforms)); + } + + AZStd::vector SeedListFileTableModel::CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& /*platforms*/, const QString& project) + { + if (absoluteFilePath.empty()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Input file path is empty."); + return {}; + } + + // Get the file name without the extension for display purposes + AZStd::string fileName; + AzFramework::StringFunc::Path::GetFileName(absoluteFilePath.c_str(), fileName); + + // Create a Seed List File and save it to disk + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath); + + AZStd::shared_ptr newSeedListFile = AZStd::make_shared(absoluteFilePath, QString(fileName.c_str()), project, false); + newSeedListFile->m_seedListModel->SetHasUnsavedChanges(true); + bool saveResult = newSeedListFile->SaveSeedFile(); + if (!saveResult) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to create Seed List File: %s", absoluteFilePath.c_str()); + return {}; + } + + // Add new file to the model + m_seedListFileInfoMap[key] = newSeedListFile; + AddFileKey(key); + + AZStd::vector createdFiles = { absoluteFilePath }; + return createdFiles; + } + + bool SeedListFileTableModel::DeleteFile(const QModelIndex& index) + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + if (m_seedListFileInfoMap.find(key) == m_seedListFileInfoMap.end()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to find Seed File Info with key ( %s )", key.c_str()); + return false; + } + + SeedListFileInfoPtr seedFileInfo = m_seedListFileInfoMap[key]; + + // Remove file from disk + const char* absolutePath = seedFileInfo->m_absolutePath.c_str(); + if (AZ::IO::FileIOBase::GetInstance()->Exists(absolutePath)) + { + if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(absolutePath)) + { + AZ_Error(AssetBundler::AppWindowName, false, "File (%s) is Read-Only. Please check your version control and try again.", absolutePath); + return false; + } + + auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(absolutePath); + if (!deleteResult) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to delete: %s", absolutePath); + return false; + } + } + + // Remove file from model + m_seedListFileInfoMap.erase(key); + RemoveFileKey(index); + + return true; + } + + void SeedListFileTableModel::Reload(const char* fileExtension, const QSet& watchedFolders, const QSet& watchedFiles, const AZStd::unordered_map& pathToProjectNameMap) + { + // Load in the Seed List files from disk + AssetBundlerAbstractFileTableModel::Reload(fileExtension, watchedFolders, watchedFiles, pathToProjectNameMap); + + // Add the in-memory Default Seed List to the model + m_seedListFileInfoMap[m_inMemoryDefaultSeedListKey] = m_inMemoryDefaultSeedList; + AddFileKey(m_inMemoryDefaultSeedListKey); + } + + void SeedListFileTableModel::LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName, bool isDefaultFile) + { + // Get the file name without the extension for display purposes + AZStd::string fileName; + AzFramework::StringFunc::Path::GetFileName(absoluteFilePath.c_str(), fileName); + + // Read the SeedListFile into memory and store it + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath); + auto fileInfoIt = m_seedListFileInfoMap.find(key); + if (fileInfoIt != m_seedListFileInfoMap.end() && fileInfoIt->second->HasUnsavedChanges()) + { + AZ_Warning(AssetBundler::AppWindowName, false, "Seed List File %s has unsaved changes and couldn't be reloaded", absoluteFilePath.c_str()); + return; + } + + AZStd::string projectNameOnDisplay = projectName; + if (projectName.empty()) + { + auto outcome = AssetBundler::GetCurrentProjectName(); + if (!outcome.IsSuccess()) + { + AZ_Error(AssetBundler::AppWindowName, false, outcome.TakeError().c_str()); + return; + } + + projectNameOnDisplay = outcome.TakeValue(); + } + + m_seedListFileInfoMap[key].reset(new SeedListFileInfo(absoluteFilePath, QString(fileName.c_str()), QString(projectNameOnDisplay.c_str()), true, isDefaultFile)); + AddFileKey(key); + } + + void SeedListFileTableModel::SelectDefaultSeedLists(bool setSelected) + { + for (const AZStd::string& key : GetAllFileKeys()) + { + auto seedFileInfo = m_seedListFileInfoMap[key]; + if (!seedFileInfo->m_isDefaultSeedList) + { + continue; + } + + seedFileInfo->m_isChecked = setSelected; + if(setSelected) + { + m_checkedSeedListFiles.insert(key); + } + else + { + m_checkedSeedListFiles.erase(key); + } + } + + m_seedTabWidget->SetGenerateAssetListsButtonEnabled(!m_checkedSeedListFiles.empty()); + + // Update the Check State display of all elements + QModelIndex firstIndex = index(0, 0); + QModelIndex lastIndex = index(rowCount() - 1, columnCount() - 1); + emit dataChanged(firstIndex, lastIndex, { Qt::CheckStateRole }); + } + + AZStd::vector SeedListFileTableModel::GenerateAssetLists(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms) + { + if (!m_checkedSeedListFiles.size()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot Generate Asset List File(s): No Seed List Files are selected"); + return {}; + } + + if (absoluteFilePath.empty()) + { + AZ_Error(AssetBundler::AppWindowName, false, "File path cannot be empty"); + return {}; + } + + if(platforms == AzFramework::PlatformFlags::Platform_NONE) + { + AZ_Error(AssetBundler::AppWindowName, false, "Input platform cannot be empty"); + return {}; + } + + // Get all of the Seeds into one AssetSeedManager + AzToolsFramework::AssetSeedManager assetSeedManager; + + if (m_checkedSeedListFiles.find(m_inMemoryDefaultSeedListKey) != m_checkedSeedListFiles.end()) + { + // The In-Memory Default Seed List can't be loaded from a file on disk, it is a special case + assetSeedManager = *m_inMemoryDefaultSeedList->m_seedListModel->GetSeedListManager().get(); + m_checkedSeedListFiles.erase(m_inMemoryDefaultSeedListKey); + } + + for (const auto& checkedSeedFileKey : m_checkedSeedListFiles) + { + assetSeedManager.Load(m_seedListFileInfoMap[checkedSeedFileKey]->m_absolutePath); + } + + // Generate an AssetList for every input platform + AZStd::vector createdFiles; + for (const auto& platformIndex : AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(platforms)) + { + AZStd::string platformSpecificCachePath = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(platformIndex); + AzFramework::StringFunc::Path::StripFullName(platformSpecificCachePath); + + FilePath platformSpecificPath(absoluteFilePath, AZStd::string(AzFramework::PlatformHelper::GetPlatformName(platformIndex))); + if (assetSeedManager.SaveAssetFileInfo(platformSpecificPath.AbsolutePath(), AzFramework::PlatformHelper::GetPlatformFlagFromPlatformIndex(platformIndex))) + { + createdFiles.emplace_back(platformSpecificPath.AbsolutePath()); + } + } + + return createdFiles; + } + + QSharedPointer SeedListFileTableModel::GetSeedListFileContents(const QModelIndex& index) + { + auto seedFileInfoOutcome = GetSeedFileInfo(index); + if (!seedFileInfoOutcome.IsSuccess()) + { + return QSharedPointer(); + } + + return seedFileInfoOutcome.GetValue()->m_seedListModel; + } + + bool SeedListFileTableModel::SetSeedPlatforms(const QModelIndex& seedFileIndex, const QModelIndex& seedIndex, const AzFramework::PlatformFlags& platforms) + { + AZStd::string key = GetFileKey(seedFileIndex); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + if (m_seedListFileInfoMap.find(key) == m_seedListFileInfoMap.end()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to find Seed File Info with key ( %s )", key.c_str()); + return false; + } + + SeedListFileInfoPtr seedFileInfo = m_seedListFileInfoMap[key]; + if (!seedFileInfo->m_seedListModel->SetSeedPlatforms(seedIndex, platforms)) + { + // Error has already been thrown + return false; + } + + // Update display so the user knows there are unsaved changes + m_keysWithUnsavedChanges.insert(key); + QModelIndex changedIndex = QAbstractTableModel::index(seedFileIndex.row(), Column::ColumnFileName); + emit dataChanged(changedIndex, changedIndex, { Qt::DisplayRole, Qt::FontRole }); + + return true; + } + + bool SeedListFileTableModel::AddSeed(const QModelIndex& seedFileIndex, const AZStd::string& seedRelativePath, const AzFramework::PlatformFlags& platforms) + { + AZStd::string key = GetFileKey(seedFileIndex); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + if (m_seedListFileInfoMap.find(key) == m_seedListFileInfoMap.end()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to find Seed File Info with key ( %s )", key.c_str()); + return false; + } + + SeedListFileInfoPtr seedFileInfo = m_seedListFileInfoMap[key]; + if (!seedFileInfo->m_seedListModel->AddSeed(seedRelativePath, platforms)) + { + // Error has already been thrown + return false; + } + + // Update display so the user knows there are unsaved changes + m_keysWithUnsavedChanges.insert(key); + QModelIndex changedIndex = QAbstractTableModel::index(seedFileIndex.row(), Column::ColumnFileName); + emit dataChanged(changedIndex, changedIndex, { Qt::DisplayRole, Qt::FontRole }); + + return true; + } + + bool SeedListFileTableModel::RemoveSeed(const QModelIndex& seedFileIndex, const QModelIndex& seedIndex) + { + AZStd::string key = GetFileKey(seedFileIndex); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + if (m_seedListFileInfoMap.find(key) == m_seedListFileInfoMap.end()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to find Seed File Info with key ( %s )", key.c_str()); + return false; + } + + SeedListFileInfoPtr seedFileInfo = m_seedListFileInfoMap[key]; + if (!seedFileInfo->m_seedListModel->RemoveSeed(seedIndex)) + { + // Error has already been thrown + return false; + } + + // Update display so the user knows there are unsaved changes + m_keysWithUnsavedChanges.insert(key); + QModelIndex changedIndex = QAbstractTableModel::index(seedFileIndex.row(), Column::ColumnFileName); + emit dataChanged(changedIndex, changedIndex, { Qt::DisplayRole, Qt::FontRole }); + + return true; + } + + bool SeedListFileTableModel::WriteToDisk(const AZStd::string& key) + { + if (key == m_inMemoryDefaultSeedListKey) + { + return true; + } + + auto seedListFileIt = m_seedListFileInfoMap.find(key); + return seedListFileIt != m_seedListFileInfoMap.end() && seedListFileIt->second->SaveSeedFile(); + } + + AZStd::string SeedListFileTableModel::GetFileAbsolutePath(const QModelIndex& index) const + { + auto seedFileInfoOutcome = GetSeedFileInfo(index); + if (!seedFileInfoOutcome.IsSuccess() || seedFileInfoOutcome.GetValue()->m_absolutePath == m_inMemoryDefaultSeedListKey) + { + // Error has already been thrown + return AZStd::string(); + } + return seedFileInfoOutcome.GetValue()->m_absolutePath; + } + + int SeedListFileTableModel::GetFileNameColumnIndex() const + { + return Column::ColumnFileName; + } + + int SeedListFileTableModel::GetTimeStampColumnIndex() const + { + return Column::ColumnFileModificationTime; + } + + int SeedListFileTableModel::columnCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : Column::Max; + } + + QVariant SeedListFileTableModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case Column::ColumnFileName: + return QString(tr("Seed List File")); + case Column::ColumnProject: + return QString(tr("Project Source")); + case Column::ColumnFileModificationTime: + return QString(tr("Modification Time")); + default: + break; + } + } + + return QVariant(); + } + + QVariant SeedListFileTableModel::data(const QModelIndex& index, int role) const + { + auto seedFileInfoOutcome = GetSeedFileInfo(index); + if (!seedFileInfoOutcome.IsSuccess()) + { + return QVariant(); + } + + int col = index.column(); + bool hasUnsavedChanges = seedFileInfoOutcome.GetValue()->m_seedListModel->HasUnsavedChanges(); + + switch (role) + { + case Qt::DisplayRole: + [[fallthrough]]; + case SortRole: + { + if (col == Column::ColumnFileName) + { + QString displayName = seedFileInfoOutcome.GetValue()->m_fileName; + if (hasUnsavedChanges) + { + displayName.append("*"); + } + return displayName; + } + else if (col == Column::ColumnProject) + { + return seedFileInfoOutcome.GetValue()->m_project; + } + else if (col == Column::ColumnFileModificationTime) + { + if (role == SortRole) + { + return seedFileInfoOutcome.GetValue()->m_fileModificationTime; + } + else + { + return seedFileInfoOutcome.GetValue()->m_fileModificationTime.toString(DateTimeFormat); + } + } + else + { + // Returning an empty QString will ensure the checkboxes do not have any text displayed next to them + return QString(); + } + } + case Qt::FontRole: + { + if (col == Column::ColumnFileName && hasUnsavedChanges) + { + QFont boldFont; + boldFont.setBold(true); + return boldFont; + } + } + case Qt::CheckStateRole: + { + if (col == Column::ColumnCheckBox) + { + if (seedFileInfoOutcome.GetValue()->m_isChecked) + { + return Qt::Checked; + } + else + { + return Qt::Unchecked; + } + } + } + default: + break; + } + + return QVariant(); + } + + bool SeedListFileTableModel::setData(const QModelIndex& index, const QVariant& value, int role) + { + if (role != Qt::CheckStateRole || index.column() != Column::ColumnCheckBox) + { + return false; + } + + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + return false; + } + + auto seedFileInfo = m_seedListFileInfoMap.find(key); + if (seedFileInfo == m_seedListFileInfoMap.end()) + { + return false; + } + + if (value == Qt::CheckState::Unchecked) + { + seedFileInfo->second->m_isChecked = false; + m_checkedSeedListFiles.erase(key); + + if (seedFileInfo->second->m_isDefaultSeedList) + { + m_seedTabWidget->UncheckSelectDefaultSeedListsCheckBox(); + } + } + else + { + seedFileInfo->second->m_isChecked = true; + m_checkedSeedListFiles.insert(key); + } + + m_seedTabWidget->SetGenerateAssetListsButtonEnabled(!m_checkedSeedListFiles.empty()); + + return true; + } + + Qt::ItemFlags SeedListFileTableModel::flags(const QModelIndex& index) const + { + if (index.column() == Column::ColumnCheckBox) + { + return Qt::ItemIsUserCheckable | QAbstractTableModel::flags(index); + } + + return QAbstractTableModel::flags(index); + } + + AZ::Outcome SeedListFileTableModel::GetSeedFileInfo(const QModelIndex& index) const + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return AZ::Failure(); + } + + if (m_seedListFileInfoMap.find(key) != m_seedListFileInfoMap.end()) + { + return AZ::Success(m_seedListFileInfoMap.at(key)); + } + else + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot find Seed File Info"); + return AZ::Failure(); + } + } + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/SeedListFileTableModel.h b/Code/Tools/AssetBundler/source/models/SeedListFileTableModel.h new file mode 100644 index 0000000000..3bd8fbd600 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/SeedListFileTableModel.h @@ -0,0 +1,134 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +#include +#include + +#include +#include + +namespace AssetBundler +{ + class SeedListTableModel; + + class SeedTabWidget; + + struct SeedListFileInfo + { + /** + * Stores information about a Seed List File on disk. + * + * @param absolutePath The absolute path of the Seed List File + * @param fileName The name of the Seed List File. This does not include the ".seed" file extension + * @param project The area of the codebase the Seed List File is from (ex: ProjectName, Engine, Gem) + * @param loadFromFile Set to True if you wish to load an existing Seed List File into memory. Set to False if you are creating a new Seed List File. + */ + SeedListFileInfo( + const AZStd::string& absolutePath, + const QString& fileName, + const QString& project, + bool loadFromFile, + bool isDefaultSeedList = false, + const AZStd::vector& defaultSeeds = AZStd::vector(), + const AzFramework::PlatformFlags& platforms = AzFramework::PlatformFlags::Platform_NONE); + + bool SaveSeedFile(); + + bool HasUnsavedChanges(); + + AZStd::string m_absolutePath; + bool m_isChecked = false; + bool m_isDefaultSeedList = false; + QString m_fileName; + QString m_project; + QDateTime m_fileModificationTime; + + QSharedPointer m_seedListModel; + }; + + using SeedListFileInfoPtr = AZStd::shared_ptr; + /// Stores SeedListFileInfo, using the absolute path (without the drive letter) of the Seed List file as the key + using SeedListFileInfoMap = AZStd::unordered_map; + + class SeedListFileTableModel + : public AssetBundlerAbstractFileTableModel + { + + public: + explicit SeedListFileTableModel(SeedTabWidget* parentSeedTabWidget); + virtual ~SeedListFileTableModel(); + + void AddDefaultSeedsToInMemoryList(const AZStd::vector& defaultSeeds, const char* projectName, const AzFramework::PlatformFlags& platforms); + + AZStd::vector CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms, const QString& project) override; + + bool DeleteFile(const QModelIndex& index) override; + + void Reload(const char* fileExtension, const QSet& watchedFolders, const QSet& watchedFiles = QSet(), const AZStd::unordered_map& pathToProjectNameMap = AZStd::unordered_map()) override; + + void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) override; + + void SelectDefaultSeedLists(bool setSelected); + + AZStd::vector GenerateAssetLists(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms); + + QSharedPointer GetSeedListFileContents(const QModelIndex& index); + + bool SetSeedPlatforms(const QModelIndex& seedFileIndex, const QModelIndex& seedIndex, const AzFramework::PlatformFlags& platforms); + + bool AddSeed(const QModelIndex& seedFileIndex, const AZStd::string& seedRelativePath, const AzFramework::PlatformFlags& platforms); + + bool RemoveSeed(const QModelIndex& seedFileIndex, const QModelIndex& seedIndex); + + bool WriteToDisk(const AZStd::string& key) override; + + AZStd::string GetFileAbsolutePath(const QModelIndex& index) const override; + + int GetFileNameColumnIndex() const override; + + int GetTimeStampColumnIndex() const override; + + ////////////////////////////////////////////////////////////////////////// + // QAbstractListModel overrides + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::CheckStateRole) override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + ////////////////////////////////////////////////////////////////////////// + + enum Column + { + ColumnCheckBox, + ColumnFileName, + ColumnProject, + ColumnFileModificationTime, + Max + }; + + private: + AZ::Outcome GetSeedFileInfo(const QModelIndex& index) const; + + SeedListFileInfoMap m_seedListFileInfoMap; + AZStd::unordered_set m_checkedSeedListFiles; + + AZStd::string m_inMemoryDefaultSeedListKey = "InMemoryDefaultKey"; + SeedListFileInfoPtr m_inMemoryDefaultSeedList; + + SeedTabWidget* m_seedTabWidget = nullptr; + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/SeedListTableModel.cpp b/Code/Tools/AssetBundler/source/models/SeedListTableModel.cpp new file mode 100644 index 0000000000..fc04686436 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/SeedListTableModel.cpp @@ -0,0 +1,270 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +namespace AssetBundler +{ + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // AdditionalSeedInfo + ////////////////////////////////////////////////////////////////////////////////////////////////// + AdditionalSeedInfo::AdditionalSeedInfo(const QString& relativePath, const QString& platformList) + : m_relativePath(relativePath) + , m_platformList(platformList) + { + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // SeedListTableModel + ////////////////////////////////////////////////////////////////////////////////////////////////// + SeedListTableModel::SeedListTableModel(QObject* parent, const AZStd::string& absolutePath, const AZStd::vector& defaultSeeds, const AzFramework::PlatformFlags& platforms) + : QAbstractTableModel(parent) + { + m_seedListManager.reset(new AzToolsFramework::AssetSeedManager()); + + if (absolutePath.empty() && defaultSeeds.empty()) + { + return; + } + + if (!defaultSeeds.empty()) + { + for (const AZStd::string& seed : defaultSeeds) + { + m_seedListManager->AddSeedAssetForValidPlatforms(seed, platforms); + } + + m_isFileOnDisk = false; + } + else + { + m_seedListManager->Load(absolutePath); + } + + AZ::Data::AssetInfo assetInfo; + QString platformList; + for (const auto& seed : m_seedListManager->GetAssetSeedList()) + { + assetInfo = AzToolsFramework::AssetSeedManager::GetAssetInfoById(seed.m_assetId, AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(seed.m_platformFlags)[0], absolutePath); + platformList = QString(m_seedListManager->GetReadablePlatformList(seed).c_str()); + + m_additionalSeedInfoMap[seed.m_assetId].reset(new AdditionalSeedInfo(assetInfo.m_relativePath.c_str(), platformList)); + } + } + + AZ::Outcome SeedListTableModel::GetSeedPlatforms(const QModelIndex& index) const + { + auto seedOutcome = GetSeedInfo(index); + if (!seedOutcome.IsSuccess()) + { + // Error has already been thrown + return AZ::Failure(); + } + + return AZ::Success(seedOutcome.GetValue().m_platformFlags); + } + + bool SeedListTableModel::Save(const AZStd::string& absolutePath) + { + if (!HasUnsavedChanges()) + { + // There are no changes, so there is nothing to save + return true; + } + + SetHasUnsavedChanges(!m_seedListManager->Save(absolutePath)); + return !HasUnsavedChanges(); + } + + bool SeedListTableModel::SetSeedPlatforms(const QModelIndex& index, const AzFramework::PlatformFlags& platforms) + { + auto seedOutcome = GetSeedInfo(index); + if (!seedOutcome.IsSuccess()) + { + // Error has already been thrown + return false; + } + + if (platforms == AzFramework::PlatformFlags::Platform_NONE) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot Edit Platforms: No platforms were selected"); + return false; + } + + auto setPlatformOutcome = m_seedListManager->SetSeedPlatformFlags(index.row(), platforms); + if (!setPlatformOutcome.IsSuccess()) + { + AZ_Error(AssetBundler::AppWindowName, false, setPlatformOutcome.GetError().c_str()); + return false; + } + + // Update the cached display info + auto additionalSeedInfo = m_additionalSeedInfoMap.find(seedOutcome.GetValue().m_assetId); + if (additionalSeedInfo == m_additionalSeedInfoMap.end()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to find additional Seed info"); + return false; + } + additionalSeedInfo->second->m_platformList = QString(AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(platforms).c_str()); + + SetHasUnsavedChanges(true); + + // Update the display + QModelIndex firstChangedIndex = QAbstractTableModel::index(index.row(), Column::ColumnRelativePath); + QModelIndex lastChangedIndex = QAbstractTableModel::index(index.row(), Column::Max - 1); + emit dataChanged(firstChangedIndex, lastChangedIndex, { Qt::DisplayRole }); + + return true; + } + + bool SeedListTableModel::AddSeed(const AZStd::string& seedRelativePath, const AzFramework::PlatformFlags& platforms) + { + AZStd::pair addSeedsResult = m_seedListManager->AddSeedAssetForValidPlatforms(seedRelativePath, platforms); + + if (!addSeedsResult.first.IsValid() || addSeedsResult.second == AzFramework::PlatformFlags::Platform_NONE) + { + // Error has already been thrown + return false; + } + + QString platformList = QString(AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(addSeedsResult.second).c_str()); + + int lastRowIndex = AZStd::max(rowCount() - 1, 0); + beginInsertRows(QModelIndex(), lastRowIndex, lastRowIndex); + + m_additionalSeedInfoMap[addSeedsResult.first].reset(new AdditionalSeedInfo(QString(seedRelativePath.c_str()), platformList)); + + endInsertRows(); + + SetHasUnsavedChanges(true); + return true; + } + + bool SeedListTableModel::RemoveSeed(const QModelIndex& seedIndex) + { + auto seedOutcome = GetSeedInfo(seedIndex); + if (!seedOutcome.IsSuccess()) + { + // Error has already been thrown + return false; + } + + int row = seedIndex.row(); + beginRemoveRows(QModelIndex(), row, row); + m_seedListManager->RemoveSeedAsset(seedOutcome.GetValue().m_assetId, seedOutcome.GetValue().m_platformFlags); + m_additionalSeedInfoMap.erase(seedOutcome.GetValue().m_assetId); + endRemoveRows(); + + SetHasUnsavedChanges(true); + return true; + } + + int SeedListTableModel::rowCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : static_cast(m_additionalSeedInfoMap.size()); + } + + int SeedListTableModel::columnCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : Column::Max; + } + + QVariant SeedListTableModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case Column::ColumnRelativePath: + return QString("Seed"); + case Column::ColumnPlatformList: + return QString("Platforms"); + default: + break; + } + } + + return QVariant(); + } + + QVariant SeedListTableModel::data(const QModelIndex& index, int role) const + { + auto additionalSeedInfoOutcome = GetAdditionalSeedInfo(index); + if (!additionalSeedInfoOutcome.IsSuccess()) + { + return QVariant(); + } + + switch (role) + { + case Qt::DisplayRole: + { + if (index.column() == Column::ColumnRelativePath) + { + return additionalSeedInfoOutcome.GetValue()->m_relativePath; + } + else if (index.column() == Column::ColumnPlatformList) + { + return additionalSeedInfoOutcome.GetValue()->m_platformList; + } + } + default: + break; + } + + return QVariant(); + } + + AZ::Outcome SeedListTableModel::GetSeedInfo(const QModelIndex& index) const + { + int row = index.row(); + int col = index.column(); + if (row >= rowCount() || row < 0 || col >= columnCount() || col < 0) + { + AZ_Error(AssetBundler::AppWindowName, false, "Selected index (%i, %i) is out of range", row, col); + return AZ::Failure(); + } + + return AZ::Success(m_seedListManager->GetAssetSeedList().at(row)); + } + + AZ::Outcome SeedListTableModel::GetAdditionalSeedInfo(const QModelIndex& index) const + { + auto seedInfoOutcome = GetSeedInfo(index); + if (!seedInfoOutcome.IsSuccess()) + { + // Error has already been thrown + return AZ::Failure(); + } + + auto additionalSeedInfoIt = m_additionalSeedInfoMap.find(seedInfoOutcome.GetValue().m_assetId); + if (additionalSeedInfoIt == m_additionalSeedInfoMap.end()) + { + return AZ::Failure(); + } + + return AZ::Success(additionalSeedInfoIt->second); + } + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/SeedListTableModel.h b/Code/Tools/AssetBundler/source/models/SeedListTableModel.h new file mode 100644 index 0000000000..b8cbe95201 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/SeedListTableModel.h @@ -0,0 +1,84 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +#include +#include + +#include + +namespace AssetBundler +{ + struct AdditionalSeedInfo + { + AdditionalSeedInfo(const QString& relativePath, const QString& platformList); + + QString m_relativePath; + QString m_platformList; + }; + + using AdditionalSeedInfoPtr = AZStd::shared_ptr; + using AdditionalSeedInfoMap = AZStd::unordered_map; + + class SeedListTableModel + : public QAbstractTableModel + { + public: + explicit SeedListTableModel(QObject* parent = nullptr, const AZStd::string& absolutePath = AZStd::string(), const AZStd::vector& defaultSeeds = AZStd::vector(), const AzFramework::PlatformFlags& platforms = AzFramework::PlatformFlags::Platform_NONE); + virtual ~SeedListTableModel() {} + + AZStd::shared_ptr GetSeedListManager() { return m_seedListManager; } + + bool HasUnsavedChanges() { return m_hasUnsavedChanges && m_isFileOnDisk; } + + void SetHasUnsavedChanges(bool hasUnsavedChanges) { m_hasUnsavedChanges = hasUnsavedChanges; } + + bool Save(const AZStd::string& absolutePath); + + AZ::Outcome GetSeedPlatforms(const QModelIndex& index) const; + + bool SetSeedPlatforms(const QModelIndex& index, const AzFramework::PlatformFlags& platforms); + + bool AddSeed(const AZStd::string& seedRelativePath, const AzFramework::PlatformFlags& platforms); + + bool RemoveSeed(const QModelIndex& seedIndex); + + ////////////////////////////////////////////////////////////////////////// + // QAbstractListModel overrides + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; + ////////////////////////////////////////////////////////////////////////// + + enum Column + { + ColumnRelativePath, + ColumnPlatformList, + Max + }; + + private: + AZ::Outcome GetSeedInfo(const QModelIndex& index) const; + + AZ::Outcome GetAdditionalSeedInfo(const QModelIndex& index) const; + + AZStd::shared_ptr m_seedListManager; + AdditionalSeedInfoMap m_additionalSeedInfoMap; + + bool m_hasUnsavedChanges = false; + bool m_isFileOnDisk = true; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/AddSeedDialog.cpp b/Code/Tools/AssetBundler/source/ui/AddSeedDialog.cpp new file mode 100644 index 0000000000..be156efde2 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AddSeedDialog.cpp @@ -0,0 +1,96 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include + +#include +#include + +const char QtRelativePathPrefix[] = "../"; + +namespace AssetBundler +{ + AddSeedDialog::AddSeedDialog(QWidget* parent, const AzFramework::PlatformFlags& enabledPlatforms, const AZStd::string& platformSpecificCachePath) + : QDialog(parent) + , m_platformSpecificCachePath(platformSpecificCachePath.c_str()) + { + m_ui.reset(new Ui::AddSeedDialog); + m_ui->setupUi(this); + + // Set up Browse File button + m_ui->fileNameLineEdit->setReadOnly(true); + connect(m_ui->browseFileButton, &QPushButton::clicked, this, &AddSeedDialog::OnBrowseFileButtonPressed); + + // Set up Platform selection + m_ui->platformSelectionWidget->Init(enabledPlatforms); + connect(m_ui->platformSelectionWidget, &PlatformSelectionWidget::PlatformsSelected, this, &AddSeedDialog::OnPlatformSelectionChanged); + + // Set up Cancel and Create New File buttons + m_ui->addSeedButton->setEnabled(false); + connect(m_ui->cancelButton, &QPushButton::clicked, this, &QDialog::reject); + connect(m_ui->addSeedButton, &QPushButton::clicked, this, &QDialog::accept); + } + + AZStd::string AddSeedDialog::GetFileName() + { + return m_fileName; + } + + AzFramework::PlatformFlags AddSeedDialog::GetPlatformFlags() + { + return m_ui->platformSelectionWidget->GetSelectedPlatforms(); + } + + void AddSeedDialog::OnBrowseFileButtonPressed() + { + QString seedAbsolutePath = QFileDialog::getOpenFileName(this, tr("Add New Seed"), m_platformSpecificCachePath); + m_fileNameIsValid = !seedAbsolutePath.isEmpty(); + if (!m_fileNameIsValid) + { + // The user canceled out of the window, do not update anything + return; + } + + // Make sure the path is relative to the platform-specific cache + QDir platformSpecificCacheDir(m_platformSpecificCachePath); + QString seedRelativePath = platformSpecificCacheDir.relativeFilePath(seedAbsolutePath); + + // trim off the "../" from the relative path + FormatRelativePathString(seedRelativePath); + m_fileName = seedRelativePath.toUtf8().data(); + + // Update the ui + m_ui->fileNameLineEdit->setText(seedRelativePath); + m_ui->addSeedButton->setEnabled(m_platformIsValid && m_fileNameIsValid); + } + + void AddSeedDialog::OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms) + { + // Hide the "Create File" button if no platforms are selected + m_platformIsValid = selectedPlatforms != AzFramework::PlatformFlags::Platform_NONE; + m_ui->addSeedButton->setEnabled(m_platformIsValid && m_fileNameIsValid); + } + + void AddSeedDialog::FormatRelativePathString(QString& relativePath) + { + if (relativePath.startsWith(QtRelativePathPrefix)) + { + relativePath.remove(0, static_cast(strlen(QtRelativePathPrefix))); + } + } + +} //namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/AddSeedDialog.h b/Code/Tools/AssetBundler/source/ui/AddSeedDialog.h new file mode 100644 index 0000000000..fed6b031d1 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AddSeedDialog.h @@ -0,0 +1,58 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include + +#include +#include +#endif + +namespace Ui +{ + class AddSeedDialog; +} + +namespace AssetBundler +{ + class GUIApplicationManager; + + class AddSeedDialog + : public QDialog + { + Q_OBJECT + + public: + explicit AddSeedDialog(QWidget* parent, const AzFramework::PlatformFlags& enabledPlatforms, const AZStd::string& platformSpecificCachePath); + virtual ~AddSeedDialog() {} + + AZStd::string GetFileName(); + AzFramework::PlatformFlags GetPlatformFlags(); + + private: + void OnBrowseFileButtonPressed(); + void OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms); + + void FormatRelativePathString(QString& relativePath); + + QSharedPointer m_ui; + QString m_platformSpecificCachePath; + bool m_isAddSeedDialog = false; + + AZStd::string m_fileName; + + bool m_fileNameIsValid = false; + bool m_platformIsValid = false; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/AddSeedDialog.ui b/Code/Tools/AssetBundler/source/ui/AddSeedDialog.ui new file mode 100644 index 0000000000..e3c0f471aa --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AddSeedDialog.ui @@ -0,0 +1,185 @@ + + + AddSeedDialog + + + Qt::ApplicationModal + + + + 0 + 0 + 450 + 108 + + + + + 0 + 0 + + + + + 450 + 0 + + + + Add Seed Asset + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Select Seed Asset: + + + + + + + + + true + + + + + + + Browse... + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + + + + + + + + + + + + + 10 + + + 10 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + false + + + + + + + Add Seed + + + true + + + + + + + + + + AssetBundler::PlatformSelectionWidget + QWidget +
source/ui/PlatformSelectionWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/AssetBundlerTabWidget.cpp b/Code/Tools/AssetBundler/source/ui/AssetBundlerTabWidget.cpp new file mode 100644 index 0000000000..2719944af4 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AssetBundlerTabWidget.cpp @@ -0,0 +1,370 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AssetBundler +{ + const char AssetBundlerCommonSettingsFile[] = "AssetBundlerCommonSettings.json"; + const char AssetBundlerUserSettingsFile[] = "AssetBundlerUserSettings.json"; + + const char ScanPathsKey[] = "ScanPaths"; + + const QString AssetBundlingFileTypes[] = + { + "SeedLists", + "AssetLists", + "BundleSettings", + "Bundles", + "Rules" + }; + + const int MarginSize = 10; + + AssetBundlerTabWidget::AssetBundlerTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager) + : QWidget(parent) + , m_guiApplicationManager(guiApplicationManager) + { + connect(m_guiApplicationManager, &GUIApplicationManager::UpdateTab, this, &AssetBundlerTabWidget::OnUpdateTab); + connect(m_guiApplicationManager, &GUIApplicationManager::UpdateFiles, this, &AssetBundlerTabWidget::OnUpdateFiles); + + QAction* deleteFileAction = new QAction(tr("Delete"), this); + addAction(deleteFileAction); + deleteFileAction->setShortcut(QKeySequence::Delete); + connect(deleteFileAction, &QAction::triggered, this, &AssetBundlerTabWidget::OnDeleteSelectedFileRequested); + } + + AssetBundlerTabWidget::~AssetBundlerTabWidget() + { + m_guiApplicationManager = nullptr; + } + + void AssetBundlerTabWidget::Activate() + { + SetActiveProjectLabel(tr("Active Project: %1").arg(m_guiApplicationManager->GetCurrentProjectName().c_str())); + + SetupContextMenu(); + Reload(); + + connect(GetFileTableView()->header(), &QHeaderView::sortIndicatorChanged, m_fileTableFilterModel.get(), &AssetBundlerFileTableFilterModel::sort); + GetFileTableView()->header()->setSortIndicatorShown(true); + // Setting this in descending order will ensure the most recent files are at the top + GetFileTableView()->header()->setSortIndicator(GetFileTableModel()->GetTimeStampColumnIndex(), Qt::DescendingOrder); + GetFileTableView()->setSortingEnabled(true); + } + + void AssetBundlerTabWidget::InitAssetBundlerSettings(const char* currentProjectFolderPath) + { + AZStd::string commonSettingsPath = GetAssetBundlerCommonSettingsFile(currentProjectFolderPath); + if (!AZ::IO::FileIOBase::GetInstance()->Exists(commonSettingsPath.c_str())) + { + CreateEmptyAssetBundlerSettings(commonSettingsPath); + } + + AZStd::string userSettingsPath = GetAssetBundlerUserSettingsFile(currentProjectFolderPath); + if (!AZ::IO::FileIOBase::GetInstance()->Exists(userSettingsPath.c_str())) + { + CreateEmptyAssetBundlerSettings(userSettingsPath); + } + } + + void AssetBundlerTabWidget::OnFileTableContextMenuRequested(const QPoint& pos) + { + AZStd::string selectedFileAbsolutePath(GetFileTableModel()->GetFileAbsolutePath(GetSelectedFileTableIndex())); + + QMenu* contextMenu = new QMenu(this); + contextMenu->setToolTipsVisible(true); + + bool arePathOperationsEnabled = !selectedFileAbsolutePath.empty(); + QString emptyPathToolTip(tr("This file is not present on-disk.")); + + QAction* action = contextMenu->addAction(AzQtComponents::fileBrowserActionName(), [=]() + { + AzQtComponents::ShowFileOnDesktop(selectedFileAbsolutePath.c_str()); + }); + if (arePathOperationsEnabled) + { + action->setToolTip(tr("Shows the location of this file on your computer")); + } + else + { + action->setToolTip(emptyPathToolTip); + action->setEnabled(false); + } + + action = contextMenu->addAction(tr("Copy Path to Clipboard"), [=]() + { + QApplication::clipboard()->setText(QString(selectedFileAbsolutePath.c_str())); + }); + if (arePathOperationsEnabled) + { + action->setToolTip(tr("Copies the absolute path of this file to your Clipboard")); + } + else + { + action->setToolTip(emptyPathToolTip); + action->setEnabled(false); + } + + contextMenu->addSeparator(); + + // We can't use the same Delete action as the constructor because we need to modify a lot of values + action = new QAction(tr("Delete"), this); + action->setShortcutContext(Qt::WidgetWithChildrenShortcut); + action->setShortcut(QKeySequence::Delete); + connect(action, &QAction::triggered, this, &AssetBundlerTabWidget::OnDeleteSelectedFileRequested); + if (arePathOperationsEnabled) + { + action->setToolTip(tr("Deletes the selected file from disk.")); + } + else + { + action->setToolTip(emptyPathToolTip); + action->setEnabled(false); + } + contextMenu->addAction(action); + + contextMenu->exec(GetFileTableView()->mapToGlobal(pos)); + delete contextMenu; + } + + void AssetBundlerTabWidget::OnDeleteSelectedFileRequested() + { + AZStd::string selectedFileAbsolutePath(GetFileTableModel()->GetFileAbsolutePath(GetSelectedFileTableIndex())); + if (selectedFileAbsolutePath.empty()) + { + return; + } + + QString messageBoxText = QString(tr("Are you sure you would like to delete %1? \n\nThis will permanently delete the file.")).arg(QString(selectedFileAbsolutePath.c_str())); + + QMessageBox::StandardButton confirmDeleteFileResult = QMessageBox::question(this, QString(tr("Delete %1")).arg(GetFileTypeDisplayName()), messageBoxText); + if (confirmDeleteFileResult != QMessageBox::StandardButton::Yes) + { + // User canceled out of the confirmation dialog + return; + } + + if (GetFileTableModel()->DeleteFile(GetSelectedFileTableIndex())) + { + RemoveScanPathFromAssetBundlerSettings(GetFileType(), selectedFileAbsolutePath.c_str()); + } + } + + void AssetBundlerTabWidget::ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType fileType) + { + AZStd::string currentProjectFolderPath = m_guiApplicationManager->GetCurrentProjectFolder(); + ReadAssetBundlerSettings(GetAssetBundlerUserSettingsFile(currentProjectFolderPath.c_str()), fileType); + ReadAssetBundlerSettings(GetAssetBundlerCommonSettingsFile(currentProjectFolderPath.c_str()), fileType); + } + + void AssetBundlerTabWidget::AddScanPathToAssetBundlerSettings(AssetBundlingFileType fileType, AZStd::string filePath) + { + AZStd::string defaultFolderPath; + switch (fileType) + { + case AssetBundlingFileType::SeedListFileType: + defaultFolderPath = m_guiApplicationManager->GetSeedListsFolder(); + break; + case AssetBundlingFileType::AssetListFileType: + defaultFolderPath = m_guiApplicationManager->GetAssetListsFolder(); + break; + case AssetBundlingFileType::RulesFileType: + defaultFolderPath = m_guiApplicationManager->GetRulesFolder(); + break; + case AssetBundlingFileType::BundleSettingsFileType: + defaultFolderPath = m_guiApplicationManager->GetBundleSettingsFolder(); + break; + case AssetBundlingFileType::BundleFileType: + defaultFolderPath = m_guiApplicationManager->GetBundlesFolder(); + break; + default: + AZ_Warning(AssetBundler::AppWindowName, false, "No default folder is defined for AssetBundlingFileType ( %i ).", static_cast(fileType)); + break; + } + + AzFramework::StringFunc::Path::Normalize(filePath); + AzFramework::StringFunc::Path::Normalize(defaultFolderPath); + + if (AzFramework::StringFunc::StartsWith(filePath, defaultFolderPath)) + { + // file is already in a watched folder, no need to add it to the settings file + return; + } + + AddScanPathToAssetBundlerSettings(fileType, QString(filePath.c_str())); + } + + void AssetBundlerTabWidget::AddScanPathToAssetBundlerSettings(AssetBundlingFileType fileType, const QString& filePath) + { + AZStd::string assetBundlerSettingsFileAbsolutePath = GetAssetBundlerUserSettingsFile(m_guiApplicationManager->GetCurrentProjectFolder().c_str()); + QJsonObject assetBundlerSettings = AssetBundler::ReadJson(assetBundlerSettingsFileAbsolutePath); + QJsonObject scanPathsSettings = assetBundlerSettings[ScanPathsKey].toObject(); + QJsonArray scanPaths = scanPathsSettings[AssetBundlingFileTypes[fileType]].toArray(); + + QFileInfo inputFileInfo(filePath); + + for (const QJsonValue scanPath : m_watchedFiles + m_watchedFolders) + { + AZStd::string scanFilePathStr = scanPath.toString().toUtf8().data(); + AzFramework::StringFunc::Path::ConstructFull(GetCachedEngineRoot().c_str(), scanFilePathStr.c_str(), scanFilePathStr); + + // Check whether the file has already been watched + // Get absolute file paths via QFileInfo to keep consistency in the letter case + if (inputFileInfo.absoluteFilePath().startsWith( + QFileInfo(scanFilePathStr.c_str()).absoluteFilePath())) + { + return; + } + } + + scanPaths.push_back(filePath); + scanPathsSettings[AssetBundlingFileTypes[fileType]] = scanPaths; + assetBundlerSettings[ScanPathsKey] = scanPathsSettings; + AssetBundler::SaveJson(assetBundlerSettingsFileAbsolutePath, assetBundlerSettings); + + m_watchedFiles.insert(filePath); + m_guiApplicationManager->AddWatchedPath(filePath); + } + + void AssetBundlerTabWidget::RemoveScanPathFromAssetBundlerSettings(AssetBundlingFileType fileType, const QString& filePath) + { + AZStd::string assetBundlerSettingsFileAbsolutePath = GetAssetBundlerUserSettingsFile(m_guiApplicationManager->GetCurrentProjectFolder().c_str()); + QJsonObject assetBundlerSettings = AssetBundler::ReadJson(assetBundlerSettingsFileAbsolutePath); + QJsonObject scanPathsSettings = assetBundlerSettings[ScanPathsKey].toObject(); + QJsonArray scanPaths = scanPathsSettings[AssetBundlingFileTypes[fileType]].toArray(); + + for (auto itr = scanPaths.begin(); itr != scanPaths.end(); ++itr) + { + QJsonValueRef scanPathValueRef = *itr; + AZStd::string scanPath = scanPathValueRef.toString().toUtf8().data(); + AzFramework::StringFunc::Path::ConstructFull(GetCachedEngineRoot().c_str(), scanPath.c_str(), scanPath); + + // Check whether the file is being watched + // Get absolute file paths via QFileInfo to keep consistency in the letter case + if (QFileInfo(filePath).absoluteFilePath() == QFileInfo(scanPath.c_str()).absoluteFilePath()) + { + itr = scanPaths.erase(itr); + break; + } + } + + scanPathsSettings[AssetBundlingFileTypes[fileType]] = scanPaths; + assetBundlerSettings[ScanPathsKey] = scanPathsSettings; + AssetBundler::SaveJson(assetBundlerSettingsFileAbsolutePath, assetBundlerSettings); + + m_guiApplicationManager->RemoveWatchedPath(filePath); + } + + void AssetBundlerTabWidget::OnUpdateTab(const AZStd::string& path) + { + if (m_watchedFolders.contains(path.c_str()) || + m_watchedFiles.contains(path.c_str())) + { + Reload(); + } + } + + void AssetBundlerTabWidget::OnUpdateFiles(AssetBundlingFileType fileType, const AZStd::vector& absoluteFilePaths) + { + if (fileType == GetFileType()) + { + GetFileTableModel()->ReloadFiles(absoluteFilePaths, m_filePathToGemNameMap); + m_fileTableFilterModel->sort(m_fileTableFilterModel->sortColumn(), m_fileTableFilterModel->sortOrder()); + FileSelectionChanged(); + } + } + + void AssetBundlerTabWidget::SetupContextMenu() + { + GetFileTableView()->setContextMenuPolicy(Qt::CustomContextMenu); + connect(GetFileTableView(), &QTreeView::customContextMenuRequested, this, &AssetBundlerTabWidget::OnFileTableContextMenuRequested); + } + + void AssetBundlerTabWidget::ReadAssetBundlerSettings(const AZStd::string& filePath, AssetBundlingFileType fileType) + { + // Read the config file which contains the customized scan paths information + AZStd::vector assetBundlerSettingsFileList; + QJsonObject assetBundlerSettings = AssetBundler::ReadJson(filePath); + QJsonObject scanPaths = assetBundlerSettings.find(ScanPathsKey).value().toObject(); + + for (const QJsonValue scanPath : scanPaths[AssetBundlingFileTypes[fileType]].toArray()) + { + AZStd::string absoluteScanPath = scanPath.toString().toUtf8().data(); + AZStd::replace(absoluteScanPath.begin(), absoluteScanPath.end(), AZ_WRONG_FILESYSTEM_SEPARATOR, AZ_CORRECT_FILESYSTEM_SEPARATOR); + + if (AzFramework::StringFunc::Path::IsRelative(absoluteScanPath.c_str())) + { + AzFramework::StringFunc::Path::ConstructFull(GetCachedEngineRoot().c_str(), absoluteScanPath.c_str(), absoluteScanPath); + } + + if (AZ::IO::FileIOBase::GetInstance()->IsDirectory(absoluteScanPath.c_str())) + { + // The path specified in the config file is a directory + m_watchedFolders.insert(absoluteScanPath.c_str()); + } + else if (AZ::IO::FileIOBase::GetInstance()->Exists(absoluteScanPath.c_str())) + { + // The path specified in the config file is a file + m_watchedFiles.insert(absoluteScanPath.c_str()); + } + } + } + + AZStd::string AssetBundlerTabWidget::GetAssetBundlerUserSettingsFile(const char* currentProjectFolderPath) + { + AZStd::string absoluteFilePath; + AzFramework::StringFunc::Path::ConstructFull(currentProjectFolderPath, AssetBundlerUserSettingsFile, absoluteFilePath); + return absoluteFilePath; + } + + AZStd::string AssetBundlerTabWidget::GetAssetBundlerCommonSettingsFile(const char* currentProjectFolderPath) + { + AZStd::string absoluteFilePath; + AzFramework::StringFunc::Path::ConstructFull(currentProjectFolderPath, AssetBundlerCommonSettingsFile, absoluteFilePath); + return absoluteFilePath; + } + + void AssetBundlerTabWidget::CreateEmptyAssetBundlerSettings(const AZStd::string& filePath) + { + QJsonObject assetBundlerSettings; + QJsonObject scanPathSettings; + + for (const auto& fileType : AssetBundlingFileTypes) + { + scanPathSettings.insert(fileType, QJsonArray()); + } + + assetBundlerSettings.insert(ScanPathsKey, scanPathSettings); + + AssetBundler::SaveJson(filePath, assetBundlerSettings); + } + +} // namespace AssetBundler +#include diff --git a/Code/Tools/AssetBundler/source/ui/AssetBundlerTabWidget.h b/Code/Tools/AssetBundler/source/ui/AssetBundlerTabWidget.h new file mode 100644 index 0000000000..edef5c0437 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AssetBundlerTabWidget.h @@ -0,0 +1,118 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#endif + +namespace AssetBundler +{ + // Keys for the corresponding scan path lists in the asset bundling settings file + extern const QString AssetBundlingFileTypes[]; + + extern const int MarginSize; + + class AssetBundlerTabWidget + : public QWidget + { + Q_OBJECT + + public: + explicit AssetBundlerTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager); + virtual ~AssetBundlerTabWidget(); + + void Activate(); + + virtual QString GetTabTitle() = 0; + + virtual QString GetFileTypeDisplayName() = 0; + + virtual AssetBundlingFileType GetFileType() = 0; + + virtual bool HasUnsavedChanges() = 0; + + //! Reload all the files on display. + virtual void Reload() = 0; + + //! Saves the selected file to disk. + //! @return true on successful save, or throws an error message and returns false on a failed save. + virtual bool SaveCurrentSelection() = 0; + + //! Saves all modified files to disk. + //! @return true on successful save, or throws an error message and returns false on a failed save. + virtual bool SaveAll() = 0; + + //! Set watched folders and files for the model + virtual void SetModelDataSource() = 0; + + virtual AzQtComponents::TableView* GetFileTableView() = 0; + + virtual QModelIndex GetSelectedFileTableIndex() = 0; + + virtual AssetBundlerAbstractFileTableModel* GetFileTableModel() = 0; + + virtual void SetActiveProjectLabel(const QString& labelText) = 0; + + virtual void ApplyConfig() = 0; + + virtual void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) = 0; + + static void InitAssetBundlerSettings(const char* currentProjectFolderPath); + + void AddScanPathToAssetBundlerSettings(AssetBundlingFileType fileType, AZStd::string filePath); + + GUIApplicationManager* GetGUIApplicationManager() { return m_guiApplicationManager; } + + protected: + void OnFileTableContextMenuRequested(const QPoint& pos); + //! Asks the user to confirm they wish to permanently delete the selected file, then removes it from disk and memory. + void OnDeleteSelectedFileRequested(); + bool ConfirmFileDeleteDialog(const QString& absoluteFilePath); + void ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType fileType); + void RemoveScanPathFromAssetBundlerSettings(AssetBundlingFileType fileType, const QString& filePath); + + GUIApplicationManager* m_guiApplicationManager = nullptr; + QScopedPointer m_fileTableFilterModel; + + QSet m_watchedFolders; + QSet m_watchedFiles; + AZStd::unordered_map m_filePathToGemNameMap; + + private slots: + void OnUpdateTab(const AZStd::string& path); + void OnUpdateFiles(AssetBundlingFileType fileType, const AZStd::vector& absoluteFilePaths); + + private: + void SetupContextMenu(); + void AddScanPathToAssetBundlerSettings(AssetBundlingFileType fileType, const QString& filePath); + void ReadAssetBundlerSettings(const AZStd::string& filePath, AssetBundlingFileType fileType); + + static AZStd::string GetAssetBundlerUserSettingsFile(const char* currentProjectFolderPath); + static AZStd::string GetAssetBundlerCommonSettingsFile(const char* currentProjectFolderPath); + static void CreateEmptyAssetBundlerSettings(const AZStd::string& filePath); + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.cpp b/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.cpp new file mode 100644 index 0000000000..339dc080fa --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.cpp @@ -0,0 +1,182 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace AssetBundler +{ + AssetListTabWidget::AssetListTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager) + : AssetBundlerTabWidget(parent, guiApplicationManager) + , m_fileTableModel(new AssetListFileTableModel()) + , m_assetListContentsModel(new AssetListTableModel()) + { + m_ui.reset(new Ui::AssetListTabWidget); + m_ui->setupUi(this); + + m_ui->mainVerticalLayout->setContentsMargins(10, 10, 10, 10); + + // File view of all Asset List Files + m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(this, m_fileTableModel->GetFileNameColumnIndex(), m_fileTableModel->GetTimeStampColumnIndex())); + + m_fileTableFilterModel->setSourceModel(m_fileTableModel.data()); + m_ui->assetListsTable->setModel(m_fileTableFilterModel.data()); + connect(m_ui->fileFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, + m_fileTableFilterModel.data(), static_cast(&AssetBundlerFileTableFilterModel::FilterChanged)); + + connect(m_ui->assetListsTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &AssetListTabWidget::FileSelectionChanged); + + m_ui->fileTableHeaderLayout->setContentsMargins(0, 0, 0, 0); + m_ui->fileTableVerticalLayout->setContentsMargins(0, 0, 0, 0); + m_ui->assetListsTable->setIndentation(0); + + // Generate Bundle Button + m_ui->generateBundleButton->setDefault(true); + m_ui->generateBundleButton->setEnabled(false); + connect(m_ui->generateBundleButton, &QPushButton::clicked, this, &AssetListTabWidget::OnGenerateBundleButtonPressed); + + // Absolute path of selected Asset List file + m_ui->assetListFileAbsolutePathLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); + + // Table that displays the contents of an Asset List File + m_assetListContentsFilterModel.reset(new AssetBundlerFileTableFilterModel(this, AssetListTableModel::Column::ColumnAssetName)); + + m_assetListContentsFilterModel->setSourceModel(m_assetListContentsModel.data()); + m_ui->assetListContentsTable->setModel(m_assetListContentsFilterModel.data()); + connect(m_ui->assetListContentsFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, + m_assetListContentsFilterModel.data(), static_cast(&AssetBundlerFileTableFilterModel::FilterChanged)); + + + m_ui->fileContentsHeaderLayout->setContentsMargins(0, 0, 0, 0); + m_ui->fileContentsVerticalLayout->setContentsMargins(0, 0, 0, 0); + m_ui->assetListContentsTable->setIndentation(0); + + SetModelDataSource(); + } + + void AssetListTabWidget::SetModelDataSource() + { + // Remove the current watched folders and files + m_guiApplicationManager->RemoveWatchedPaths(m_watchedFolders + m_watchedFiles); + + // Set the new watched folder for the model + m_watchedFolders.clear(); + m_watchedFiles.clear(); + m_watchedFolders.insert(m_guiApplicationManager->GetAssetListsFolder().c_str()); + ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType::AssetListFileType); + + m_guiApplicationManager->AddWatchedPaths(m_watchedFolders + m_watchedFiles); + } + + AzQtComponents::TableView* AssetListTabWidget::GetFileTableView() + { + return m_ui->assetListsTable; + } + + QModelIndex AssetListTabWidget::GetSelectedFileTableIndex() + { + return m_selectedFileTableIndex; + } + + AssetBundlerAbstractFileTableModel* AssetListTabWidget::GetFileTableModel() + { + return m_fileTableModel.get(); + } + + void AssetListTabWidget::SetActiveProjectLabel(const QString& labelText) + { + m_ui->activeProjectLabel->setText(labelText); + } + + void AssetListTabWidget::ApplyConfig() + { + const GUIApplicationManager::Config& config = m_guiApplicationManager->GetConfig(); + + m_ui->fileTableFrame->setFixedWidth(config.fileTableWidth); + + m_ui->assetListsTable->header()->resizeSection(AssetListFileTableModel::Column::ColumnFileName, config.assetListFileNameColumnWidth); + m_ui->assetListsTable->header()->resizeSection(AssetListFileTableModel::Column::ColumnPlatform, config.assetListPlatformColumnWidth); + + m_ui->assetListContentsFilteredSearchWidget->setFixedWidth(config.fileTableWidth); + + m_ui->assetListContentsTable->header()->resizeSection(AssetListTableModel::Column::ColumnAssetName, config.productAssetNameColumnWidth); + m_ui->assetListContentsTable->header()->resizeSection(AssetListTableModel::Column::ColumnRelativePath, config.productAssetRelativePathColumnWidth); + } + + + void AssetListTabWidget::Reload() + { + // Reload all the asset list files + m_fileTableModel->Reload(AzToolsFramework::AssetSeedManager::GetAssetListFileExtension(), m_watchedFolders, m_watchedFiles); + + // Update the selected row + FileSelectionChanged(); + } + + void AssetListTabWidget::FileSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) + { + AZ_UNUSED(selected); + AZ_UNUSED(deselected); + + if (m_ui->assetListsTable->selectionModel()->selectedRows().size() == 0) + { + // Set selected index to an invalid value + m_selectedFileTableIndex = QModelIndex(); + m_ui->assetListFileAbsolutePathLabel->setText(""); + m_assetListContentsModel.reset(new AssetListTableModel()); + m_assetListContentsFilterModel->setSourceModel(m_assetListContentsModel.data()); + m_ui->generateBundleButton->setEnabled(false); + + return; + } + + m_selectedFileTableIndex = m_fileTableFilterModel->mapToSource(m_ui->assetListsTable->selectionModel()->currentIndex()); + + m_ui->assetListFileAbsolutePathLabel->setText(QString(m_fileTableModel->GetFileAbsolutePath(m_selectedFileTableIndex).c_str())); + + m_assetListContentsModel = m_fileTableModel->GetAssetListFileContents(m_selectedFileTableIndex); + m_assetListContentsFilterModel->setSourceModel(m_assetListContentsModel.data()); + + m_ui->generateBundleButton->setEnabled(true); + } + + void AssetListTabWidget::OnGenerateBundleButtonPressed() + { + GenerateBundlesModal generateBundlesModal( + this, + m_fileTableModel->GetFileAbsolutePath(m_selectedFileTableIndex), + m_guiApplicationManager->GetBundlesFolder(), + m_guiApplicationManager->GetBundleSettingsFolder(), + this); + generateBundlesModal.exec(); + } +} //namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.h b/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.h new file mode 100644 index 0000000000..890f45a0c9 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.h @@ -0,0 +1,82 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#endif + +namespace Ui +{ + class AssetListTabWidget; +} + +class QFileSystemModel; +class QStringListModel; + +namespace AssetBundler +{ + class GUIApplicationManager; + + class AssetListFileTableModel; + class AssetListTableModel; + + class AssetListTabWidget + : public AssetBundlerTabWidget + { + Q_OBJECT + + public: + explicit AssetListTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager); + virtual ~AssetListTabWidget() {} + + ////////////////////////////////////////////////////////////////////////// + // AssetBundlerTabWidget overrides + QString GetTabTitle() override { return tr("Asset Lists"); } + QString GetFileTypeDisplayName() override { return tr("Asset List file"); } + AssetBundlingFileType GetFileType() override { return AssetBundlingFileType::AssetListFileType; } + bool HasUnsavedChanges() override { return false; }; + void Reload() override; + bool SaveCurrentSelection() override { return true; }; + bool SaveAll() override { return true; }; + void SetModelDataSource() override; + AzQtComponents::TableView* GetFileTableView() override; + QModelIndex GetSelectedFileTableIndex() override; + AssetBundlerAbstractFileTableModel* GetFileTableModel() override; + void SetActiveProjectLabel(const QString& labelText) override; + void ApplyConfig() override; + void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) override; + ////////////////////////////////////////////////////////////////////////// + + private: + void OnGenerateBundleButtonPressed(); + + QSharedPointer m_ui; + + QSharedPointer m_fileTableModel; + QModelIndex m_selectedFileTableIndex; + + QSharedPointer m_assetListContentsFilterModel; + QSharedPointer m_assetListContentsModel; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.ui b/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.ui new file mode 100644 index 0000000000..a5bdea227b --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.ui @@ -0,0 +1,168 @@ + + + AssetListTabWidget + + + + 0 + 0 + 813 + 673 + + + + Asset List Tab Widget + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Generate Bundle + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Asset List Files + + + + + + + + + + Filter by file name + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Asset List + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Filter by file name + + + + + + + + + + + + + + + + AzQtComponents::TableView + QTreeView +
AzQtComponents/Components/Widgets/TableView.h
+ 1 +
+ + AzQtComponents::FilteredSearchWidget + QTreeView +
AzQtComponents/Components/FilteredSearchWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.cpp b/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.cpp new file mode 100644 index 0000000000..b670fd0ebd --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.cpp @@ -0,0 +1,159 @@ +/* +* All or portions of this file Copyright(c) Amazon.com, Inc. or its affiliates or +*its licensors. +* +* For complete copyrightand license terms please see the LICENSE at the root of this +* distribution(the "License").All use of this software is governed by the License, +* or , if provided, by the license below or the license accompanying this file.Do not +*remove or modify any license notices.This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#include +#include + +#include +#include + +#include + +#include +#include + +const double BytesToMegabytes = 1024.0 * 1024.0; + +namespace AssetBundler +{ + + BundleListTabWidget::BundleListTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager) + : AssetBundlerTabWidget(parent, guiApplicationManager) + { + m_ui.reset(new Ui::BundleListTabWidget); + m_ui->setupUi(this); + + m_ui->mainVerticalLayout->setContentsMargins(MarginSize, MarginSize, MarginSize, MarginSize); + + m_fileTableModel.reset(new BundleFileListModel); + m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(this, m_fileTableModel->GetFileNameColumnIndex(), m_fileTableModel->GetTimeStampColumnIndex())); + + m_fileTableFilterModel->setSourceModel(m_fileTableModel.data()); + m_ui->fileTableView->setModel(m_fileTableFilterModel.data()); + connect(m_ui->fileFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, + m_fileTableFilterModel.data(), static_cast(&AssetBundlerFileTableFilterModel::FilterChanged)); + + connect(m_ui->fileTableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &BundleListTabWidget::FileSelectionChanged); + + m_ui->fileTableView->setIndentation(0); + + m_relatedBundlesListModel.reset(new QStringListModel); + m_ui->relatedBundlesListView->setModel(m_relatedBundlesListModel.data()); + + m_ui->bundleFileContentsVerticalLayout->setContentsMargins(MarginSize, MarginSize, MarginSize, MarginSize); + + SetModelDataSource(); + } + + void BundleListTabWidget::Reload() + { + // The act of cracking open paks kicks off a DirectoryChanged event. We need to temporarily remove the Bundles + // directory from our watched paths to prevent an infinite loop of events. + m_guiApplicationManager->RemoveWatchedPaths(m_watchedFolders); + + // Reload all the bundle files + m_fileTableModel->Reload(AzToolsFramework::AssetBundleSettings::GetBundleFileExtension(), m_watchedFolders, m_watchedFiles); + + // Update the selected row + FileSelectionChanged(); + + // Start recieving DirectoryChanged events for these folders again + m_guiApplicationManager->AddWatchedPaths(m_watchedFolders); + } + + void BundleListTabWidget::SetModelDataSource() + { + // Remove the current watched folders and files + m_guiApplicationManager->RemoveWatchedPaths(m_watchedFolders + m_watchedFiles); + + // Set the new watched folder for the model + m_watchedFolders.clear(); + m_watchedFiles.clear(); + m_watchedFolders.insert(m_guiApplicationManager->GetBundlesFolder().c_str()); + ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType::BundleFileType); + + m_guiApplicationManager->AddWatchedPaths(m_watchedFolders + m_watchedFiles); + } + + AzQtComponents::TableView* BundleListTabWidget::GetFileTableView() + { + return m_ui->fileTableView; + } + + QModelIndex BundleListTabWidget::GetSelectedFileTableIndex() + { + return m_selectedFileTableIndex; + } + + AssetBundlerAbstractFileTableModel* BundleListTabWidget::GetFileTableModel() + { + return m_fileTableModel.get(); + } + + void BundleListTabWidget::SetActiveProjectLabel(const QString& labelText) + { + m_ui->activeProjectLabel->setText(labelText); + } + + void BundleListTabWidget::ApplyConfig() + { + const GUIApplicationManager::Config& config = m_guiApplicationManager->GetConfig(); + m_ui->fileTableFrame->setFixedWidth(config.fileTableWidth); + m_ui->fileTableView->header()->resizeSection(BundleFileListModel::Column::ColumnFileName, config.fileNameColumnWidth); + } + + + void BundleListTabWidget::FileSelectionChanged(const QItemSelection& /*selected*/, const QItemSelection& /*deselected*/) + { + if (m_ui->fileTableView->selectionModel()->selectedRows().size() == 0) + { + m_selectedFileTableIndex = QModelIndex(); + ClearDisplayedBundleValues(); + return; + } + + m_selectedFileTableIndex = m_fileTableFilterModel->mapToSource(m_ui->fileTableView->selectionModel()->selectedRows()[0]); + AZ::Outcome< BundleFileInfoPtr, void> fileInfoOutcome = m_fileTableModel->GetBundleInfo(m_selectedFileTableIndex); + + if (!fileInfoOutcome.IsSuccess()) + { + ClearDisplayedBundleValues(); + return; + } + + BundleFileInfoPtr fileInfoPtr = fileInfoOutcome.GetValue(); + + m_ui->absolutePathLabel->setText(fileInfoPtr->m_absolutePath.c_str()); + + QString sizeFormat("%1 MB"); + double compressedSize = (double)fileInfoPtr->m_compressedSize / BytesToMegabytes; + m_ui->compressedSizeValueLabel->setText(sizeFormat.arg(compressedSize, 6, 'f', 3)); + + bool hasRelatedBundles = !fileInfoPtr->m_relatedBundles.isEmpty(); + if (hasRelatedBundles) + { + m_relatedBundlesListModel->setStringList(fileInfoPtr->m_relatedBundles); + } + m_ui->relatedBundlesLabel->setVisible(hasRelatedBundles); + m_ui->relatedBundlesListView->setVisible(hasRelatedBundles); + } + + void BundleListTabWidget::ClearDisplayedBundleValues() + { + m_ui->absolutePathLabel->clear(); + m_ui->compressedSizeValueLabel->clear(); + m_ui->relatedBundlesLabel->setVisible(false); + m_ui->relatedBundlesListView->setVisible(false); + m_relatedBundlesListModel->setStringList({}); + } +} + +#include diff --git a/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.h b/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.h new file mode 100644 index 0000000000..c05e1078fa --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.h @@ -0,0 +1,67 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +#include +#include +#include +#include +#include +#include +#endif + +namespace Ui +{ + class BundleListTabWidget; +} + +namespace AssetBundler +{ + class BundleFileListModel; + + class BundleListTabWidget + : public AssetBundlerTabWidget + { + Q_OBJECT + public: + explicit BundleListTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager); + virtual ~BundleListTabWidget() {} + + QString GetTabTitle() override { return tr("Completed Bundles"); } + QString GetFileTypeDisplayName() override { return tr("Bundle"); } + AssetBundlingFileType GetFileType() override { return AssetBundlingFileType::BundleFileType; } + bool HasUnsavedChanges() override { return false; } + void Reload() override; + bool SaveCurrentSelection() override { return true; } + bool SaveAll() override { return true; } + void SetModelDataSource() override; + AzQtComponents::TableView* GetFileTableView() override; + QModelIndex GetSelectedFileTableIndex() override; + AssetBundlerAbstractFileTableModel* GetFileTableModel() override; + void SetActiveProjectLabel(const QString& labelText) override; + void ApplyConfig() override; + void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) override; + + private: + void ClearDisplayedBundleValues(); + + QSharedPointer m_ui; + QSharedPointer m_fileTableModel; + QModelIndex m_selectedFileTableIndex; + QSharedPointer m_relatedBundlesListModel; + }; + +} diff --git a/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.ui b/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.ui new file mode 100644 index 0000000000..9880640f09 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.ui @@ -0,0 +1,253 @@ + + + BundleListTabWidget + + + + 0 + 0 + 888 + 562 + + + + Bundle List Tab Widget + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Bundles + + + + + + + + + + Filter by file name + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Bundle Info + + + + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Compressed Size + + + + + + + TextLabel + + + + + + + Related Bundles + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + + AzQtComponents::TableView + QTreeView +
AzQtComponents/Components/Widgets/TableView.h
+ 1 +
+ + AzQtComponents::FilteredSearchWidget + QTreeView +
AzQtComponents/Components/FilteredSearchWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.cpp b/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.cpp new file mode 100644 index 0000000000..b5c2d78030 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.cpp @@ -0,0 +1,451 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include + +#include +#include + +namespace AssetBundler +{ + ////////////////////////////////////////////////////////////////////////////////////////////////// + // ComparisonDataWidget + ////////////////////////////////////////////////////////////////////////////////////////////////// + + const QStringList ComparisonTypeStringList = { "Default", "Delta", "Union", "Intersection", "Complement", "Wildcard", "Regex" }; + + ComparisonDataWidget::ComparisonDataWidget( + AZStd::shared_ptr comparisonList, + size_t comparisonDataIndex, + const AZStd::string& defaultAssetListFileDirectory, + QWidget* parent) + : QWidget(parent) + , m_comparisonDataIndex(comparisonDataIndex) + , m_defaultAssetListFileDirectory(defaultAssetListFileDirectory) + { + m_ui.reset(new Ui::ComparisonDataWidget); + m_ui->setupUi(this); + + m_comparisonList = comparisonList; + + if (!IsComparisonDataIndexValid()) + { + AZ_Error("AssetBundler", false, "ComparisonData index ( %u ) is out of bounds. ComparisonData cannot be displayed.", m_comparisonDataIndex); + return; + } + + // Due to initialization order, we need to hard-code this or else the value will be overwritten once this + // ComparisonDataWidget is added to the ComparisonDataCard, and the Card.qss file is applied + QString lineEditStyle("background-color: #CCCCCC;"); + m_ui->nameLineEdit->setStyleSheet(lineEditStyle); + m_ui->firstInputLineEdit->setStyleSheet(lineEditStyle); + m_ui->secondInputLineEdit->setStyleSheet(lineEditStyle); + m_ui->filePatternLineEdit->setStyleSheet(lineEditStyle); + + m_ui->firstInputLineEdit->setReadOnly(true); + m_ui->secondInputLineEdit->setReadOnly(true); + + SetAllDisplayValues(m_comparisonList->GetComparisonList()[m_comparisonDataIndex]); + + MouseWheelEventFilter* mouseWheelEventFilter = new MouseWheelEventFilter(this); + + connect(m_ui->nameLineEdit, &QLineEdit::textEdited, this, &ComparisonDataWidget::OnNameLineEditChanged); + + m_ui->comparisonTypeComboBox->installEventFilter(mouseWheelEventFilter); + connect(m_ui->comparisonTypeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ComparisonDataWidget::OnComparisonTypeComboBoxChanged); + + m_ui->firstInputComboBox->installEventFilter(mouseWheelEventFilter); + connect(m_ui->firstInputComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ComparisonDataWidget::OnFirstInputComboBoxChanged); + connect(m_ui->firstInputBrowseButton, &QPushButton::pressed, this, &ComparisonDataWidget::OnFirstInputBrowseButtonPressed); + + m_ui->secondInputComboBox->installEventFilter(mouseWheelEventFilter); + connect(m_ui->secondInputComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ComparisonDataWidget::OnSecondInputComboBoxChanged); + connect(m_ui->secondInputBrowseButton, &QPushButton::pressed, this, &ComparisonDataWidget::OnSecondInputBrowseButtonPressed); + + connect(m_ui->filePatternLineEdit, &QLineEdit::textEdited, this, &ComparisonDataWidget::OnFilePatternLineEditChanged); + } + + void ComparisonDataWidget::UpdateListOfTokenNames() + { + using namespace AzToolsFramework; + + if (!IsComparisonDataIndexValid()) + { + return; + } + + m_inputTokenNameList.clear(); + m_ui->firstInputComboBox->clear(); + m_ui->secondInputComboBox->clear(); + + // Store info about the current FirstInput and SecondInput values so we may auto-select them later + auto allComparisonDataSteps = m_comparisonList->GetComparisonList(); + AZStd::string selectedFirstInput = allComparisonDataSteps.at(m_comparisonDataIndex).m_firstInput; + int selectedFirstInputIndex = 0; + AZStd::string selectedSecondInput = allComparisonDataSteps.at(m_comparisonDataIndex).m_secondInput; + int selectedSecondInputIndex = 0; + + // Build list of all Token Names that have come before the current Comparison Step + m_inputTokenNameList.append(tr("Choose Asset List...")); + int currentComboBoxIndex = 1; + + AZStd::string tokenName; + for (size_t i = 0; i < m_comparisonDataIndex; ++i) + { + tokenName = allComparisonDataSteps.at(i).m_output; + if (!AssetFileInfoListComparison::IsTokenFile(tokenName)) + { + continue; + } + + if (tokenName == selectedFirstInput) + { + selectedFirstInputIndex = currentComboBoxIndex; + } + if (tokenName == selectedSecondInput) + { + selectedSecondInputIndex = currentComboBoxIndex; + } + + m_inputTokenNameList.append(RemoveTokenCharFromString(tokenName)); + ++currentComboBoxIndex; + } + + // Update display with list of Token Names, and select current Token Name in both input combo boxes + m_ui->firstInputComboBox->insertItems(0, m_inputTokenNameList); + m_ui->firstInputComboBox->setCurrentIndex(selectedFirstInputIndex); + m_isFirstInputFileNameVisible = selectedFirstInputIndex == 0; + SetFirstInputFileVisibility(m_isFirstInputFileNameVisible); + + m_ui->secondInputComboBox->insertItems(0, m_inputTokenNameList); + m_ui->secondInputComboBox->setCurrentIndex(selectedSecondInputIndex); + m_isSecondInputFileNameVisible = selectedSecondInputIndex == 0; + SetSecondInputFileVisibility(m_isSecondInputFileNameVisible); + } + + void ComparisonDataWidget::SetAllDisplayValues(const AzToolsFramework::AssetFileInfoListComparison::ComparisonData& comparisonData) + { + using namespace AzToolsFramework; + + // Name (Token value) + m_ui->nameLineEdit->setText(RemoveTokenCharFromString(comparisonData.m_output)); + + // Comparison Type + InitComparisonTypeComboBox(comparisonData); + + // Inputs + UpdateListOfTokenNames(); + m_ui->firstInputLineEdit->setText(QString(comparisonData.m_cachedFirstInputPath.c_str())); + m_ui->secondInputLineEdit->setText(QString(comparisonData.m_cachedSecondInputPath.c_str())); + + // Update fields that are not always visible + UpdateOnComparisonTypeChanged(comparisonData.m_filePatternType != AssetFileInfoListComparison::FilePatternType::Default); + } + + void ComparisonDataWidget::OnNameLineEditChanged() + { + if (!IsComparisonDataIndexValid()) + { + return; + } + + AZStd::string tokenName = m_ui->nameLineEdit->text().toUtf8().data(); + AzToolsFramework::AssetFileInfoListComparison::FormatOutputToken(tokenName); + m_comparisonList->SetOutput(m_comparisonDataIndex, tokenName); + emit comparisonDataChanged(); + emit comparisonDataTokenNameChanged(m_comparisonDataIndex); + } + + void ComparisonDataWidget::UpdateOnComparisonTypeChanged(bool isFilePatternOperation) + { + using namespace AzToolsFramework; + + if (!IsComparisonDataIndexValid()) + { + return; + } + + AssetFileInfoListComparison::ComparisonData comparisonData = m_comparisonList->GetComparisonList()[m_comparisonDataIndex]; + m_ui->inputBLabel->setVisible(!isFilePatternOperation); + m_ui->secondInputComboBox->setVisible(!isFilePatternOperation); + SetSecondInputFileVisibility(!isFilePatternOperation && m_isSecondInputFileNameVisible); + + m_ui->filePatternLabel->setVisible(isFilePatternOperation); + m_ui->filePatternLineEdit->setVisible(isFilePatternOperation); + m_ui->filePatternLineEdit->setText(comparisonData.m_filePattern.c_str()); + } + + void ComparisonDataWidget::InitComparisonTypeComboBox(const AzToolsFramework::AssetFileInfoListComparison::ComparisonData& comparisonData) + { + using namespace AzToolsFramework; + + m_ui->comparisonTypeComboBox->insertItems(0, ComparisonTypeStringList); + int initialSelectionIndex = ComparisonTypeIndex::Default; + + if (comparisonData.m_filePatternType != AssetFileInfoListComparison::FilePatternType::Default + && comparisonData.m_comparisonType == AssetFileInfoListComparison::ComparisonType::FilePattern) + { + if (comparisonData.m_filePatternType == AssetFileInfoListComparison::FilePatternType::Wildcard) + { + initialSelectionIndex = ComparisonTypeIndex::Wildcard; + } + else + { + initialSelectionIndex = ComparisonTypeIndex::Regex; + } + } + else + { + switch (comparisonData.m_comparisonType) + { + case AssetFileInfoListComparison::ComparisonType::Default: + break; + case AssetFileInfoListComparison::ComparisonType::Delta: + initialSelectionIndex = ComparisonTypeIndex::Delta; + break; + case AssetFileInfoListComparison::ComparisonType::Union: + initialSelectionIndex = ComparisonTypeIndex::Union; + break; + case AssetFileInfoListComparison::ComparisonType::Intersection: + initialSelectionIndex = ComparisonTypeIndex::Intersection; + break; + case AssetFileInfoListComparison::ComparisonType::Complement: + initialSelectionIndex = ComparisonTypeIndex::Complement; + break; + default: + AZ_Warning("AssetBundler", false, "ComparisonType ( %u ) is not supported in the Asset Bundler", comparisonData.m_comparisonType); + } + } + + m_ui->comparisonTypeComboBox->setCurrentIndex(initialSelectionIndex); + } + + void ComparisonDataWidget::OnComparisonTypeComboBoxChanged(int index) + { + using namespace AzToolsFramework; + + if (!IsComparisonDataIndexValid()) + { + return; + } + + bool isFilePattern = false; + + switch (index) + { + case ComparisonTypeIndex::Default: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::Default); + break; + case ComparisonTypeIndex::Delta: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::Delta); + break; + case ComparisonTypeIndex::Union: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::Union); + break; + case ComparisonTypeIndex::Intersection: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::Intersection); + break; + case ComparisonTypeIndex::Complement: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::Complement); + break; + case ComparisonTypeIndex::Wildcard: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::FilePattern); + m_comparisonList->SetFilePatternType(m_comparisonDataIndex, AssetFileInfoListComparison::FilePatternType::Wildcard); + isFilePattern = true; + break; + case ComparisonTypeIndex::Regex: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::FilePattern); + m_comparisonList->SetFilePatternType(m_comparisonDataIndex, AssetFileInfoListComparison::FilePatternType::Regex); + isFilePattern = true; + break; + } + + UpdateOnComparisonTypeChanged(isFilePattern); + emit comparisonDataChanged(); + } + + void ComparisonDataWidget::OnFilePatternLineEditChanged() + { + if (!IsComparisonDataIndexValid()) + { + return; + } + + m_comparisonList->SetFilePattern(m_comparisonDataIndex, m_ui->filePatternLineEdit->text().toUtf8().data()); + emit comparisonDataChanged(); + } + + void ComparisonDataWidget::OnFirstInputComboBoxChanged(int index) + { + AZStd::string firstInputValue; + + if (!IsComparisonDataIndexValid()) + { + return; + } + + m_isFirstInputFileNameVisible = index == 0; + + if (!m_isFirstInputFileNameVisible) + { + // The 0th index is the default value, which translates to an empty token string. + firstInputValue = m_ui->firstInputComboBox->currentText().toUtf8().data(); + AzToolsFramework::AssetFileInfoListComparison::FormatOutputToken(firstInputValue); + } + + SetFirstInputFileVisibility(m_isFirstInputFileNameVisible); + + m_comparisonList->SetFirstInput(m_comparisonDataIndex, firstInputValue); + emit comparisonDataChanged(); + } + + void ComparisonDataWidget::SetFirstInputFileVisibility(bool isVisible) + { + m_ui->firstInputLineEdit->setVisible(isVisible); + m_ui->firstInputBrowseButton->setVisible(isVisible); + } + + void ComparisonDataWidget::OnFirstInputBrowseButtonPressed() + { + if (!IsComparisonDataIndexValid()) + { + return; + } + + QString absoluteFilePath = BrowseButtonPressed(); + if (absoluteFilePath.isEmpty()) + { + // User canceled out of the dialog + return; + } + + m_ui->firstInputLineEdit->setText(absoluteFilePath); + m_comparisonList->SetCachedFirstInputPath(m_comparisonDataIndex, absoluteFilePath.toUtf8().data()); + } + + void ComparisonDataWidget::OnSecondInputComboBoxChanged(int index) + { + if (!IsComparisonDataIndexValid()) + { + return; + } + + AZStd::string secondInputValue; + + m_isSecondInputFileNameVisible = index == 0; + + if (!m_isSecondInputFileNameVisible) + { + // The 0th index is the default value, which translates to an empty token string. + secondInputValue = m_ui->secondInputComboBox->currentText().toUtf8().data(); + AzToolsFramework::AssetFileInfoListComparison::FormatOutputToken(secondInputValue); + } + + SetSecondInputFileVisibility(m_isSecondInputFileNameVisible); + + m_comparisonList->SetSecondInput(m_comparisonDataIndex, secondInputValue); + emit comparisonDataChanged(); + } + + void ComparisonDataWidget::SetSecondInputFileVisibility(bool isVisible) + { + m_ui->secondInputLineEdit->setVisible(isVisible); + m_ui->secondInputBrowseButton->setVisible(isVisible); + } + + void ComparisonDataWidget::OnSecondInputBrowseButtonPressed() + { + if (!IsComparisonDataIndexValid()) + { + return; + } + + QString absoluteFilePath = BrowseButtonPressed(); + if (absoluteFilePath.isEmpty()) + { + // User canceled out of the dialog + return; + } + + m_ui->secondInputLineEdit->setText(absoluteFilePath); + m_comparisonList->SetCachedSecondInputPath(m_comparisonDataIndex, absoluteFilePath.toUtf8().data()); + } + + QString ComparisonDataWidget::BrowseButtonPressed() + { + AZStd::string selectedPath = NewFileDialog::OSNewFileDialog( + this, + AzToolsFramework::AssetSeedManager::GetAssetListFileExtension(), + "Asset List", + m_defaultAssetListFileDirectory); + AzToolsFramework::RemovePlatformIdentifier(selectedPath); + return selectedPath.c_str(); + } + + bool ComparisonDataWidget::IsComparisonDataIndexValid() + { + return m_comparisonList->GetComparisonList().size() > m_comparisonDataIndex; + } + + QString ComparisonDataWidget::RemoveTokenCharFromString(const AZStd::string& tokenName) + { + QString displayName = tokenName.c_str(); + if (displayName.startsWith(AzToolsFramework::AssetFileInfoListComparison::GetTokenIdentifier())) + { + displayName.remove(0, 1); + } + + return displayName; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // MouseWheelEventFilter + ////////////////////////////////////////////////////////////////////////////////////////////////// + + bool MouseWheelEventFilter::eventFilter(QObject* obj, QEvent* ev) + { + if (ev->type() == QEvent::Wheel) + { + return true; + } + + return QObject::eventFilter(obj, ev); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // ComparisonDataCard + ////////////////////////////////////////////////////////////////////////////////////////////////// + + ComparisonDataCard::ComparisonDataCard( + AZStd::shared_ptr comparisonList, + size_t comparisonDataIndex, + const AZStd::string& defaultAssetListFileDirectory, + QWidget* parent) + : AzQtComponents::Card(parent) + { + m_comparisonDataWidget = new ComparisonDataWidget(comparisonList, comparisonDataIndex, defaultAssetListFileDirectory, this); + setContentWidget(m_comparisonDataWidget); + + connect(this, &AzQtComponents::Card::contextMenuRequested, this, &ComparisonDataCard::OnContextMenuRequested); + } + + void ComparisonDataCard::OnContextMenuRequested(const QPoint& position) + { + emit comparisonDataCardContextMenuRequested(m_comparisonDataWidget->GetComparisonDataIndex(), position); + } + +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.h b/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.h new file mode 100644 index 0000000000..9728d281a7 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.h @@ -0,0 +1,151 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include +#include +#include + +#include +#endif + +namespace Ui +{ + class ComparisonDataWidget; +} + +namespace AssetBundler +{ + //! Widget for displaying and editing a single Comparison Step inside a Comparison Rules file. + class ComparisonDataWidget + : public QWidget + { + Q_OBJECT + + public: + explicit ComparisonDataWidget( + AZStd::shared_ptr comparisonList, + size_t comparisonDataIndex, + const AZStd::string& defaultAssetListFileDirectory, + QWidget* parent = nullptr); + virtual ~ComparisonDataWidget() {} + + enum ComparisonTypeIndex : int + { + Default = 0, + Delta, + Union, + Intersection, + Complement, + Wildcard, + Regex, + MAX + }; + + size_t GetComparisonDataIndex() { return m_comparisonDataIndex; } + + void UpdateListOfTokenNames(); + + Q_SIGNALS: + void comparisonDataChanged(); + + void comparisonDataTokenNameChanged(size_t comparisonDataIndex); + + private: + void SetAllDisplayValues(const AzToolsFramework::AssetFileInfoListComparison::ComparisonData& comparisonData); + + void OnNameLineEditChanged(); + + void UpdateOnComparisonTypeChanged(bool isFilePatternOperation); + + void InitComparisonTypeComboBox(const AzToolsFramework::AssetFileInfoListComparison::ComparisonData& comparisonData); + + void OnComparisonTypeComboBoxChanged(int index); + + void OnFilePatternLineEditChanged(); + + void OnFirstInputComboBoxChanged(int index); + + void SetFirstInputFileVisibility(bool isVisible); + + void OnFirstInputBrowseButtonPressed(); + + void OnSecondInputComboBoxChanged(int index); + + void SetSecondInputFileVisibility(bool isVisible); + + void OnSecondInputBrowseButtonPressed(); + + QString BrowseButtonPressed(); + + bool IsComparisonDataIndexValid(); + + QString RemoveTokenCharFromString(const AZStd::string& tokenName); + + QSharedPointer m_ui; + + AZStd::shared_ptr m_comparisonList; + size_t m_comparisonDataIndex; + + AZStd::string m_defaultAssetListFileDirectory; + + QStringList m_inputTokenNameList; + QString m_outputAssetListFileAbsolutePath; + + bool m_isFirstInputFileNameVisible = false; + bool m_isSecondInputFileNameVisible = false; + }; + + class MouseWheelEventFilter + : public QObject + { + Q_OBJECT + + public: + explicit MouseWheelEventFilter(QObject* parent) : QObject(parent) {} + + protected: + bool eventFilter(QObject* obj, QEvent* ev) override; + }; + + + //! Wrapper widget that controls the expansion state and signals that trigger a context menu of a ComparisonDataWidget. + class ComparisonDataCard + : public AzQtComponents::Card + { + Q_OBJECT + + public: + explicit ComparisonDataCard( + AZStd::shared_ptr comparisonList, + size_t comparisonDataIndex, + const AZStd::string& defaultAssetListFileDirectory, + QWidget* parent = nullptr); + virtual ~ComparisonDataCard() {} + + ComparisonDataWidget* GetComparisonDataWidget() { return m_comparisonDataWidget; } + + Q_SIGNALS: + void comparisonDataCardContextMenuRequested(size_t comparisonDataIndex, const QPoint& position); + + private: + ComparisonDataWidget* m_comparisonDataWidget = nullptr; + + private slots: + void OnContextMenuRequested(const QPoint& position); + }; + + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.ui b/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.ui new file mode 100644 index 0000000000..4e148e21bb --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.ui @@ -0,0 +1,150 @@ + + + ComparisonDataWidget + + + + 0 + 0 + 400 + 300 + + + + + 0 + 0 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + QLayout::SetDefaultConstraint + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Name + + + + + + + + + + Comparison Type + + + + + + + + + + Input A + + + + + + + + + + 10 + + + + + + + + Browse... + + + + + + + + + Input B + + + + + + + + + + 10 + + + + + + + + Browse... + + + + + + + + + File Pattern + + + + + + + + + + + + + + diff --git a/Code/Tools/AssetBundler/source/ui/EditSeedDialog.cpp b/Code/Tools/AssetBundler/source/ui/EditSeedDialog.cpp new file mode 100644 index 0000000000..a42e0cd0f0 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/EditSeedDialog.cpp @@ -0,0 +1,62 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include + +#include + +namespace AssetBundler +{ + + EditSeedDialog::EditSeedDialog( + QWidget* parent, + const AzFramework::PlatformFlags& enabledPlatforms, + const AzFramework::PlatformFlags& selectedPlatforms, + const AzFramework::PlatformFlags& partiallySelectedPlatforms) + : QDialog(parent) + { + m_ui.reset(new Ui::EditSeedDialog); + m_ui->setupUi(this); + + m_ui->platformSelectionWidget->Init(enabledPlatforms); + m_ui->platformSelectionWidget->SetSelectedPlatforms(selectedPlatforms, partiallySelectedPlatforms); + connect(m_ui->platformSelectionWidget, &PlatformSelectionWidget::PlatformsSelected, this, &EditSeedDialog::OnPlatformSelectionChanged); + + // Set up confirm and cancel buttons + connect(m_ui->applyChangesButton, &QPushButton::clicked, this, &QDialog::accept); + connect(m_ui->cancelButton, &QPushButton::clicked, this, &QDialog::reject); + } + + AzFramework::PlatformFlags EditSeedDialog::GetPlatformFlags() + { + return m_ui->platformSelectionWidget->GetSelectedPlatforms(); + } + + AzFramework::PlatformFlags EditSeedDialog::GetPartiallySelectedPlatformFlags() + { + return m_ui->platformSelectionWidget->GetPartiallySelectedPlatforms(); + } + + void EditSeedDialog::OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms, const AzFramework::PlatformFlags& partiallySelectedPlatforms) + { + // Disable the "Apply Changes" button if no platforms are selected + bool areAnyPlatformsSelected = selectedPlatforms != AzFramework::PlatformFlags::Platform_NONE || + partiallySelectedPlatforms != AzFramework::PlatformFlags::Platform_NONE; + m_ui->applyChangesButton->setEnabled(areAnyPlatformsSelected); + } + +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/EditSeedDialog.h b/Code/Tools/AssetBundler/source/ui/EditSeedDialog.h new file mode 100644 index 0000000000..751c1eae3d --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/EditSeedDialog.h @@ -0,0 +1,52 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include + +#include +#include +#endif + +namespace Ui +{ + class EditSeedDialog; +} + +namespace AssetBundler +{ + class EditSeedDialog + : public QDialog + { + Q_OBJECT + + public: + explicit EditSeedDialog( + QWidget* parent, + const AzFramework::PlatformFlags& enabledPlatforms, + const AzFramework::PlatformFlags& selectedPlatforms, + const AzFramework::PlatformFlags& partiallySelectedPlatforms = AzFramework::PlatformFlags::Platform_NONE); + virtual ~EditSeedDialog() {} + + AzFramework::PlatformFlags GetPlatformFlags(); + AzFramework::PlatformFlags GetPartiallySelectedPlatformFlags(); + + private: + void OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms, const AzFramework::PlatformFlags& partiallySelectedPlatforms); + + QSharedPointer m_ui; + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/EditSeedDialog.ui b/Code/Tools/AssetBundler/source/ui/EditSeedDialog.ui new file mode 100644 index 0000000000..7d42d2d252 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/EditSeedDialog.ui @@ -0,0 +1,117 @@ + + + EditSeedDialog + + + + 0 + 0 + 400 + 92 + + + + + 300 + 0 + + + + Edit Selected Platforms + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + 10 + + + 10 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + + + + + Apply Changes + + + true + + + + + + + + + + AssetBundler::PlatformSelectionWidget + QWidget +
source/ui/PlatformSelectionWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.cpp b/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.cpp new file mode 100644 index 0000000000..3724bc8753 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.cpp @@ -0,0 +1,276 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +const char CustomBundleSettingsText[] = "Custom"; + +namespace AssetBundler +{ + GenerateBundlesModal::GenerateBundlesModal( + QWidget* parent, + const AZStd::string& assetListFileAbsolutePath, + const AZStd::string& defaultBundleDirectory, + const AZStd::string& defaultBundleSettingsDirectory, + AssetListTabWidget* assetListTabWidget) + : QDialog(parent) + , m_assetListFileAbsolutePath(assetListFileAbsolutePath) + , m_defaultBundleDirectory(defaultBundleDirectory) + , m_defaultBundleSettingsDirectory(defaultBundleSettingsDirectory) + , m_assetListTabWidget(assetListTabWidget) + { + m_ui.reset(new Ui::GenerateBundlesModal); + m_ui->setupUi(this); + + m_platformName = AzToolsFramework::GetPlatformIdentifier(m_assetListFileAbsolutePath); + + // Selected Asset List + m_ui->selectedAssetListPathLabel->setText(QString(m_assetListFileAbsolutePath.c_str())); + + // Platform + m_ui->platformNameLabel->setText(QString(m_platformName.c_str())); + + // Bundle Output + m_ui->outputBundlePathLineEdit->setReadOnly(true); + connect(m_ui->outputBundlePathBrowseButton, &QPushButton::clicked, this, &GenerateBundlesModal::OnOutputBundleLocationBrowseButtonPressed); + + // Bundle Settings files + m_ui->bundleSettingsFileLineEdit->setReadOnly(true); + m_ui->bundleSettingsFileLineEdit->setText(tr(CustomBundleSettingsText)); + connect(m_ui->bundleSettingsFileBrowseButton, &QPushButton::clicked, this, &GenerateBundlesModal::OnBundleSettingsBrowseButtonPressed); + connect(m_ui->bundleSettingsFileSaveButton, &QPushButton::clicked, this, &GenerateBundlesModal::OnBundleSettingsSaveButtonPressed); + + // Max Bundle Size + m_ui->maxBundleSizeSpinBox->setRange(1, AzToolsFramework::MaxBundleSizeInMB); + m_ui->maxBundleSizeSpinBox->setValue(AzToolsFramework::MaxBundleSizeInMB); + m_ui->maxBundleSizeSpinBox->setButtonSymbols(QAbstractSpinBox::ButtonSymbols::NoButtons); + m_ui->maxBundleSizeSpinBox->setSuffix(" MB"); + connect(m_ui->maxBundleSizeSpinBox, QOverload::of(&QSpinBox::valueChanged), this, &GenerateBundlesModal::OnMaxBundleSizeChanged); + + // Bundle Version + m_ui->bundleVersionSpinBox->setRange(1, AzFramework::AssetBundleManifest::CurrentBundleVersion); + m_ui->bundleVersionSpinBox->setValue(AzFramework::AssetBundleManifest::CurrentBundleVersion); + m_ui->bundleVersionSpinBox->setButtonSymbols(QAbstractSpinBox::ButtonSymbols::NoButtons); + connect(m_ui->bundleVersionSpinBox, QOverload::of(&QSpinBox::valueChanged), this, &GenerateBundlesModal::OnBundleVersionChanged); + + // Cancel and Generate Bundles buttons + m_ui->generateBundlesButton->setEnabled(false); + connect(m_ui->cancelButton, &QPushButton::clicked, this, &QDialog::reject); + connect(m_ui->generateBundlesButton, &QPushButton::clicked, this, &GenerateBundlesModal::OnGenerateBundlesButtonPressed); + + // In-memory Bundle Settings + m_bundleSettings.m_assetFileInfoListPath = m_assetListFileAbsolutePath; + m_bundleSettings.m_platform = m_platformName; + m_bundleSettings.m_maxBundleSizeInMB = static_cast(m_ui->maxBundleSizeSpinBox->value()); + m_bundleSettings.m_bundleVersion = m_ui->bundleVersionSpinBox->value(); + } + + GenerateBundlesModal::~GenerateBundlesModal() + { + m_assetListTabWidget = nullptr; + } + + void GenerateBundlesModal::OnOutputBundleLocationBrowseButtonPressed() + { + AZStd::string outputBundleAbsolutePath = NewFileDialog::OSNewFileDialog( + this, + AzToolsFramework::AssetBundleSettings::GetBundleFileExtension(), + "Bundle", + m_defaultBundleDirectory); + + if (outputBundleAbsolutePath.empty()) + { + // User canceled out of the dialog + return; + } + + AzToolsFramework::RemovePlatformIdentifier(outputBundleAbsolutePath); + AddPlatformIdentifier(outputBundleAbsolutePath, m_platformName); + + m_bundleSettings.m_bundleFilePath = outputBundleAbsolutePath; + + m_ui->outputBundlePathLineEdit->setText(outputBundleAbsolutePath.c_str()); + m_ui->generateBundlesButton->setEnabled(true); + } + + void GenerateBundlesModal::OnBundleSettingsBrowseButtonPressed() + { + AZStd::string bundleSettingsAbsolutePath = NewFileDialog::OSNewFileDialog( + this, + AzToolsFramework::AssetBundleSettings::GetBundleSettingsFileExtension(), + "Bundle Settings", + m_defaultBundleSettingsDirectory); + + if (bundleSettingsAbsolutePath.empty()) + { + // User canceled out of the dialog + return; + } + + // Read in the values from the Bundle Settings file + bool loadResult = LoadBundleSettingsValues(bundleSettingsAbsolutePath); + if (!loadResult) + { + return; + } + + // Update the display name for our settings + UpdateBundleSettingsDisplayName(bundleSettingsAbsolutePath); + } + + bool GenerateBundlesModal::LoadBundleSettingsValues(const AZStd::string& absoluteBundleSettingsFilePath) + { + using namespace AzToolsFramework; + + auto outcome = AssetBundleSettings::Load(absoluteBundleSettingsFilePath); + if (!outcome.IsSuccess()) + { + AZ_Error("AssetBundler", false, outcome.GetError().c_str()); + return false; + } + + // We don't want to overwrite all of the in-memory bundle settings, so we will just update a few + AssetBundleSettings loadedSettings = outcome.TakeValue(); + + m_bundleSettings.m_maxBundleSizeInMB = loadedSettings.m_maxBundleSizeInMB; + m_ui->maxBundleSizeSpinBox->setValue(static_cast(m_bundleSettings.m_maxBundleSizeInMB)); + + m_bundleSettings.m_bundleVersion = loadedSettings.m_bundleVersion; + m_ui->bundleVersionSpinBox->setValue(m_bundleSettings.m_bundleVersion); + + return true; + } + + void GenerateBundlesModal::UpdateBundleSettingsDisplayName(const AZStd::string& absoluteBundleSettingsFilePath) + { + if (absoluteBundleSettingsFilePath.empty()) + { + m_ui->bundleSettingsFileLineEdit->setText(tr(CustomBundleSettingsText)); + return; + } + + AZStd::string bundleSettingsFileName = absoluteBundleSettingsFilePath; + AzToolsFramework::RemovePlatformIdentifier(bundleSettingsFileName); + AzFramework::StringFunc::Path::GetFileName(bundleSettingsFileName.c_str(), bundleSettingsFileName); + m_ui->bundleSettingsFileLineEdit->setText(bundleSettingsFileName.c_str()); + } + + void GenerateBundlesModal::OnBundleSettingsSaveButtonPressed() + { + using namespace AzToolsFramework; + + // Ask the user where they want to save the Bundle Settings file + AZStd::string bundleSettingsAbsolutePath = NewFileDialog::OSNewFileDialog( + this, + AssetBundleSettings::GetBundleSettingsFileExtension(), + "Bundle Settings", + m_defaultBundleSettingsDirectory); + + if (bundleSettingsAbsolutePath.empty()) + { + // User canceled out of the operation + return; + } + + AzToolsFramework::RemovePlatformIdentifier(bundleSettingsAbsolutePath); + AddPlatformIdentifier(bundleSettingsAbsolutePath, m_platformName); + + if (AZ::IO::FileIOBase::GetInstance()->Exists(bundleSettingsAbsolutePath.c_str())) + { + QString messageBoxText = QString(tr("Bundle Settings ( %1 ) already exists on-disk. Saving the current settings will override the existing settings. \n\nDo you wish to continue?")).arg(bundleSettingsAbsolutePath.c_str()); + + QMessageBox::StandardButton confirmDeleteFileResult = QMessageBox::question(this, QString(tr("Replace Existing Settings")), messageBoxText); + if (confirmDeleteFileResult != QMessageBox::StandardButton::Yes) + { + // User canceled out of the operation + return; + } + } + + bool saveResult = AssetBundleSettings::Save(m_bundleSettings, bundleSettingsAbsolutePath); + if (!saveResult) + { + // Error has already been thrown + return; + } + + m_assetListTabWidget->AddScanPathToAssetBundlerSettings(AssetBundlingFileType::BundleSettingsFileType, bundleSettingsAbsolutePath); + + UpdateBundleSettingsDisplayName(bundleSettingsAbsolutePath); + } + + void GenerateBundlesModal::OnMaxBundleSizeChanged() + { + m_bundleSettings.m_maxBundleSizeInMB = static_cast(m_ui->maxBundleSizeSpinBox->value()); + UpdateBundleSettingsDisplayName(""); + } + + void GenerateBundlesModal::OnBundleVersionChanged() + { + m_bundleSettings.m_bundleVersion = m_ui->bundleVersionSpinBox->value(); + UpdateBundleSettingsDisplayName(""); + } + + void GenerateBundlesModal::OnGenerateBundlesButtonPressed() + { + using namespace AzToolsFramework; + + if (AZ::IO::FileIOBase::GetInstance()->Exists(m_bundleSettings.m_bundleFilePath.c_str())) + { + QString messageBoxText = QString(tr("Asset Bundle ( %1 ) already exists on-disk. Generating a new Bundle will override the existing Bundle. \n\nDo you wish to permanently delete the existing Bundle?")).arg(m_bundleSettings.m_bundleFilePath.c_str()); + + QMessageBox::StandardButton confirmDeleteFileResult = QMessageBox::question(this, QString(tr("Replace Existing Bundle")), messageBoxText); + if (confirmDeleteFileResult != QMessageBox::StandardButton::Yes) + { + // User canceled out of the operation + return; + } + } + + bool result = false; + AssetBundleCommandsBus::BroadcastResult(result, &AssetBundleCommandsBus::Events::CreateAssetBundle, m_bundleSettings); + + // This operation will take long enough that the OS will throw up its own wait cursor, + // but there is a slight delay where the UI is unresponsive but the cursor hasn't changed. + // We are changing the cursor manually to avoid that. + setCursor(Qt::WaitCursor); + + emit QDialog::accept(); + + if (result) + { + m_assetListTabWidget->AddScanPathToAssetBundlerSettings(AssetBundlingFileType::BundleFileType, m_bundleSettings.m_bundleFilePath); + + // The watched files list was updated after the files were created, so we need to force-reload them + m_assetListTabWidget->GetGUIApplicationManager()->UpdateFiles(AssetBundlingFileType::BundleFileType, { m_bundleSettings.m_bundleFilePath }); + } + + AZStd::vector generatedFilePaths = { m_bundleSettings.m_bundleFilePath }; + NewFileDialog::FileGenerationResultMessageBox(this, generatedFilePaths, !result); + + unsetCursor(); + } + +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.h b/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.h new file mode 100644 index 0000000000..b4edaedb9b --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.h @@ -0,0 +1,75 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include + +#include +#include +#endif + +namespace Ui +{ + class GenerateBundlesModal; +} + +namespace AssetBundler +{ + class AssetListTabWidget; + + class GenerateBundlesModal + : public QDialog + { + Q_OBJECT + + public: + explicit GenerateBundlesModal( + QWidget* parent, + const AZStd::string& assetListFileAbsolutePath, + const AZStd::string& defaultBundleDirectory, + const AZStd::string& defaultBundleSettingsDirectory, + AssetListTabWidget* assetListTabWidget); + virtual ~GenerateBundlesModal(); + + private: + void OnOutputBundleLocationBrowseButtonPressed(); + + void OnBundleSettingsBrowseButtonPressed(); + + bool LoadBundleSettingsValues(const AZStd::string& absoluteBundleSettingsFilePath); + + void UpdateBundleSettingsDisplayName(const AZStd::string& absoluteBundleSettingsFilePath); + + void OnBundleSettingsSaveButtonPressed(); + + void OnMaxBundleSizeChanged(); + + void OnBundleVersionChanged(); + + void OnGenerateBundlesButtonPressed(); + + QSharedPointer m_ui; + + AssetListTabWidget* m_assetListTabWidget = nullptr; + + AZStd::string m_assetListFileAbsolutePath; + AZStd::string m_defaultBundleDirectory; + AZStd::string m_defaultBundleSettingsDirectory; + AZStd::string m_platformName; + + AzToolsFramework::AssetBundleSettings m_bundleSettings; + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.ui b/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.ui new file mode 100644 index 0000000000..df7ac0f0be --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.ui @@ -0,0 +1,292 @@ + + + GenerateBundlesModal + + + Qt::ApplicationModal + + + + 0 + 0 + 800 + 300 + + + + + 0 + 0 + + + + + 750 + 0 + + + + Generate Bundles + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 5 + + + 0 + + + 5 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Asset List + + + + + + + TextLabel + + + + + + + Platform + + + + + + + TextLabel + + + + + + + Output Bundle Name + + + + + + + + + + + + Browse... + + + + + + + + + + + + Qt::Horizontal + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Settings + + + + + + + + + + + + Browse... + + + + + + + Save + + + + + + + + + Max Bundle Size + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Bundle Version + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + + + + + Generate Bundles + + + true + + + + + + + + + + diff --git a/Code/Tools/AssetBundler/source/ui/MainWindow.cpp b/Code/Tools/AssetBundler/source/ui/MainWindow.cpp new file mode 100644 index 0000000000..c0e30c01f2 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/MainWindow.cpp @@ -0,0 +1,249 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace AssetBundler +{ + + MainWindow::MainWindow(AssetBundler::GUIApplicationManager* guiApplicationManager, QWidget* parent) + : QMainWindow(parent) + , m_guiApplicationManager(guiApplicationManager) + { + m_ui.reset(new Ui::MainWindow); + m_ui->setupUi(this); + + m_ui->verticalLayout->setContentsMargins(0, 0, 0, 0); + + // Set up Log + m_logModel.reset(new AzToolsFramework::Logging::LogTableModel(this)); + m_ui->logTableView->setModel(m_logModel.data()); + m_ui->logTableView->setIndentation(0); + + m_ui->logTableView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(m_ui->logTableView, &QWidget::customContextMenuRequested, this, &MainWindow::ShowLogContextMenu); + + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + + // Create the Unsaved Changes Popup + m_unsavedChangesMsgBox.reset(new QMessageBox(this)); + m_unsavedChangesMsgBox->setText(tr("There are unsaved changes.")); + m_unsavedChangesMsgBox->setInformativeText(tr("Would you like to save all changes before quitting?")); + m_unsavedChangesMsgBox->setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + m_unsavedChangesMsgBox->setDefaultButton(QMessageBox::Save); + + // Set up Quit functionality + m_ui->actionClose->setShortcut(Qt::Key_Q | Qt::CTRL); + m_ui->actionClose->setMenuRole(QAction::QuitRole); + connect(m_ui->actionClose, SIGNAL(triggered()), this, SLOT(close())); + this->addAction(m_ui->actionClose); + + // Set up Tabs + AssetBundlerTabWidget::InitAssetBundlerSettings(m_guiApplicationManager->GetCurrentProjectFolder().c_str()); + + m_seedListTab.reset(new SeedTabWidget(this, m_guiApplicationManager, QString(m_guiApplicationManager->GetAssetBundlingFolder().c_str()))); + m_ui->tabWidget->addTab(m_seedListTab.data(), m_seedListTab->GetTabTitle()); + + m_assetListTab.reset(new AssetListTabWidget(this, m_guiApplicationManager)); + m_ui->tabWidget->addTab(m_assetListTab.data(), m_assetListTab->GetTabTitle()); + + m_rulesTab.reset(new RulesTabWidget(this, m_guiApplicationManager)); + m_ui->tabWidget->addTab(m_rulesTab.data(), m_rulesTab->GetTabTitle()); + + m_bundleListTab.reset(new BundleListTabWidget(this, m_guiApplicationManager)); + m_ui->tabWidget->addTab(m_bundleListTab.data(), m_bundleListTab->GetTabTitle()); + + // Set up link to documentation + QAction* supportAction = new QAction(QIcon(":/stylesheet/img/help.svg"), "", this); + connect(supportAction, &QAction::triggered, this, &MainWindow::OnSupportClicked); + connect(m_ui->actionDocumentation, &QAction::triggered, this, &MainWindow::OnSupportClicked); + m_ui->tabWidget->setActionToolBarVisible(); + m_ui->tabWidget->addAction(supportAction); + + // Set up Save functionality + m_ui->actionSave->setShortcut(Qt::Key_S | Qt::CTRL); + connect(m_ui->actionSave, &QAction::triggered, this, &MainWindow::SaveCurrentSelection); + + m_ui->actionSaveAll->setShortcut(Qt::Key_S | Qt::CTRL | Qt::SHIFT); + connect(m_ui->actionSaveAll, &QAction::triggered, this, &MainWindow::SaveAll); + } + + MainWindow::~MainWindow() + { + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + m_guiApplicationManager = nullptr; + } + + void MainWindow::Activate() + { + m_seedListTab->Activate(); + m_rulesTab->Activate(); + m_assetListTab->Activate(); + m_bundleListTab->Activate(); + } + + void MainWindow::ApplyConfig() + { + const GUIApplicationManager::Config& config = m_guiApplicationManager->GetConfig(); + // Event Log Details + m_ui->logTableView->header()->resizeSection(AzToolsFramework::Logging::LogTableModel::ColumnType, config.logTypeColumnWidth); + m_ui->logTableView->header()->resizeSection(AzToolsFramework::Logging::LogTableModel::ColumnWindow, config.logSourceColumnWidth); + + m_seedListTab->ApplyConfig(); + m_assetListTab->ApplyConfig(); + m_rulesTab->ApplyConfig(); + m_bundleListTab->ApplyConfig(); + } + + void MainWindow::WriteToLog(const AZStd::string& message, AzToolsFramework::Logging::LogLine::LogType logType) + { + WriteToLog(message.c_str(), logType); + } + + void MainWindow::WriteToLog(const QString& message, AzToolsFramework::Logging::LogLine::LogType logType) + { + WriteToLog(message.toUtf8().data(), logType); + } + + void MainWindow::WriteToLog(const char* message, AzToolsFramework::Logging::LogLine::LogType logType) + { + WriteToLog(message, "AssetBundler", logType); + } + + void MainWindow::WriteToLog(const char* message, const char* window, AzToolsFramework::Logging::LogLine::LogType logType) + { + m_logModel->AppendLine( + AzToolsFramework::Logging::LogLine( + message, + window, + logType, + QDateTime::currentMSecsSinceEpoch())); + m_ui->logTableView->scrollToBottom(); + } + + bool MainWindow::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + WriteToLog(message, window, AzToolsFramework::Logging::LogLine::LogType::TYPE_ERROR); + return true; + } + + bool MainWindow::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + WriteToLog(message, window, AzToolsFramework::Logging::LogLine::LogType::TYPE_WARNING); + return true; + } + + bool MainWindow::OnPrintf(const char* /*window*/, const char* /*message*/) + { + return true; + } + + void MainWindow::ShowWindow() + { + AzQtComponents::bringWindowToTop(this); + } + + void MainWindow::closeEvent(QCloseEvent* event) + { + if (!HasUnsavedChanges()) + { + // No need to ask the user if they want to quit when there are no unsaved changes + event->accept(); + return; + } + + int unsavedChangesResult = m_unsavedChangesMsgBox->exec(); + + switch (unsavedChangesResult) + { + case QMessageBox::Save: + // Save All was clicked + SaveAll(); + event->accept(); + break; + case QMessageBox::Discard: + // Don't Save was clicked + event->accept(); + break; + case QMessageBox::Cancel: + // Cancel was clicked + event->ignore(); + break; + default: + // should never be reached + AZ_Assert(false, "No result was returned by the Unsaved Changes Message Box!"); + break; + } + } + + void MainWindow::OnSupportClicked() + { + QDesktopServices::openUrl( + QStringLiteral("https://docs.aws.amazon.com/lumberyard/latest/userguide/asset-bundler-overview.html")); + } + + void MainWindow::ShowLogContextMenu(const QPoint& pos) + { + QModelIndex index = m_ui->logTableView->indexAt(pos); + + QMenu menu; + + QAction* action = menu.addAction(tr("Copy line"), this, [&]() + { + QApplication::clipboard()->setText(index.data(AzToolsFramework::Logging::LogTableModel::LogLineTextRole).toString()); + }); + action->setEnabled(index.isValid()); + + menu.exec(m_ui->logTableView->mapToGlobal(pos)); + } + + bool MainWindow::HasUnsavedChanges() + { + return m_seedListTab->HasUnsavedChanges() || m_rulesTab->HasUnsavedChanges(); + } + + void MainWindow::SaveCurrentSelection() + { + switch (m_ui->tabWidget->currentIndex()) + { + case TabIndex::Seeds: + m_seedListTab->SaveCurrentSelection(); + break; + case TabIndex::Rules: + m_rulesTab->SaveCurrentSelection(); + break; + default: + break; + } + } + + void MainWindow::SaveAll() + { + m_seedListTab->SaveAll(); + m_rulesTab->SaveAll(); + } +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/MainWindow.h b/Code/Tools/AssetBundler/source/ui/MainWindow.h new file mode 100644 index 0000000000..e8c5570649 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/MainWindow.h @@ -0,0 +1,105 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#endif + +namespace Ui +{ + class MainWindow; +} + +namespace AssetBundler +{ + class GUIApplicationManager; + + class MainWindow + : public QMainWindow + , public AZ::Debug::TraceMessageBus::Handler + { + Q_OBJECT + + public: + + explicit MainWindow(AssetBundler::GUIApplicationManager* guiApplicationManager, QWidget* parent = 0); + virtual ~MainWindow(); + + void Activate(); + + void ApplyConfig(); + + void WriteToLog(const AZStd::string& message, AzToolsFramework::Logging::LogLine::LogType logType); + void WriteToLog(const QString& message, AzToolsFramework::Logging::LogLine::LogType logType); + void WriteToLog(const char* message, AzToolsFramework::Logging::LogLine::LogType logType); + void WriteToLog(const char* message, const char* window, AzToolsFramework::Logging::LogLine::LogType logType); + + ///////////////////////////////////////////////////////// + // TraceMessageBus overrides + bool OnPreError(const char* window, const char* fileName, int line, const char* func, const char* message) override; + bool OnPreWarning(const char* window, const char* fileName, int line, const char* func, const char* message) override; + bool OnPrintf(const char* window, const char* message) override; + ///////////////////////////////////////////////////////// + + public Q_SLOTS: + void ShowWindow(); + + protected: + void closeEvent(QCloseEvent* event) override; + + private: + QSharedPointer m_ui; + + // Tabs + QSharedPointer m_assetListTab; + QSharedPointer m_seedListTab; + QSharedPointer m_rulesTab; + QSharedPointer m_bundleListTab; + + enum TabIndex + { + Seeds, + AssetLists, + Rules, + Bundles, + MAX + }; + + void OnSupportClicked(); + + // Log + QSharedPointer m_logModel; + + void ShowLogContextMenu(const QPoint& pos); + + // Detecting Unsaved Changes + QSharedPointer m_unsavedChangesMsgBox; + + bool HasUnsavedChanges(); + void SaveCurrentSelection(); + void SaveAll(); + + AssetBundler::GUIApplicationManager* m_guiApplicationManager = nullptr; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/MainWindow.ui b/Code/Tools/AssetBundler/source/ui/MainWindow.ui new file mode 100644 index 0000000000..902652459f --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/MainWindow.ui @@ -0,0 +1,112 @@ + + + MainWindow + + + + 0 + 0 + 1200 + 1000 + + + + + 200 + 200 + + + + Asset Bundler + + + + + + + -1 + + + + + + + + 0 + 0 + + + + + + + + + + 0 + 0 + 1200 + 21 + + + + + File + + + + + + + + + Help + + + + + + + + + Save + + + + + Close + + + + + Documentation + + + + + About Asset Bundler + + + + + Save All + + + + + + AzQtComponents::TableView + QTreeView +
AzQtComponents/Components/Widgets/TableView.h
+ 1 +
+ + AzQtComponents::TabWidget + QTabWidget +
AzQtComponents/Components/Widgets/TabWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/NewFileDialog.cpp b/Code/Tools/AssetBundler/source/ui/NewFileDialog.cpp new file mode 100644 index 0000000000..170da4a659 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/NewFileDialog.cpp @@ -0,0 +1,224 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace AssetBundler +{ + NewFileDialog::NewFileDialog( + QWidget* parent, + const QString& dialogTitle, + const QString& startingPath, + const char* fileExtension, + const QString& fileNameFilter, + const AzFramework::PlatformFlags& enabledPlatforms, + bool isRunningRule) + : QDialog(parent) + , m_startingPath(startingPath) + , m_fileExtension(fileExtension) + { + m_ui.reset(new Ui::NewFileDialog); + m_ui->setupUi(this); + + setWindowTitle(dialogTitle); + + // Set up File Name section + m_ui->fileNameLineEdit->setEnabled(false); + connect(m_ui->browseButton, &QPushButton::clicked, this, &NewFileDialog::OnBrowseButtonPressed); + + m_newFileDialog.setFileMode(QFileDialog::AnyFile); + m_newFileDialog.setNameFilter(fileNameFilter); + m_newFileDialog.setViewMode(QFileDialog::Detail); + m_newFileDialog.setDirectory(m_startingPath); + // We are not creating a new file when Qt thinks we are, so we need to block signals or else the file watcher will be triggered too soon + m_newFileDialog.blockSignals(true); + + // Set up Platform selection + QString disabledPatformMessageOverride; + if (isRunningRule) + { + disabledPatformMessageOverride = tr("This platform is not valid for all input Asset Lists."); + } + m_ui->platformSelectionWidget->Init(enabledPlatforms, disabledPatformMessageOverride); + connect(m_ui->platformSelectionWidget, &PlatformSelectionWidget::PlatformsSelected, this, &NewFileDialog::OnPlatformSelectionChanged); + + // Set up Cancel and Create New File buttons + m_ui->createFileButton->setEnabled(false); + connect(m_ui->cancelButton, &QPushButton::clicked, this, &QDialog::reject); + connect(m_ui->createFileButton, &QPushButton::clicked, this, &NewFileDialog::OnCreateFileButtonPressed); + } + + AZStd::string NewFileDialog::GetAbsoluteFilePath() + { + return m_absoluteFilePath; + } + + AzFramework::PlatformFlags NewFileDialog::GetPlatformFlags() + { + return m_ui->platformSelectionWidget->GetSelectedPlatforms(); + } + + void NewFileDialog::OnBrowseButtonPressed() + { + int result = m_newFileDialog.exec(); + if (result == QDialog::DialogCode::Accepted) + { + m_absoluteFilePath = m_newFileDialog.selectedFiles()[0].toUtf8().data(); + AzToolsFramework::RemovePlatformIdentifier(m_absoluteFilePath); + + if (m_fileExtension && !AzFramework::StringFunc::Path::HasExtension(m_absoluteFilePath.c_str())) + { + m_absoluteFilePath.append("."); + m_absoluteFilePath.append(m_fileExtension); + } + + m_ui->fileNameLineEdit->setEnabled(true); + m_ui->fileNameLineEdit->setText(m_absoluteFilePath.c_str()); + } + + m_fileNameIsValid = !m_absoluteFilePath.empty(); + m_ui->createFileButton->setEnabled(m_platformIsValid && m_fileNameIsValid); + } + + void NewFileDialog::OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms) + { + // Hide the "Create File" button if no platforms are selected + m_platformIsValid = selectedPlatforms != AzFramework::PlatformFlags::Platform_NONE; + m_ui->createFileButton->setEnabled(m_platformIsValid && m_fileNameIsValid); + } + + void NewFileDialog::OnCreateFileButtonPressed() + { + // Check to see if any of the selected platform-specific files already exist on-disk + QString overwriteExistingFilesList; + AZStd::fixed_vector selectedPlatformNames = AzFramework::PlatformHelper::GetPlatforms(GetPlatformFlags()); + for (const AZStd::string& platformName : selectedPlatformNames) + { + FilePath platformSpecificFilePath(GetAbsoluteFilePath(), platformName); + const char* platformSpecificFileAbsolutePath = platformSpecificFilePath.AbsolutePath().c_str(); + if (AZ::IO::FileIOBase::GetInstance()->Exists(platformSpecificFileAbsolutePath)) + { + overwriteExistingFilesList.append(QString("%1\n").arg(platformSpecificFileAbsolutePath)); + } + } + + // Ask the user if they are sure they want to overwrite existing files + if (!overwriteExistingFilesList.isEmpty()) + { + QString messageBoxText = QString(tr("The following files already exist on-disk. Generating new files will overwrite the existing ones.\n\n%1\n\nDo you wish to permanently delete the existing files?")).arg(overwriteExistingFilesList); + + QMessageBox::StandardButton confirmDeleteFileResult = QMessageBox::question(this, QString(tr("Replace Existing Files")), messageBoxText); + if (confirmDeleteFileResult != QMessageBox::StandardButton::Yes) + { + // User canceled out of the operation + return; + } + } + + emit QDialog::accept(); + } + + AZStd::string NewFileDialog::OSNewFileDialog(QWidget* parent, const char* fileExtension, const char* fileTypeDisplayName, const AZStd::string& startingDirectory) + { + QFileDialog filePathDialog(parent); + filePathDialog.setFileMode(QFileDialog::AnyFile); + filePathDialog.setNameFilter(QString(tr("%1 (*.%2)")).arg(fileTypeDisplayName).arg(fileExtension)); + filePathDialog.setViewMode(QFileDialog::Detail); + filePathDialog.setDirectory(startingDirectory.c_str()); + + // Since we handle file creation instead of the OS, we have to block signals or else the model will be reloaded, + // and our in-memory changes will be lost. + filePathDialog.blockSignals(true); + int result = filePathDialog.exec(); + if (result == QDialog::DialogCode::Rejected || filePathDialog.selectedFiles().empty()) + { + // User canceled out of the file dialog, cancel operation + return ""; + } + + AZStd::string absoluteFilePath(filePathDialog.selectedFiles()[0].toUtf8().data()); + if (!AzFramework::StringFunc::Path::HasExtension(absoluteFilePath.c_str())) + { + absoluteFilePath = AZStd::string::format("%s%c%s", absoluteFilePath.c_str(), AZ_FILESYSTEM_EXTENSION_SEPARATOR, fileExtension); + } + + return absoluteFilePath; + } + + int NewFileDialog::FileGenerationResultMessageBox(QWidget* parent, const AZStd::vector& generatedFiles, bool generatedWithErrors) + { + QMessageBox messageBox(parent); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.setDefaultButton(QMessageBox::Ok); + + if (generatedFiles.empty()) + { + messageBox.setText(QString("No files were generated. Please refer to the console for more information.")); + messageBox.setIcon(QMessageBox::Critical); + return messageBox.exec(); + } + + QString messageText; + if (generatedWithErrors) + { + messageText = QString("The following files were generated with errors. Please refer to the console for more information.\n\n"); + messageBox.setIcon(QMessageBox::Warning); + } + else + { + messageText = QString("You have successfully generated:\n\n"); + messageBox.setIcon(QMessageBox::NoIcon); + } + + AZStd::string fileName; + for (const AZStd::string& filePath : generatedFiles) + { + AzFramework::StringFunc::Path::GetFullFileName(filePath.c_str(), fileName); + messageText.append(QString("%1\n").arg(fileName.c_str())); + } + + AZStd::string extension; + AzFramework::StringFunc::Path::GetExtension(fileName.c_str(), extension, false); + if (extension == AzToolsFramework::AssetSeedManager::GetAssetListFileExtension()) + { + messageText.append("\nVisit the Asset Lists tab to see the lists."); + } + else if (extension == AzToolsFramework::AssetBundleSettings::GetBundleFileExtension()) + { + messageText.append("\nVisit the Completed Bundles tab to see the bundles."); + } + + messageBox.setText(messageText); + + // QMessageBoxes try to shrink to the smallest size possible, so we need to make a spacer + QSpacerItem* horizontalSpacer = new QSpacerItem(550, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); + QGridLayout* layout = static_cast(messageBox.layout()); + layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount()); + + return messageBox.exec(); + } + +} //namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/NewFileDialog.h b/Code/Tools/AssetBundler/source/ui/NewFileDialog.h new file mode 100644 index 0000000000..5974d3da6a --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/NewFileDialog.h @@ -0,0 +1,73 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include + +#include +#include +#include +#endif + +namespace Ui +{ + class NewFileDialog; +} + +namespace AssetBundler +{ + class GUIApplicationManager; + + class NewFileDialog + : public QDialog + { + Q_OBJECT + + public: + explicit NewFileDialog( + QWidget* parent, + const QString& dialogTitle, + const QString& startingPath, + const char* fileExtension, + const QString& fileNameFilter, + const AzFramework::PlatformFlags& enabledPlatforms, + bool isRunningRule = false); + virtual ~NewFileDialog() {} + + AZStd::string GetAbsoluteFilePath(); + AzFramework::PlatformFlags GetPlatformFlags(); + + //! A standard OS-specific New File Dialog, but blocks all Qt signals from the dialog and does NOT create a new file. + //! Use in place of the static QFileDialog functions to avoid unexpected file watcher updates. + //! Returns the absolute path of the file the user either selected or attempted to create, or an empty string if the user canceled out of the dialog. + static AZStd::string OSNewFileDialog(QWidget* parent, const char* fileExtension, const char* fileTypeDisplayName, const AZStd::string& startingDirectory); + + static int FileGenerationResultMessageBox(QWidget* parent, const AZStd::vector& generatedFiles, bool generatedWithErrors); + + private: + void OnBrowseButtonPressed(); + void OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms); + void OnCreateFileButtonPressed(); + + QSharedPointer m_ui; + QString m_startingPath; + const char* m_fileExtension; + QFileDialog m_newFileDialog; + + AZStd::string m_absoluteFilePath; + + bool m_fileNameIsValid = false; + bool m_platformIsValid = false; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/NewFileDialog.ui b/Code/Tools/AssetBundler/source/ui/NewFileDialog.ui new file mode 100644 index 0000000000..17d439549c --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/NewFileDialog.ui @@ -0,0 +1,154 @@ + + + NewFileDialog + + + Qt::ApplicationModal + + + + 0 + 0 + 450 + 90 + + + + + 0 + 0 + + + + + 450 + 0 + + + + Dialog + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Save As: + + + + + + + true + + + + + + + Browse... + + + + + + + + + + + + + + + 10 + + + 10 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + false + + + + + + + Create New File + + + true + + + + + + + + + + AssetBundler::PlatformSelectionWidget + QWidget +
source/ui/PlatformSelectionWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.cpp b/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.cpp new file mode 100644 index 0000000000..80b4590c3c --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.cpp @@ -0,0 +1,126 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include + +namespace AssetBundler +{ + + PlatformSelectionWidget::PlatformSelectionWidget(QWidget* parent) + : QWidget(parent) + { + m_ui.reset(new Ui::PlatformSelectionWidget); + m_ui->setupUi(this); + + m_platformHelper.reset(new AzFramework::PlatformHelper); + + m_selectedPlatforms = AzFramework::PlatformFlags::Platform_NONE; + m_partiallySelectedPlatforms = AzFramework::PlatformFlags::Platform_NONE; + } + + void PlatformSelectionWidget::Init(const AzFramework::PlatformFlags& enabledPlatforms, const QString& disabledPatformMessageOverride) + { + using namespace AzFramework; + + // Set up Platform Checkboxes + for (const AZStd::string_view& platformString : m_platformHelper->GetPlatforms(PlatformFlags::AllNamedPlatforms)) + { + // Create the CheckBox and store what platform it maps to + QSharedPointer platformCheckBox(new QCheckBox(QString::fromUtf8(platformString.data(), platformString.size()))); + m_platformCheckBoxes.push_back(platformCheckBox); + PlatformFlags currentPlatformFlag = m_platformHelper->GetPlatformFlag(platformString); + m_platformList.push_back(currentPlatformFlag); + + // Add the CheckBox to the view + m_ui->platformCheckBoxLayout->addWidget(platformCheckBox.data()); + + // If the platform is not enabled for the current project, disable it and tell the user + if ((enabledPlatforms & currentPlatformFlag) == PlatformFlags::Platform_NONE) + { + platformCheckBox->setEnabled(false); + if (disabledPatformMessageOverride.isEmpty()) + { + platformCheckBox->setToolTip(tr("This platform is not enabled for the current project.")); + } + else + { + platformCheckBox->setToolTip(disabledPatformMessageOverride); + } + } + else + { + connect(platformCheckBox.data(), &QCheckBox::stateChanged, this, &PlatformSelectionWidget::OnPlatformSelectionChanged); + } + } + } + + void PlatformSelectionWidget::SetSelectedPlatforms(const AzFramework::PlatformFlags& selectedPlatforms, const AzFramework::PlatformFlags& partiallySelectedPlatforms) + { + m_selectedPlatforms = AzFramework::PlatformFlags::Platform_NONE; + m_partiallySelectedPlatforms = AzFramework::PlatformFlags::Platform_NONE; + for (int checkBoxIndex = 0; checkBoxIndex < m_platformCheckBoxes.size(); ++checkBoxIndex) + { + AzFramework::PlatformFlags checkBoxPlatform = m_platformList[checkBoxIndex]; + bool isSelected = (checkBoxPlatform & selectedPlatforms) != AzFramework::PlatformFlags::Platform_NONE; + m_platformCheckBoxes[checkBoxIndex]->setChecked(isSelected); + if (isSelected) + { + m_selectedPlatforms |= checkBoxPlatform; + } + + // Set the check status to Qt::PartiallyChecked when some of the selected items support the current platform + bool isPartiallySelected = (checkBoxPlatform & partiallySelectedPlatforms) != AzFramework::PlatformFlags::Platform_NONE; + if (isPartiallySelected) + { + m_platformCheckBoxes[checkBoxIndex]->setCheckState(Qt::PartiallyChecked); + m_partiallySelectedPlatforms |= checkBoxPlatform; + } + } + + emit PlatformsSelected(m_selectedPlatforms, m_partiallySelectedPlatforms); + } + + AzFramework::PlatformFlags PlatformSelectionWidget::GetSelectedPlatforms() + { + return m_selectedPlatforms; + } + + AzFramework::PlatformFlags PlatformSelectionWidget::GetPartiallySelectedPlatforms() + { + return m_partiallySelectedPlatforms; + } + + void PlatformSelectionWidget::OnPlatformSelectionChanged() + { + m_selectedPlatforms = AzFramework::PlatformFlags::Platform_NONE; + m_partiallySelectedPlatforms = AzFramework::PlatformFlags::Platform_NONE; + for (int checkBoxIndex = 0; checkBoxIndex < m_platformCheckBoxes.size(); ++checkBoxIndex) + { + if (m_platformCheckBoxes[checkBoxIndex]->checkState() == Qt::Checked) + { + m_selectedPlatforms |= m_platformList[checkBoxIndex]; + } + else if (m_platformCheckBoxes[checkBoxIndex]->checkState() == Qt::PartiallyChecked) + { + m_partiallySelectedPlatforms |= m_platformList[checkBoxIndex]; + } + } + + emit PlatformsSelected(m_selectedPlatforms, m_partiallySelectedPlatforms); + } + +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.h b/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.h new file mode 100644 index 0000000000..223044478f --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.h @@ -0,0 +1,62 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include + +#include +#include +#include +#endif + +namespace Ui +{ + class PlatformSelectionWidget; +} + +namespace AssetBundler +{ + class PlatformSelectionWidget + : public QWidget + { + Q_OBJECT + + public: + explicit PlatformSelectionWidget(QWidget* parent); + virtual ~PlatformSelectionWidget() {} + + void Init(const AzFramework::PlatformFlags& enabledPlatforms, const QString& disabledPatformMessageOverride = ""); + + void SetSelectedPlatforms(const AzFramework::PlatformFlags& selectedPlatforms, const AzFramework::PlatformFlags& partiallySelectedPlatforms); + + AzFramework::PlatformFlags GetSelectedPlatforms(); + AzFramework::PlatformFlags GetPartiallySelectedPlatforms(); + + Q_SIGNALS: + void PlatformsSelected(AzFramework::PlatformFlags selectedPlatforms, AzFramework::PlatformFlags partiallySelectedPlatforms); + + private: + void OnPlatformSelectionChanged(); + + QSharedPointer m_ui; + AZStd::unique_ptr m_platformHelper; + + QVector> m_platformCheckBoxes; + AZStd::vector m_platformList; + + AzFramework::PlatformFlags m_selectedPlatforms; + AzFramework::PlatformFlags m_partiallySelectedPlatforms; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.ui b/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.ui new file mode 100644 index 0000000000..d2ecb61e64 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.ui @@ -0,0 +1,49 @@ + + + PlatformSelectionWidget + + + + 0 + 0 + 400 + 300 + + + + Form + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Platforms: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + + + diff --git a/Code/Tools/AssetBundler/source/ui/RulesTabWidget.cpp b/Code/Tools/AssetBundler/source/ui/RulesTabWidget.cpp new file mode 100644 index 0000000000..56447f4a57 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/RulesTabWidget.cpp @@ -0,0 +1,432 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +namespace AssetBundler +{ + RulesTabWidget::RulesTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager) + : AssetBundlerTabWidget(parent, guiApplicationManager) + { + m_ui.reset(new Ui::RulesTabWidget); + m_ui->setupUi(this); + + m_ui->mainVerticalLayout->setContentsMargins(MarginSize, MarginSize, MarginSize, MarginSize); + + m_fileTableModel.reset(new RulesFileTableModel); + m_ui->fileTableView->setModel(m_fileTableModel.data()); + + // Table View of all Rules files + m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(this, m_fileTableModel->GetFileNameColumnIndex(), m_fileTableModel->GetTimeStampColumnIndex())); + + m_fileTableFilterModel->setSourceModel(m_fileTableModel.data()); + m_ui->fileTableView->setModel(m_fileTableFilterModel.data()); + connect(m_ui->fileFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, + m_fileTableFilterModel.data(), static_cast(&AssetBundlerFileTableFilterModel::FilterChanged)); + + connect(m_ui->fileTableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RulesTabWidget::FileSelectionChanged); + + m_ui->fileTableView->setIndentation(0); + + // New File Button + connect(m_ui->createNewFileButton, &QPushButton::clicked, this, &RulesTabWidget::OnNewFileButtonPressed); + + // Run Rule Button + m_ui->runRuleButton->setEnabled(false); + connect(m_ui->runRuleButton, &QPushButton::clicked, this, &RulesTabWidget::OnRunRuleButtonPressed); + + // Add Comparison Step button + connect(m_ui->addComparisonStepButton, &QPushButton::clicked, this, &RulesTabWidget::AddNewComparisonStep); + + SetModelDataSource(); + } + + bool RulesTabWidget::HasUnsavedChanges() + { + return m_fileTableModel->HasUnsavedChanges(); + } + + void RulesTabWidget::Reload() + { + m_fileTableModel->Reload(AzToolsFramework::AssetFileInfoListComparison::GetComparisonRulesFileExtension(), m_watchedFolders, m_watchedFiles); + FileSelectionChanged(); + } + + bool RulesTabWidget::SaveCurrentSelection() + { + return m_fileTableModel->Save(m_selectedFileTableIndex); + } + + bool RulesTabWidget::SaveAll() + { + return m_fileTableModel->SaveAll(); + } + + void RulesTabWidget::SetModelDataSource() + { + // Remove the current watched folders and files + m_guiApplicationManager->RemoveWatchedPaths(m_watchedFolders + m_watchedFiles); + + // Set the new watched folder for the model + m_watchedFolders.clear(); + m_watchedFiles.clear(); + m_watchedFolders.insert(m_guiApplicationManager->GetRulesFolder().c_str()); + ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType::RulesFileType); + + m_guiApplicationManager->AddWatchedPaths(m_watchedFolders + m_watchedFiles); + } + + AzQtComponents::TableView* RulesTabWidget::GetFileTableView() + { + return m_ui->fileTableView; + } + + QModelIndex RulesTabWidget::GetSelectedFileTableIndex() + { + return m_selectedFileTableIndex; + } + + AssetBundlerAbstractFileTableModel* RulesTabWidget::GetFileTableModel() + { + return m_fileTableModel.get(); + } + + void RulesTabWidget::SetActiveProjectLabel(const QString& labelText) + { + m_ui->activeProjectLabel->setText(labelText); + } + + void RulesTabWidget::ApplyConfig() + { + const GUIApplicationManager::Config& config = m_guiApplicationManager->GetConfig(); + m_ui->fileTableFrame->setFixedWidth(config.fileTableWidth); + m_ui->fileTableView->header()->resizeSection(RulesFileTableModel::Column::ColumnFileName, config.fileNameColumnWidth); + } + + + void RulesTabWidget::FileSelectionChanged(const QItemSelection& /*selected*/, const QItemSelection& /*deselected*/) + { + if (m_ui->fileTableView->selectionModel()->selectedRows().size() == 0) + { + m_selectedFileTableIndex = QModelIndex(); + m_selectedComparisonRules = nullptr; + m_ui->runRuleButton->setEnabled(false); + m_ui->addComparisonStepButton->setEnabled(false); + m_ui->rulesFileAbsolutePathLabel->clear(); + RemoveAllComparisonDataCards(); + + return; + } + + m_ui->runRuleButton->setEnabled(true); + m_ui->addComparisonStepButton->setEnabled(true); + + m_selectedFileTableIndex = m_fileTableFilterModel->mapToSource(m_ui->fileTableView->selectionModel()->selectedRows()[0]); + m_selectedComparisonRules = m_fileTableModel->GetComparisonSteps(m_selectedFileTableIndex); + + m_ui->rulesFileAbsolutePathLabel->setText(m_fileTableModel->GetFileAbsolutePath(m_selectedFileTableIndex).c_str()); + + RebuildComparisonDataCardList(); + } + + void RulesTabWidget::OnNewFileButtonPressed() + { + AZStd::string absoluteFilePath = NewFileDialog::OSNewFileDialog( + this, + AzToolsFramework::AssetFileInfoListComparison::GetComparisonRulesFileExtension(), + "Comparison Rules", + m_guiApplicationManager->GetRulesFolder()); + + if (absoluteFilePath.empty()) + { + // User canceled out of the dialog + return; + } + + AZStd::vector createdFile = m_fileTableModel->CreateNewFiles(absoluteFilePath); + if (!createdFile.empty()) + { + AddScanPathToAssetBundlerSettings(AssetBundlingFileType::RulesFileType, createdFile.at(0)); + } + } + + void RulesTabWidget::OnRunRuleButtonPressed() + { + using namespace AzToolsFramework; + + // Determine which platforms all of the input Asset List files have in common + AzFramework::PlatformFlags commonPlatforms = AzFramework::PlatformFlags::AllNamedPlatforms; + for (const AssetFileInfoListComparison::ComparisonData& comparisonStep : m_selectedComparisonRules->GetComparisonList()) + { + if (!comparisonStep.m_cachedFirstInputPath.empty()) + { + commonPlatforms = commonPlatforms & GetPlatformsOnDiskForPlatformSpecificFile(comparisonStep.m_cachedFirstInputPath); + } + + if (!comparisonStep.m_cachedSecondInputPath.empty()) + { + commonPlatforms = commonPlatforms & GetPlatformsOnDiskForPlatformSpecificFile(comparisonStep.m_cachedSecondInputPath); + } + } + + if (commonPlatforms == AzFramework::PlatformFlags::Platform_NONE) + { + AZ_Error("AssetBundler", false, "Unable to run Rule: Input Asset List files have no platforms in common."); + return; + } + + // Prompt the user to select an output path and the platforms to run the rule on + NewFileDialog runRuleDialog = NewFileDialog( + this, + "Run Rule", + QString(m_guiApplicationManager->GetAssetListsFolder().c_str()), + AzToolsFramework::AssetSeedManager::GetAssetListFileExtension(), + QString(tr("Asset List (*.%1)")).arg(AzToolsFramework::AssetSeedManager::GetAssetListFileExtension()), + commonPlatforms, + true); + + auto dialogResponse = runRuleDialog.exec(); + if (dialogResponse == QDialog::DialogCode::Rejected) + { + // User canceled the operation + return; + } + + AZStd::vector outputFilePaths; + bool hasFileGenerationErrors = false; + + AZStd::fixed_vector selectedPlatformNames = AzFramework::PlatformHelper::GetPlatforms(runRuleDialog.GetPlatformFlags()); + for (const AZStd::string& platformName : selectedPlatformNames) + { + // We do not want to modify the original Rules file, as we do not save Asset List file paths to disk + AssetFileInfoListComparison currentFileCopy = *m_selectedComparisonRules.get(); + + //Update the first and second input values with any non-token Asset List file paths that have been set, + size_t numComparisonSteps = currentFileCopy.GetNumComparisonSteps(); + for (size_t comparisonStepIndex = 0; comparisonStepIndex < numComparisonSteps; ++comparisonStepIndex) + { + AssetFileInfoListComparison::ComparisonData comparisonStep = currentFileCopy.GetComparisonList()[comparisonStepIndex]; + if (comparisonStep.m_firstInput.empty()) + { + if (comparisonStep.m_cachedFirstInputPath.empty()) + { + AZ_Error("AssetBundler", false, "Unable to run Rule: Comparison Step #%u has no specified first input.", comparisonStepIndex); + return; + } + + FilePath firstInput = FilePath(comparisonStep.m_cachedFirstInputPath, platformName); + currentFileCopy.SetFirstInput(comparisonStepIndex, firstInput.AbsolutePath()); + } + + if (comparisonStep.m_comparisonType != AssetFileInfoListComparison::ComparisonType::FilePattern + && comparisonStep.m_secondInput.empty()) + { + if (comparisonStep.m_cachedSecondInputPath.empty()) + { + AZ_Error("AssetBundler", false, "Unable to run Rule: Comparison Step #%u has no specified second input.", comparisonStepIndex); + return; + } + + FilePath secondInput = FilePath(comparisonStep.m_cachedSecondInputPath, platformName); + currentFileCopy.SetSecondInput(comparisonStepIndex, secondInput.AbsolutePath()); + } + } + + // Set the output location of the Asset List file that will be generated + FilePath finalOutputPath = FilePath(runRuleDialog.GetAbsoluteFilePath(), platformName); + currentFileCopy.SetOutput(numComparisonSteps - 1, finalOutputPath.AbsolutePath()); + + //Run the Rule + auto compareOutcome = currentFileCopy.CompareAndSaveResults(); + if (compareOutcome.IsSuccess()) + { + outputFilePaths.emplace_back(finalOutputPath.AbsolutePath()); + } + else + { + hasFileGenerationErrors = true; + AZ_Error("AssetBundler", false, compareOutcome.GetError().c_str()); + } + } + + // Add created files to the file watcher + for (const AZStd::string& absolutePath : outputFilePaths) + { + AddScanPathToAssetBundlerSettings(AssetBundlingFileType::AssetListFileType, absolutePath); + } + + // The watched files list was updated after the files were created, so we need to force-reload them + m_guiApplicationManager->UpdateFiles(AssetBundlingFileType::AssetListFileType, outputFilePaths); + + NewFileDialog::FileGenerationResultMessageBox(this, outputFilePaths, hasFileGenerationErrors); + } + + void RulesTabWidget::MarkFileChanged() + { + m_fileTableModel->MarkFileChanged(m_selectedFileTableIndex); + } + + void RulesTabWidget::RebuildComparisonDataCardList() + { + RemoveAllComparisonDataCards(); + PopulateComparisonDataCardList(); + } + + void RulesTabWidget::PopulateComparisonDataCardList() + { + if (!m_selectedComparisonRules) + { + return; + } + + for (int index = 0; index < m_selectedComparisonRules->GetComparisonList().size(); ++index) + { + CreateComparisonDataCard(m_selectedComparisonRules, static_cast(index)); + } + } + + void RulesTabWidget::CreateComparisonDataCard(AZStd::shared_ptr comparisonList, size_t comparisonDataIndex) + { + ComparisonDataCard* comparisonDataCard = new ComparisonDataCard(comparisonList, comparisonDataIndex, m_guiApplicationManager->GetAssetListsFolder()); + comparisonDataCard->setTitle(tr("Step %1").arg(static_cast(comparisonDataIndex) + 1)); + m_ui->comparisonDataListLayout->addWidget(comparisonDataCard); + m_comparisonDataCardList.push_back(comparisonDataCard); + + ComparisonDataWidget* comparisonDataWidget = comparisonDataCard->GetComparisonDataWidget(); + connect(comparisonDataCard, &ComparisonDataCard::comparisonDataCardContextMenuRequested, this, &RulesTabWidget::OnComparisonDataCardContextMenuRequested); + connect(comparisonDataWidget, &ComparisonDataWidget::comparisonDataChanged, this, &RulesTabWidget::MarkFileChanged); + connect(comparisonDataWidget, &ComparisonDataWidget::comparisonDataTokenNameChanged, this, &RulesTabWidget::OnAnyTokenNameChanged); + + comparisonDataCard->show(); + } + + void RulesTabWidget::RemoveAllComparisonDataCards() + { + m_comparisonDataCardList.clear(); + + while (!m_ui->comparisonDataListLayout->isEmpty()) + { + QLayoutItem* item = m_ui->comparisonDataListLayout->takeAt(0); + item->widget()->hide(); + delete item; + } + } + + void RulesTabWidget::AddNewComparisonStep() + { + if (!m_selectedComparisonRules) + { + return; + } + + if (!m_selectedComparisonRules->AddComparisonStep(AzToolsFramework::AssetFileInfoListComparison::ComparisonData())) + { + return; + } + + CreateComparisonDataCard(m_selectedComparisonRules, m_selectedComparisonRules->GetComparisonList().size() - 1); + MarkFileChanged(); + } + + void RulesTabWidget::RemoveComparisonStep(size_t comparisonDataIndex) + { + if (!m_selectedComparisonRules) + { + return; + } + + if (m_selectedComparisonRules->RemoveComparisonStep(comparisonDataIndex)) + { + MarkFileChanged(); + RebuildComparisonDataCardList(); + } + } + + void RulesTabWidget::MoveComparisonStep(size_t startingIndex, size_t destinationIndex) + { + if (!m_selectedComparisonRules) + { + return; + } + + if (m_selectedComparisonRules->MoveComparisonStep(startingIndex, destinationIndex)) + { + MarkFileChanged(); + RebuildComparisonDataCardList(); + } + } + + void RulesTabWidget::OnAnyTokenNameChanged(size_t comparisonDataIndex) + { + if (comparisonDataIndex >= m_comparisonDataCardList.size() - 1) + { + return; + } + + for (size_t i = comparisonDataIndex + 1; i < m_comparisonDataCardList.size(); ++i) + { + m_comparisonDataCardList[i]->GetComparisonDataWidget()->UpdateListOfTokenNames(); + } + } + + void RulesTabWidget::OnComparisonDataCardContextMenuRequested(size_t comparisonDataIndex, const QPoint& position) + { + if (!m_selectedComparisonRules) + { + return; + } + + QMenu menu; + + QAction* moveUpAction = new QAction(tr("Move Up"), this); + moveUpAction->setEnabled(comparisonDataIndex > 0); + connect(moveUpAction, &QAction::triggered, this, [=]() { MoveComparisonStep(comparisonDataIndex, comparisonDataIndex - 1); }); + menu.addAction(moveUpAction); + + QAction* moveDownAction = new QAction(tr("Move Down"), this); + moveDownAction->setEnabled(comparisonDataIndex < m_selectedComparisonRules->GetNumComparisonSteps() - 1); + connect(moveDownAction, &QAction::triggered, this, [=]() { MoveComparisonStep(comparisonDataIndex, comparisonDataIndex + 2); }); + menu.addAction(moveDownAction); + + QAction* separator = new QAction(this); + separator->setSeparator(true); + menu.addAction(separator); + + QAction* deleteAction = new QAction(tr("Remove Comparison Step"), this); + connect(deleteAction, &QAction::triggered, this, [=]() { RemoveComparisonStep(comparisonDataIndex); }); + menu.addAction(deleteAction); + + menu.exec(position); + } + +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/RulesTabWidget.h b/Code/Tools/AssetBundler/source/ui/RulesTabWidget.h new file mode 100644 index 0000000000..7dedce3efe --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/RulesTabWidget.h @@ -0,0 +1,120 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +#include + +#include +#include +#include +#include +#include +#endif + +namespace Ui +{ + class RulesTabWidget; +} + +class QItemSelection; + +namespace AzToolsFramework +{ + class AssetFileInfoListComparison; +} + +namespace AssetBundler +{ + class GUIApplicationManager; + + class RulesFileTableModel; + + class ComparisonDataCard; + + class ComparisonDataWidget; + + class RulesTabWidget + : public AssetBundlerTabWidget + { + Q_OBJECT + + public: + explicit RulesTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager); + virtual ~RulesTabWidget() {} + + QString GetTabTitle() override { return tr("Rules"); } + + QString GetFileTypeDisplayName() override { return tr("Rules file"); } + + AssetBundlingFileType GetFileType() override { return AssetBundlingFileType::RulesFileType; } + + bool HasUnsavedChanges() override; + + void Reload() override; + + bool SaveCurrentSelection() override; + + bool SaveAll() override; + + void SetModelDataSource() override; + + AzQtComponents::TableView* GetFileTableView() override; + + QModelIndex GetSelectedFileTableIndex() override; + + AssetBundlerAbstractFileTableModel* GetFileTableModel() override; + + void SetActiveProjectLabel(const QString& labelText) override; + + void ApplyConfig() override; + + void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) override; + + private: + void OnNewFileButtonPressed(); + + void OnRunRuleButtonPressed(); + + void MarkFileChanged(); + + void RebuildComparisonDataCardList(); + + void PopulateComparisonDataCardList(); + + void CreateComparisonDataCard(AZStd::shared_ptr comparisonList, size_t comparisonDataIndex); + + void RemoveAllComparisonDataCards(); + + void AddNewComparisonStep(); + + void RemoveComparisonStep(size_t comparisonDataIndex); + + void MoveComparisonStep(size_t startingIndex, size_t destinationIndex); + + void OnAnyTokenNameChanged(size_t comparisonDataIndex); + + QSharedPointer m_ui; + + QSharedPointer m_fileTableModel; + QModelIndex m_selectedFileTableIndex; + AZStd::shared_ptr m_selectedComparisonRules; + + AZStd::vector m_comparisonDataCardList; + + private slots: + void OnComparisonDataCardContextMenuRequested(size_t comparisonDataIndex, const QPoint& position); + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/RulesTabWidget.ui b/Code/Tools/AssetBundler/source/ui/RulesTabWidget.ui new file mode 100644 index 0000000000..f7eec0a796 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/RulesTabWidget.ui @@ -0,0 +1,312 @@ + + + RulesTabWidget + + + + 0 + 0 + 1180 + 728 + + + + Rules Tab Widget + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Run Selected Rule + + + true + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Rules + + + + + + + + + + Filter by file name + + + + + + + 5 + + + 5 + + + + + + Create new Rules file + + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Comparison Steps + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 5 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Add Step + + + + + + + + + true + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + 0 + 0 + 573 + 614 + + + + + 0 + 0 + + + + + 12 + + + 10 + + + 10 + + + 10 + + + 0 + + + + + + + + Qt::Vertical + + + + 40 + 20 + + + + + + + + + + + + + + + + + + AzQtComponents::TableView + QTreeView +
AzQtComponents/Components/Widgets/TableView.h
+ 1 +
+ + AzQtComponents::FilteredSearchWidget + QTreeView +
AzQtComponents/Components/FilteredSearchWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/SeedTabWidget.cpp b/Code/Tools/AssetBundler/source/ui/SeedTabWidget.cpp new file mode 100644 index 0000000000..b05a2e0c90 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/SeedTabWidget.cpp @@ -0,0 +1,453 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +const char GenerateAssetListFilesDialogName[] = "Generate Asset List Files"; + +const int CheckBoxTableIndentationSize = 2; // when the indentation is 0, the checkboxes are too close to the edge + +namespace AssetBundler +{ + SeedTabWidget::SeedTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager, const QString& assetBundlingDirectory) + : AssetBundlerTabWidget(parent, guiApplicationManager) + , m_fileTableModel(new SeedListFileTableModel(this)) + , m_seedListContentsModel(new SeedListTableModel()) + { + AZ_UNUSED(assetBundlingDirectory); + + m_ui.reset(new Ui::SeedTabWidget); + m_ui->setupUi(this); + + m_ui->mainVerticalLayout->setContentsMargins(MarginSize, MarginSize, MarginSize, MarginSize); + + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + + // File view of all Seed List Files + m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(this, m_fileTableModel->GetFileNameColumnIndex(), m_fileTableModel->GetTimeStampColumnIndex())); + + m_fileTableFilterModel->setSourceModel(m_fileTableModel.data()); + m_ui->fileTableView->setModel(m_fileTableFilterModel.data()); + connect(m_ui->fileFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, + m_fileTableFilterModel.data(), static_cast(&AssetBundlerFileTableFilterModel::FilterChanged)); + + connect(m_ui->fileTableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &SeedTabWidget::FileSelectionChanged); + + m_ui->fileTableView->setIndentation(CheckBoxTableIndentationSize); + + // New File Button + connect(m_ui->createNewSeedListButton, &QPushButton::clicked, this, &SeedTabWidget::OnNewFileButtonPressed); + + // Select Default Seed Lists + connect(m_ui->selectDefaultSeedListsCheckBox, &QCheckBox::clicked, this, &SeedTabWidget::OnSelectDefaultSeedListsCheckBoxChanged); + + // Generate Asset Lists Button + SetGenerateAssetListsButtonEnabled(false); + connect(m_ui->generateAssetListsButton, &QPushButton::clicked, this, &SeedTabWidget::OnGenerateAssetListsButtonPressed); + + // Table that displays the contents of a Seed List File + m_seedListContentsFilterModel.reset(new AssetBundlerFileTableFilterModel(this, SeedListTableModel::Column::ColumnRelativePath)); + + m_seedListContentsFilterModel->setSourceModel(m_seedListContentsModel.data()); + m_ui->seedFileContentsTable->setModel(m_seedListContentsFilterModel.data()); + connect(m_ui->seedListContentsFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, + m_seedListContentsFilterModel.data(), static_cast(&AssetBundlerFileTableFilterModel::FilterChanged)); + + m_ui->seedFileContentsTable->setContextMenuPolicy(Qt::CustomContextMenu); + connect(m_ui->seedFileContentsTable, &QTreeView::customContextMenuRequested, this, &SeedTabWidget::OnSeedListContentsTableContextMenuRequested); + + m_ui->seedFileContentsTable->setIndentation(0); + + // Edit All Platforms + connect(m_ui->editAllSeedsButton, &QPushButton::clicked, this, &SeedTabWidget::OnEditAllButtonPressed); + + // Add Seed + connect(m_ui->addSeedButton, &QPushButton::clicked, this, &SeedTabWidget::OnAddSeedButtonPressed); + + SetModelDataSource(); + } + + SeedTabWidget::~SeedTabWidget() + { + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + } + + bool SeedTabWidget::HasUnsavedChanges() + { + return m_fileTableModel->HasUnsavedChanges(); + } + + void SeedTabWidget::Reload() + { + // Reload all the seed list files + m_fileTableModel->Reload(AzToolsFramework::AssetSeedManager::GetSeedFileExtension(), m_watchedFolders, m_watchedFiles, m_filePathToGemNameMap); + + // Update the selected row + FileSelectionChanged(); + } + + bool SeedTabWidget::SaveCurrentSelection() + { + return m_fileTableModel->Save(m_selectedFileTableIndex); + } + + bool SeedTabWidget::SaveAll() + { + return m_fileTableModel->SaveAll(); + } + + void SeedTabWidget::SetModelDataSource() + { + // Remove the current watched folders and files + m_guiApplicationManager->RemoveWatchedPaths(m_watchedFolders + m_watchedFiles); + + // Set the new watched folders for the model + m_watchedFolders.clear(); + m_watchedFolders.insert(m_guiApplicationManager->GetSeedListsFolder().c_str()); + + // Get the list of default Seed List files + m_filePathToGemNameMap = AssetBundler::GetDefaultSeedListFiles(GetCachedEngineRoot().c_str(), m_guiApplicationManager->GetCurrentProjectName(), + m_guiApplicationManager->GetGemInfoList(), m_guiApplicationManager->GetEnabledPlatforms()); + + // Get the list of default Seeds that are not stored in a Seed List file on-disk + AZStd::vector defaultSeeds = GetDefaultSeeds(AZ::Utils::GetProjectPath(), m_guiApplicationManager->GetCurrentProjectName()); + m_fileTableModel->AddDefaultSeedsToInMemoryList(defaultSeeds, m_guiApplicationManager->GetCurrentProjectName().c_str(), m_guiApplicationManager->GetEnabledPlatforms()); + + // Set the new watched filess for the model + m_watchedFiles.clear(); + for (const auto& it : m_filePathToGemNameMap) + { + m_watchedFiles.insert(it.first.c_str()); + } + + ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType::SeedListFileType); + m_guiApplicationManager->AddWatchedPaths(m_watchedFolders + m_watchedFiles); + } + + AzQtComponents::TableView* SeedTabWidget::GetFileTableView() + { + return m_ui->fileTableView; + } + + QModelIndex SeedTabWidget::GetSelectedFileTableIndex() + { + return m_selectedFileTableIndex; + } + + AssetBundlerAbstractFileTableModel* SeedTabWidget::GetFileTableModel() + { + return m_fileTableModel.get(); + } + + void SeedTabWidget::SetActiveProjectLabel(const QString& labelText) + { + m_ui->activeProjectLabel->setText(labelText); + } + + void SeedTabWidget::ApplyConfig() + { + const GUIApplicationManager::Config& config = m_guiApplicationManager->GetConfig(); + + m_ui->fileTableFrame->setFixedWidth(config.fileTableWidth); + m_ui->fileTableView->header()->resizeSection(SeedListFileTableModel::Column::ColumnFileName, config.seedListFileNameColumnWidth); + m_ui->fileTableView->header()->resizeSection(SeedListFileTableModel::Column::ColumnCheckBox, config.checkBoxColumnWidth); + m_ui->fileTableView->header()->resizeSection(SeedListFileTableModel::Column::ColumnProject, config.projectNameColumnWidth); + + m_ui->seedFileContentsTable->header()->resizeSection(SeedListTableModel::Column::ColumnRelativePath, config.seedListContentsNameColumnWidth); + } + + void SeedTabWidget::UncheckSelectDefaultSeedListsCheckBox() + { + m_ui->selectDefaultSeedListsCheckBox->setChecked(false); + } + + void SeedTabWidget::SetGenerateAssetListsButtonEnabled(bool isEnabled) + { + m_ui->generateAssetListsButton->setEnabled(isEnabled); + } + + bool SeedTabWidget::OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) + { + m_hasWarnings = true; + return false; + } + + bool SeedTabWidget::OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) + { + m_hasWarnings = true; + return false; + } + + void SeedTabWidget::FileSelectionChanged(const QItemSelection& /*selected*/, const QItemSelection& /*deselected*/) + { + if (m_ui->fileTableView->selectionModel()->selectedRows().size() == 0) + { + // Set selected index to an invalid value + m_selectedFileTableIndex = QModelIndex(); + m_ui->seedListFileAbsolutePathLabel->clear(); + return; + } + + m_selectedFileTableIndex = m_fileTableFilterModel->mapToSource(m_ui->fileTableView->selectionModel()->currentIndex()); + + m_seedListContentsModel = m_fileTableModel->GetSeedListFileContents(m_selectedFileTableIndex); + m_seedListContentsFilterModel->setSourceModel(m_seedListContentsModel.data()); + + m_ui->seedListFileAbsolutePathLabel->setText(m_fileTableModel->GetFileAbsolutePath(m_selectedFileTableIndex).c_str()); + } + + void SeedTabWidget::OnNewFileButtonPressed() + { + AZStd::string absoluteFilePath = NewFileDialog::OSNewFileDialog( + this, + AzToolsFramework::AssetSeedManager::GetSeedFileExtension(), + "Seed List", + m_guiApplicationManager->GetSeedListsFolder()); + + if (absoluteFilePath.empty()) + { + // User canceled out of the file dialog + return; + } + + AZStd::vector createdFiles = m_fileTableModel->CreateNewFiles( + absoluteFilePath, + AzFramework::PlatformFlags::Platform_NONE, + QString(m_guiApplicationManager->GetCurrentProjectName().c_str())); + + if (!createdFiles.empty()) + { + AddScanPathToAssetBundlerSettings(AssetBundlingFileType::SeedListFileType, createdFiles.at(0)); + } + } + + void SeedTabWidget::OnSelectDefaultSeedListsCheckBoxChanged() + { + m_fileTableModel->SelectDefaultSeedLists(m_ui->selectDefaultSeedListsCheckBox->isChecked()); + } + + void SeedTabWidget::OnGenerateAssetListsButtonPressed() + { + m_generateAssetListsDialog.reset( + new NewFileDialog( + this, + GenerateAssetListFilesDialogName, + QString(m_guiApplicationManager->GetAssetListsFolder().c_str()), + AzToolsFramework::AssetSeedManager::GetAssetListFileExtension(), + QString(tr("Asset List (*.%1)")).arg(AzToolsFramework::AssetSeedManager::GetAssetListFileExtension()), + m_guiApplicationManager->GetEnabledPlatforms())); + auto dialogResponse = m_generateAssetListsDialog->exec(); + if (dialogResponse == QDialog::DialogCode::Rejected) + { + // User canceled the operation + return; + } + + m_hasWarnings = false; + auto createdFiles = m_fileTableModel->GenerateAssetLists(m_generateAssetListsDialog->GetAbsoluteFilePath(), m_generateAssetListsDialog->GetPlatformFlags()); + + // Warnings will not prevent the generation of Asset List files, we must track them separately + NewFileDialog::FileGenerationResultMessageBox(this, createdFiles, m_hasWarnings); + + if (createdFiles.empty()) + { + // Error has already been thrown + return; + } + + // Add created files to the file watcher + for (const AZStd::string& absolutePath : createdFiles) + { + AddScanPathToAssetBundlerSettings(AssetBundlingFileType::AssetListFileType, absolutePath); + } + + // The watched files list was updated after the files were created, so we need to force-reload them + m_guiApplicationManager->UpdateFiles(AssetBundlingFileType::AssetListFileType, createdFiles); + } + + void SeedTabWidget::OnEditSeedButtonPressed() + { + if (!m_selectedFileTableIndex.isValid()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot perform Edit Seed operation: No Seed List File is selected"); + return; + } + + // Get the current platforms of the selected Seed so we can display them as already checked + QModelIndex currentSeedIndex = m_seedListContentsFilterModel->mapToSource(m_ui->seedFileContentsTable->selectionModel()->currentIndex()); + auto getPlatformOutcome = m_seedListContentsModel->GetSeedPlatforms(currentSeedIndex); + if (!getPlatformOutcome.IsSuccess()) + { + // Error has already been thrown + return; + } + + // Create and display the Edit Seed dialog + m_editSeedDialog.reset(new EditSeedDialog(this, m_guiApplicationManager->GetEnabledPlatforms(), getPlatformOutcome.GetValue())); + auto dialogResponse = m_editSeedDialog->exec(); + if (dialogResponse == QDialog::DialogCode::Rejected) + { + // User canceled the operation + return; + } + + // Set the data in the model + m_fileTableModel->SetSeedPlatforms(m_selectedFileTableIndex, currentSeedIndex, m_editSeedDialog->GetPlatformFlags()); + } + + void SeedTabWidget::OnEditAllButtonPressed() + { + if (!m_selectedFileTableIndex.isValid()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot perform Edit All operation: No Seed List File is selected"); + return; + } + + // Get the platforms of all the seeds so we can display them as already checked or partially checked + AzFramework::PlatformFlags selectedPlatformFlags = AzFramework::PlatformFlags::AllNamedPlatforms; + AzFramework::PlatformFlags partiallySelectedPlatformFlags = AzFramework::PlatformFlags::Platform_NONE; + QMap indexToPlatformFlagsMap; + for (int row = 0; row < m_seedListContentsModel->rowCount(); ++row) + { + QModelIndex currentSeedIndex = m_seedListContentsModel->index(row, 0); + auto getPlatformOutcome = m_seedListContentsModel->GetSeedPlatforms(currentSeedIndex); + if (!getPlatformOutcome.IsSuccess()) + { + // Error has already been thrown + return; + } + + indexToPlatformFlagsMap[currentSeedIndex] = getPlatformOutcome.TakeValue(); + selectedPlatformFlags &= indexToPlatformFlagsMap[currentSeedIndex]; + partiallySelectedPlatformFlags |= selectedPlatformFlags ^ indexToPlatformFlagsMap[currentSeedIndex]; + } + + // Create and display the Edit Seed dialog + m_editSeedDialog.reset(new EditSeedDialog( + this, + m_guiApplicationManager->GetEnabledPlatforms(), + selectedPlatformFlags, + partiallySelectedPlatformFlags)); + + auto dialogResponse = m_editSeedDialog->exec(); + if (dialogResponse == QDialog::DialogCode::Rejected) + { + // User canceled the operation + return; + } + + // Set the data in the model + for (int row = 0; row < m_seedListContentsModel->rowCount(); ++row) + { + QModelIndex currentSeedIndex = m_seedListContentsModel->index(row, 0); + AzFramework::PlatformFlags checkedPlatforms = m_editSeedDialog->GetPlatformFlags(); + AzFramework::PlatformFlags partiallyCheckedPlatforms = m_editSeedDialog->GetPartiallySelectedPlatformFlags(); + // If the platform is partially checked, we want to keep its original status when saving the changes + AzFramework::PlatformFlags platformFlags = indexToPlatformFlagsMap[currentSeedIndex] & partiallyCheckedPlatforms | checkedPlatforms; + + m_fileTableModel->SetSeedPlatforms(m_selectedFileTableIndex, currentSeedIndex, platformFlags); + } + } + + void SeedTabWidget::OnAddSeedButtonPressed() + { + if (!m_selectedFileTableIndex.isValid()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot perform Add Seed operation: No Seed List File is selected"); + return; + } + + // Get path to the platform-specific cache folder of one of the enabled platforms + AzFramework::PlatformFlags enabledPlatforms = m_guiApplicationManager->GetEnabledPlatforms(); + AZStd::fixed_vector enabledPlatformIndices = AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(enabledPlatforms); + AZStd::string platformSpecificCachePath = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(enabledPlatformIndices[0]); + + // Create and display the Add Seed Dialog + m_addSeedDialog.reset(new AddSeedDialog(this, enabledPlatforms, platformSpecificCachePath)); + auto dialogResponse = m_addSeedDialog->exec(); + if (dialogResponse == QDialog::DialogCode::Rejected) + { + // User canceled the operation + return; + } + + // Set the data in the model + m_fileTableModel->AddSeed(m_selectedFileTableIndex, m_addSeedDialog->GetFileName(), m_addSeedDialog->GetPlatformFlags()); + } + + void SeedTabWidget::OnRemoveSeedButtonPressed() + { + if (!m_selectedFileTableIndex.isValid()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot perform Remove Seed operation: No Seed List File is selected"); + return; + } + + // Set the data in the model + QModelIndex currentSeedIndex = m_seedListContentsFilterModel->mapToSource(m_ui->seedFileContentsTable->selectionModel()->currentIndex()); + m_fileTableModel->RemoveSeed(m_selectedFileTableIndex, currentSeedIndex); + } + + void SeedTabWidget::OnSeedListContentsTableContextMenuRequested(const QPoint& pos) + { + if (!m_selectedFileTableIndex.isValid()) + { + return; + } + + QMenu* contextMenu = new QMenu(this); + contextMenu->setToolTipsVisible(true); + + QAction* action = contextMenu->addAction(tr("Edit Platforms")); + connect(action, &QAction::triggered, this, &SeedTabWidget::OnEditSeedButtonPressed); + action->setToolTip(tr("Change what platforms are referenced when generating an Asset List file.")); + + contextMenu->addSeparator(); + + action = contextMenu->addAction(tr("Add Seed")); + connect(action, &QAction::triggered, this, &SeedTabWidget::OnAddSeedButtonPressed); + action->setToolTip(tr("Add a new Seed to the Seed List file.")); + + action = contextMenu->addAction(tr("Remove Seed")); + connect(action, &QAction::triggered, this, &SeedTabWidget::OnRemoveSeedButtonPressed); + action->setToolTip(tr("Removes the Seed from the Seed List file.")); + + contextMenu->exec(m_ui->seedFileContentsTable->mapToGlobal(pos)); + delete contextMenu; + } + +} //namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/SeedTabWidget.h b/Code/Tools/AssetBundler/source/ui/SeedTabWidget.h new file mode 100644 index 0000000000..c1383cdd08 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/SeedTabWidget.h @@ -0,0 +1,129 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#endif + +namespace Ui +{ + class SeedTabWidget; +} + +class QFileSystemModel; +class QStringListModel; + +namespace AssetBundler +{ + class GUIApplicationManager; + + class SeedListFileTableModel; + class SeedListTableModel; + + class NewFileDialog; + class EditSeedDialog; + class AddSeedDialog; + + class SeedTabWidget + : public AssetBundlerTabWidget + , public AZ::Debug::TraceMessageBus::Handler + { + Q_OBJECT + + public: + explicit SeedTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager, const QString& assetBundlingDirectory); + virtual ~SeedTabWidget(); + + QString GetTabTitle() override { return tr("Seeds"); } + + QString GetFileTypeDisplayName() override { return tr("Seed List file"); } + + AssetBundlingFileType GetFileType() override { return AssetBundlingFileType::SeedListFileType; } + + bool HasUnsavedChanges() override; + + void Reload() override; + + bool SaveCurrentSelection() override; + + bool SaveAll() override; + + void SetModelDataSource() override; + + AzQtComponents::TableView* GetFileTableView() override; + + QModelIndex GetSelectedFileTableIndex() override; + + AssetBundlerAbstractFileTableModel* GetFileTableModel() override; + + void SetActiveProjectLabel(const QString& labelText) override; + + void ApplyConfig() override; + + void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) override; + + void UncheckSelectDefaultSeedListsCheckBox(); + + void SetGenerateAssetListsButtonEnabled(bool isEnabled); + + ///////////////////////////////////////////////////////// + // TraceMessageBus overrides + bool OnPreError(const char* window, const char* fileName, int line, const char* func, const char* message) override; + bool OnPreWarning(const char* window, const char* fileName, int line, const char* func, const char* message) override; + ///////////////////////////////////////////////////////// + + private: + + void OnNewFileButtonPressed(); + + void OnSelectDefaultSeedListsCheckBoxChanged(); + + void OnGenerateAssetListsButtonPressed(); + + void OnEditSeedButtonPressed(); + void OnEditAllButtonPressed(); + + void OnAddSeedButtonPressed(); + void OnRemoveSeedButtonPressed(); + + void OnSeedListContentsTableContextMenuRequested(const QPoint& pos); + + QSharedPointer m_ui; + QDir m_assetBundlingFolder; + + QSharedPointer m_fileTableModel; + QModelIndex m_selectedFileTableIndex; + + QSharedPointer m_generateAssetListsDialog; + + QSharedPointer m_seedListContentsFilterModel; + QSharedPointer m_seedListContentsModel; + + QSharedPointer m_editSeedDialog; + QSharedPointer m_addSeedDialog; + + bool m_hasWarnings = false; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/SeedTabWidget.ui b/Code/Tools/AssetBundler/source/ui/SeedTabWidget.ui new file mode 100644 index 0000000000..b32072696f --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/SeedTabWidget.ui @@ -0,0 +1,297 @@ + + + SeedTabWidget + + + + 0 + 0 + 813 + 673 + + + + Seed Tab Widget + + + + + + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Generate Asset Lists + + + true + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Seed List files + + + + + + + + + + Filter by file name + + + + + + + 5 + + + 5 + + + + + + Create new Seed List file + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Default Seed Lists + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Product Assets + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 5 + + + + + Filter by file name + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Edit All + + + + + + + + Add Asset + + + + + + + + + + + + + + + + + + AzQtComponents::TableView + QTreeView +
AzQtComponents/Components/Widgets/TableView.h
+ 1 +
+ + AzQtComponents::FilteredSearchWidget + QTreeView +
AzQtComponents/Components/FilteredSearchWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/style/AssetBundler-Icon-256x256@x2.ico b/Code/Tools/AssetBundler/source/ui/style/AssetBundler-Icon-256x256@x2.ico new file mode 100644 index 0000000000..ffbf974130 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/style/AssetBundler-Icon-256x256@x2.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:690a47a0e2ff4c41ce23ad0bc5dd5bd525e03676a26d3367726beaa96babf207 +size 138199 diff --git a/Code/Tools/AssetBundler/source/ui/style/AssetBundler.qrc b/Code/Tools/AssetBundler/source/ui/style/AssetBundler.qrc new file mode 100644 index 0000000000..65ad7f11cd --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/style/AssetBundler.qrc @@ -0,0 +1,7 @@ + + + AssetBundler.qss + AssetBundlerConfig.ini + AssetBundler-Icon-256x256@x2.ico + + \ No newline at end of file diff --git a/Code/Tools/AssetBundler/source/ui/style/AssetBundler.qss b/Code/Tools/AssetBundler/source/ui/style/AssetBundler.qss new file mode 100644 index 0000000000..8603bbbb1b --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/style/AssetBundler.qss @@ -0,0 +1,173 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +/************** General (MainWindow) **************/ + +QTabWidget:pane { + border: none; +} + +QLabel#activeProjectLabel { + font-size: 18px; + font-family: "Amazon Ember Light"; + margin-bottom: 5px; +} + +QTreeView#logTableView { + border: 1px solid #1B1B1B; + margin-left: 10px; + margin-right: 10px; + margin-bottom: 10px; +} + +QTreeView#logTableView QHeaderView::section { + background-color: #1B1B1B; +} + +/************** General (Tabs) **************/ + +QFrame#fileTableFrame, +QFrame#fileContentsFrame { + border: 1px solid #1B1B1B; +} + +QFrame#fileTableFrame { + margin-right: 10px; +} + +QFrame#fileTableHeaderFrame, +QFrame#fileContentsHeaderFrame, +QFrame#fileTableHeaderFrame QLabel, +QFrame#fileContentsHeaderFrame QLabel{ + background-color: #1B1B1B; +} + +QFrame#fileTableHeaderFrame QLabel, +QFrame#fileContentsHeaderFrame QLabel{ + background-color: #1B1B1B; + margin-left: 5px; +} + +QTabWidget QTreeView QHeaderView::section { + background-color: rgb(77, 77, 77); +} + +QWidget#PlatformSelectionWidget QLabel#platformSelectionLabel { + margin-right: 10px; +} + +QDialog#NewFileDialog QPushButton#browseFileButton, +QDialog#NewFileDialog QPushButton#createFileButton, +QDialog#NewFileDialog QPushButton#cancelButton { + margin-left: 10px; + margin-right: 10px; +} + +/************** Seeds Tab **************/ + +QWidget#SeedTabWidget QPushButton#generateAssetListsButton, +QWidget#SeedTabWidget QPushButton#browseFileButton, +QWidget#SeedTabWidget QPushButton#cancelButton, +QWidget#SeedTabWidget QPushButton#addSeedButton, +QWidget#SeedTabWidget QPushButton#applyChangesButton { + margin-left: 10px; + margin-right: 10px; +} + +QCheckBox#selectDefaultSeedListsCheckBox { + margin: 5px; +} + +QWidget#seedListContentsFilteredSearchWidget { + margin-left: 5px; +} + +QDialog QFrame#inputValuesFrame { + border: none; + margin: 10px; + padding: 10px; +} + +QDialog QFrame#lineFrame { + border: none; + margin-top: 10px; + margin-bottom: 10px; +} + +QDialog QFrame#inputValuesFrame, +QDialog QFrame#lineFrame, +QDialog#AddSeedDialog QLabel, +QDialog#AddSeedDialog QCheckBox, +QDialog#EditSeedDialog QLabel, +QDialog#EditSeedDialog QCheckBox, +QDialog#NewFileDialog QLabel, +QDialog#NewFileDialog QCheckBox { + background-color: #555555; +} + +/************** Asset List Tab **************/ + +QLabel#assetListContentsLabel { + margin-right: 10px; +} + +QWidget#fileFilteredSearchWidget, +QWidget#assetListContentsFilteredSearchWidget { + margin-left: 5px; + margin-right: 5px; +} + +QPushButton#generateBundleButton { + margin-left: 10px; + margin-right: 10px; +} + +/************** Generate Bundles Modal **************/ + +QFrame#bundleSettingsFrame { + border: none; + margin-bottom: 10px; +} + +QFrame#outputBundleLocationFrame, +QFrame#bundleSettingsFileFrame { + border: none; + margin: 10px; +} + +QFrame#bundleSettingsFrame, +QFrame#outputBundleLocationFrame, +QFrame#bundleSettingsFileFrame, +QFrame#bundleSettingsFrame QLabel { + background-color: #555555; +} + +QWidget#GenerateBundlesModal QPushButton { + margin-left: 10px; + margin-right: 10px; +} + +/************** Rules Tab **************/ + +QPushButton#runRuleButton, +QPushButton#addComparisonStepButton { + margin-left: 10px; + margin-right: 10px; +} + +QScrollArea#comparisonDataList { + border: none; +} + +QFrame#comparisonDataFrame { + padding: 10px; +} diff --git a/Code/Tools/AssetBundler/source/ui/style/AssetBundlerConfig.ini b/Code/Tools/AssetBundler/source/ui/style/AssetBundlerConfig.ini new file mode 100644 index 0000000000..876ceea40e --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/style/AssetBundlerConfig.ini @@ -0,0 +1,19 @@ +[ErrorLogDetails] +LogTypeColumnWidth=180 +LogSourceColumnWidth=130 + +[GeneralFileTableDetails] +FileTableWidth=450 +FileNameColumnWidth=250 + +[SeedsTabDetails] +CheckBoxColumnWidth=22 +SeedListFileNameColumnWidth=150 +ProjectNameColumnWidth=120 +SeedListContentsNameColumnWidth=400 + +[AssetListsTabDetails] +AssetListFileNameColumnWidth=210 +AssetListPlatformColumnWidth=70 +ProductAssetNameColumnWidth=220 +ProductAssetRelativePathColumnWidth=300 \ No newline at end of file diff --git a/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.cpp b/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.cpp new file mode 100644 index 0000000000..d278b9bd2c --- /dev/null +++ b/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.cpp @@ -0,0 +1,386 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +// Forward declare platform-specific functions +namespace Platform +{ + /// On Windows this will return the setting for our custom title bar + /// On other platforms this will return the setting for using platform default + /// This ensures that functions like Exit, Maximize, and Minimize appear in the right platform-specific style + AzQtComponents::WindowDecorationWrapper::Option GetWindowDecorationWrapperOption(); +} // namespace Platform + +const char AssetBundlingFolderName [] = "AssetBundling"; +const char SeedListsFolderName [] = "SeedLists"; +const char AssetListsFolderName [] = "AssetLists"; +const char RulesFolderName[] = "Rules"; +const char BundleSettingsFolderName [] = "BundleSettings"; +const char BundlesFolderName [] = "Bundles"; + +namespace AssetBundler +{ + + GUIApplicationManager::Config GUIApplicationManager::loadConfig(QSettings& settings) + { + using namespace AzQtComponents; + + Config config = defaultConfig(); + + // Error Log + { + ConfigHelpers::GroupGuard details(&settings, QStringLiteral("ErrorLogDetails")); + ConfigHelpers::read(settings, QStringLiteral("LogTypeColumnWidth"), config.logTypeColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("LogSourceColumnWidth"), config.logSourceColumnWidth); + } + + // General File Tables + { + ConfigHelpers::GroupGuard details(&settings, QStringLiteral("GeneralFileTableDetails")); + ConfigHelpers::read(settings, QStringLiteral("FileTableWidth"), config.fileTableWidth); + ConfigHelpers::read(settings, QStringLiteral("FileNameColumnWidth"), config.fileNameColumnWidth); + } + + // Seeds Tab + { + ConfigHelpers::GroupGuard details(&settings, QStringLiteral("SeedsTabDetails")); + ConfigHelpers::read(settings, QStringLiteral("CheckBoxColumnWidth"), config.checkBoxColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("SeedListFileNameColumnWidth"), config.seedListFileNameColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("ProjectNameColumnWidth"), config.projectNameColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("SeedListContentsNameColumnWidth"), config.seedListContentsNameColumnWidth); + } + + // Asset Lists Tab + { + ConfigHelpers::GroupGuard details(&settings, QStringLiteral("AssetListsTabDetails")); + ConfigHelpers::read(settings, QStringLiteral("AssetListFileNameColumnWidth"), config.assetListFileNameColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("AssetListPlatformColumnWidth"), config.assetListPlatformColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("ProductAssetNameColumnWidth"), config.productAssetNameColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("ProductAssetRelativePathColumnWidth"), config.productAssetRelativePathColumnWidth); + } + + return config; + } + + GUIApplicationManager::Config GUIApplicationManager::defaultConfig() + { + // These are used if the values can't be read from AssetBundlerConfig.ini. + Config config; + + config.logTypeColumnWidth = 150; + config.logSourceColumnWidth = 150; + + config.fileTableWidth = 250; + config.fileNameColumnWidth = 150; + + config.checkBoxColumnWidth = 150; + config.seedListFileNameColumnWidth = 150; + config.projectNameColumnWidth = 150; + config.seedListContentsNameColumnWidth = 150; + + config.assetListFileNameColumnWidth = 150; + config.assetListPlatformColumnWidth = 150; + config.productAssetNameColumnWidth = 150; + config.productAssetRelativePathColumnWidth = 150; + + return config; + } + + GUIApplicationManager::GUIApplicationManager(int* argc, char*** argv, QObject* parent) + : ApplicationManager(argc, argv, parent) + { + } + + GUIApplicationManager::~GUIApplicationManager() + { + // Reset this before DestroyApplication, BusDisconnect needs to happen before Application::Stop() destroys the allocators. + m_platformCatalogManager.reset(); + } + + bool GUIApplicationManager::Init() + { + m_isInitializing = true; + // Initialize Asset Bundler Batch + ApplicationManager::Init(); + + AZ::IO::FixedMaxPath engineRoot = GetEngineRoot(); + + if (engineRoot.empty()) + { + // Error has already been thrown + return false; + } + + // Determine the name of the current project + auto projectOutcome = AssetBundler::GetCurrentProjectName(); + if (!projectOutcome.IsSuccess()) + { + AZ_Error("AssetBundler", false, projectOutcome.GetError().c_str()); + return false; + } + m_currentProjectName = projectOutcome.GetValue(); + + // Set up paths to the Project folder, Project Cache folder, and determine enabled platforms + auto pathOutcome = InitializePaths(); + if (!pathOutcome.IsSuccess()) + { + AZ_Error("AssetBundler", false, pathOutcome.GetError().c_str()); + return false; + } + + // Set up platform-specific Asset Catalogs + m_platformCatalogManager = AZStd::make_unique(); + + // Define some application-level settings + QApplication::setOrganizationName("Amazon"); + QApplication::setOrganizationDomain("amazon.com"); + QApplication::setApplicationName("Asset Bundler"); + + QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); + + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + + m_isInitializing = false; + + // Create the actual Qt Application + m_qApp.reset(new QApplication(*GetArgC(), *GetArgV())); + + // Create the Main Window + m_mainWindow.reset(new MainWindow(this)); + + return true; + } + + bool GUIApplicationManager::Run() + { + // Set up the Style Manager + AzQtComponents::StyleManager styleManager(qApp); + styleManager.initialize(qApp, GetEngineRoot()); + + AZ::IO::FixedMaxPath engineRoot(GetEngineRoot()); + QDir engineRootDir(engineRoot.c_str()); + AzQtComponents::StyleManager::addSearchPaths( + QStringLiteral("style"), + engineRootDir.filePath(QStringLiteral("Code/Tools/AssetBundler/source/ui/style")), + QStringLiteral(":/AssetBundler/style"), + engineRoot); + AzQtComponents::StyleManager::setStyleSheet(m_mainWindow.data(), QStringLiteral("style:AssetBundler.qss")); + + AzQtComponents::ConfigHelpers::loadConfig(&m_fileWatcher, &m_config, QStringLiteral("style:AssetBundlerConfig.ini"), this, std::bind(&GUIApplicationManager::ApplyConfig, this)); + ApplyConfig(); + + qApp->setWindowIcon(QIcon("style:AssetBundler-Icon-256x256@x2.ico")); + + // Set up the Main Window + auto wrapper = new AzQtComponents::WindowDecorationWrapper(Platform::GetWindowDecorationWrapperOption()); + wrapper->setGuest(m_mainWindow.data()); + m_mainWindow->Activate(); + wrapper->show(); + m_mainWindow->show(); + + qApp->setQuitOnLastWindowClosed(true); + + // Run the application + return qApp->exec(); + } + + void GUIApplicationManager::AddWatchedPath(const QString& folderPath) + { + m_fileWatcher.addPath(folderPath); + } + + void GUIApplicationManager::AddWatchedPaths(const QSet& folderPaths) + { + m_fileWatcher.addPaths(folderPaths.values()); + } + + void GUIApplicationManager::RemoveWatchedPath(const QString& path) + { + m_fileWatcher.removePath(path); + } + + void GUIApplicationManager::RemoveWatchedPaths(const QSet& paths) + { + // Check whether the list is empty to get rid of the warning from Qt + if (paths.isEmpty()) + { + return; + } + + m_fileWatcher.removePaths(paths.values()); + } + + bool GUIApplicationManager::OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + // We want to display errors during initialization, then let the MainWindow handle errors during runtime + if (m_isInitializing) + { + // These are fatal initialization errors, and the application will shut down after the user closes the message box + m_qApp.reset(new QApplication(*GetArgC(), *GetArgV())); + QMessageBox errorMessageBox; + errorMessageBox.setWindowTitle("Asset Bundler"); + errorMessageBox.setText(message); + errorMessageBox.setStandardButtons(QMessageBox::Ok); + errorMessageBox.setDefaultButton(QMessageBox::Ok); + errorMessageBox.exec(); + + return true; + } + + return false; + } + + bool GUIApplicationManager::OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) + { + // Don't handle warnings, let the MainWindow print them + return false; + } + + + bool GUIApplicationManager::OnPrintf(const char* /*window*/, const char* /*message*/) + { + // This is disabled during initialization to prevent a lot of message spam printed to the CLI that gets generated on setup + return m_isInitializing; + } + + AZ::Outcome GUIApplicationManager::InitializePaths() + { + // Calculate the path to the Cache for the current project + auto pathOutcome = AssetBundler::GetProjectCacheFolderPath(); + if (!pathOutcome.IsSuccess()) + { + return AZ::Failure(pathOutcome.GetError()); + } + + m_currentProjectCacheFolder = pathOutcome.GetValue().String(); + + // Calculate the path to the current project folder + pathOutcome = AssetBundler::GetProjectFolderPath(); + if (!pathOutcome.IsSuccess()) + { + return AZ::Failure(pathOutcome.GetError()); + } + + m_currentProjectFolder = pathOutcome.GetValue().String(); + + // Generate the AssetBundling folder inside the current project + AzFramework::StringFunc::Path::ConstructFull(m_currentProjectFolder.c_str(), AssetBundlingFolderName, m_assetBundlingFolder); + + // Seed Lists folder + AzFramework::StringFunc::Path::ConstructFull(m_assetBundlingFolder.c_str(), SeedListsFolderName, m_seedListsFolder); + AZ::Outcome createPathOutcome = AssetBundler::MakePath(m_seedListsFolder); + if (!createPathOutcome.IsSuccess()) + { + return createPathOutcome; + } + + // Asset Lists folder + AzFramework::StringFunc::Path::ConstructFull(m_assetBundlingFolder.c_str(), AssetListsFolderName, m_assetListsFolder); + createPathOutcome = AssetBundler::MakePath(m_assetListsFolder); + if (!createPathOutcome.IsSuccess()) + { + return createPathOutcome; + } + + // Rules folder + AzFramework::StringFunc::Path::ConstructFull(m_assetBundlingFolder.c_str(), RulesFolderName, m_rulesFolder); + createPathOutcome = AssetBundler::MakePath(m_rulesFolder); + if (!createPathOutcome.IsSuccess()) + { + return createPathOutcome; + } + + // Bundle Settings Folder + AzFramework::StringFunc::Path::ConstructFull(m_assetBundlingFolder.c_str(), BundleSettingsFolderName, m_bundleSettingsFolder); + createPathOutcome = AssetBundler::MakePath(m_bundleSettingsFolder); + if (!createPathOutcome.IsSuccess()) + { + return createPathOutcome; + } + + // Bundles Folder + AzFramework::StringFunc::Path::ConstructFull(m_assetBundlingFolder.c_str(), BundlesFolderName, m_bundlesFolder); + createPathOutcome = AssetBundler::MakePath(m_bundlesFolder); + if (!createPathOutcome.IsSuccess()) + { + return createPathOutcome; + } + + // Determine the enabled platforms + const char* appRoot = nullptr; + AzFramework::ApplicationRequests::Bus::BroadcastResult(appRoot, &AzFramework::ApplicationRequests::GetAppRoot); + m_enabledPlatforms = GetEnabledPlatformFlags(GetEngineRoot(), appRoot, AZ::Utils::GetProjectPath().c_str()); + + // Determine which Gems are enabled for the current project + if (!AzFramework::GetGemsInfo(m_gemInfoList, *m_settingsRegistry)) + { + return AZ::Failure(AZStd::string::format("Failed to read Gems for project: %s\n", m_currentProjectName.c_str())); + } + + QObject::connect(&m_fileWatcher, &QFileSystemWatcher::directoryChanged, this, &GUIApplicationManager::DirectoryChanged); + QObject::connect(&m_fileWatcher, &QFileSystemWatcher::fileChanged, this, &GUIApplicationManager::FileChanged); + + return AZ::Success(); + } + + void GUIApplicationManager::DirectoryChanged(const QString& directory) + { + UpdateTab(directory.toUtf8().data()); + } + + void GUIApplicationManager::FileChanged(const QString& path) + { + // FileChanged will only be called when engine or gem seed files are updated + // Otherwilse DirectoryChanged should be triggered + AZStd::string extension; + AzFramework::StringFunc::Path::GetExtension(path.toUtf8().data(), extension); + extension = extension.starts_with(".") ? extension.substr(1) : extension; + if (extension == AzToolsFramework::AssetSeedManager::GetSeedFileExtension()) + { + UpdateTab(GetSeedListsFolder()); + } + + // Many applications save an open file by writing a new file and then deleting the old one + // Add the file path back if it has been removed from the watcher file list + if (!m_fileWatcher.files().contains(path)) + { + m_fileWatcher.addPath(path); + } + } + + void GUIApplicationManager::ApplyConfig() + { + m_mainWindow->ApplyConfig(); + } + +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.h b/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.h new file mode 100644 index 0000000000..e81607d4a8 --- /dev/null +++ b/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.h @@ -0,0 +1,164 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#endif + +namespace AssetBundler +{ + enum AssetBundlingFileType : int + { + SeedListFileType = 0, + AssetListFileType, + BundleSettingsFileType, + BundleFileType, + RulesFileType, + NumBundlingFileTypes + }; + + class MainWindow; + + class GUIApplicationManager + : public ApplicationManager + { + Q_OBJECT + + public: + + struct Config + { + // These default values are used if the values can't be read from AssetBundlerConfig.ini, + // and the call to defaultConfig fails. + + // Error Log + int logTypeColumnWidth = -1; + int logSourceColumnWidth = -1; + + // General File Tables + int fileTableWidth = -1; + int fileNameColumnWidth = -1; + + // Seeds Tab + int checkBoxColumnWidth = -1; + int seedListFileNameColumnWidth = -1; + int projectNameColumnWidth = -1; + int seedListContentsNameColumnWidth = -1; + + // Asset Lists Tab + int assetListFileNameColumnWidth = -1; + int assetListPlatformColumnWidth = -1; + int productAssetNameColumnWidth = -1; + int productAssetRelativePathColumnWidth = -1; + }; + + /*! + * Loads the button config data from a settings object. + */ + static Config loadConfig(QSettings& settings); + + /*! + * Returns default button config data. + */ + static Config defaultConfig(); + + explicit GUIApplicationManager(int* argc, char*** argv, QObject* parent = 0); + virtual ~GUIApplicationManager(); + + bool Init() override; + + bool Run() override; + + AZStd::string GetCurrentProjectFolder() { return m_currentProjectFolder; } + AZStd::string GetAssetBundlingFolder() { return m_assetBundlingFolder; } + AZStd::string GetSeedListsFolder() { return m_seedListsFolder; } + AZStd::string GetAssetListsFolder() { return m_assetListsFolder; } + AZStd::string GetRulesFolder() { return m_rulesFolder; } + AZStd::string GetBundleSettingsFolder() { return m_bundleSettingsFolder; } + AZStd::string GetBundlesFolder() { return m_bundlesFolder; } + AZStd::string GetCurrentProjectCacheFolder() { return m_currentProjectCacheFolder; } + + AzFramework::PlatformFlags GetEnabledPlatforms() { return m_enabledPlatforms; } + + void AddWatchedPath(const QString& path); + void AddWatchedPaths(const QSet& paths); + void RemoveWatchedPath(const QString& path); + void RemoveWatchedPaths(const QSet& paths); + + //////////////////////////////////////////////////////////////////////////////////////////// + // Override the ApplicationManager TraceMessageBus methods so that messages go through MainWindow and not the CLI + + bool OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) override; + bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; + bool OnPrintf(const char* /*window*/, const char* /*message*/) override; + //////////////////////////////////////////////////////////////////////////////////////////// + + const Config& GetConfig() { return m_config; } + + Q_SIGNALS: + void ShowWindow(); + void UpdateTab(const AZStd::string& directory); + void UpdateFiles(AssetBundlingFileType fileType, const AZStd::vector& absoluteFilePaths); + + protected Q_SLOTS: + void DirectoryChanged(const QString& directory); + void FileChanged(const QString& path); + void ApplyConfig(); + + private: + /** + * Generates directory information for all paths used in this tool + * @return void on success, error message on failure + */ + AZ::Outcome InitializePaths(); + + QSharedPointer m_qApp; + + Config m_config; + + QSharedPointer m_mainWindow; + + AZStd::string m_currentProjectFolder; + AZStd::string m_assetBundlingFolder; + AZStd::string m_seedListsFolder; + AZStd::string m_assetListsFolder; + AZStd::string m_rulesFolder; + AZStd::string m_bundleSettingsFolder; + AZStd::string m_bundlesFolder; + AZStd::string m_currentProjectCacheFolder; + + AzFramework::PlatformFlags m_enabledPlatforms = AzFramework::PlatformFlags::Platform_NONE; + + AZStd::unique_ptr m_platformCatalogManager; + + bool m_isInitializing = false; + + QFileSystemWatcher m_fileWatcher; + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/utils/applicationManager.cpp b/Code/Tools/AssetBundler/source/utils/applicationManager.cpp index bb4fee2ceb..7aae023e72 100644 --- a/Code/Tools/AssetBundler/source/utils/applicationManager.cpp +++ b/Code/Tools/AssetBundler/source/utils/applicationManager.cpp @@ -45,8 +45,16 @@ namespace AssetBundler { const char compareVariablePrefix = '$'; - ApplicationManager::ApplicationManager(int* argc, char*** argv) - : AzToolsFramework::ToolsApplication(argc, argv) + GemInfo::GemInfo(AZStd::string name, AZStd::string relativeFilePath, AZStd::string absoluteFilePath) + : m_gemName(name) + , m_relativeFilePath(relativeFilePath) + , m_absoluteFilePath(absoluteFilePath) + { + } + + ApplicationManager::ApplicationManager(int* argc, char*** argv, QObject* parent) + : QObject(parent) + , AzToolsFramework::ToolsApplication(argc, argv) { } @@ -55,7 +63,7 @@ namespace AssetBundler DestroyApplication(); } - void ApplicationManager::Init() + bool ApplicationManager::Init() { AZ::Debug::TraceMessageBus::Handler::BusConnect(); Start(AzFramework::Application::Descriptor()); @@ -72,8 +80,11 @@ namespace AssetBundler m_assetSeedManager = AZStd::make_unique(); AZ_TracePrintf(AssetBundler::AppWindowName, "\n"); + g_cachedEngineRoot = AZ::IO::FixedMaxPath(GetEngineRoot()); + // There is no need to update the UserSettings file, so we can avoid a race condition by disabling save on shutdown AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); + return true; } void ApplicationManager::DestroyApplication() @@ -1522,7 +1533,7 @@ namespace AssetBundler } } - AZStd::vector defaultSeeds = GetDefaultSeeds(GetEngineRoot(), AZ::Utils::GetProjectPath(), m_currentProjectName); + AZStd::vector defaultSeeds = GetDefaultSeeds(AZ::Utils::GetProjectPath(), m_currentProjectName); if (defaultSeeds.empty()) { // Error has already been thrown @@ -2847,3 +2858,4 @@ namespace AssetBundler return !m_showVerboseOutput; } } // namespace AssetBundler +#include diff --git a/Code/Tools/AssetBundler/source/utils/applicationManager.h b/Code/Tools/AssetBundler/source/utils/applicationManager.h index 01f180a77a..d49707f489 100644 --- a/Code/Tools/AssetBundler/source/utils/applicationManager.h +++ b/Code/Tools/AssetBundler/source/utils/applicationManager.h @@ -11,6 +11,7 @@ */ #pragma once +#if !defined(Q_MOC_RUN) #include #include #include @@ -22,7 +23,7 @@ #include #include #include - +#endif namespace AssetBundler { struct SeedsParams @@ -161,16 +162,18 @@ namespace AssetBundler }; class ApplicationManager - : public AZ::Debug::TraceMessageBus::Handler + : public QObject + , public AZ::Debug::TraceMessageBus::Handler , public AzToolsFramework::ToolsApplication { + Q_OBJECT public: - explicit ApplicationManager(int* argc, char*** argv); - ~ApplicationManager(); + explicit ApplicationManager(int* argc, char*** argv, QObject* parent = 0); + virtual ~ApplicationManager(); - void Init(); + virtual bool Init(); void DestroyApplication(); - bool Run(); + virtual bool Run(); //////////////////////////////////////////////////////////////////////////////////////////// // AzFramework::Application overrides diff --git a/Code/Tools/AssetBundler/source/utils/utils.cpp b/Code/Tools/AssetBundler/source/utils/utils.cpp index b1595f7dd8..6058728a76 100644 --- a/Code/Tools/AssetBundler/source/utils/utils.cpp +++ b/Code/Tools/AssetBundler/source/utils/utils.cpp @@ -31,6 +31,7 @@ AZ_PUSH_DISABLE_WARNING(4244 4251, "-Wunknown-warning-option") #include #include #include +#include AZ_POP_DISABLE_WARNING namespace AssetBundler @@ -108,6 +109,8 @@ namespace AssetBundler const char* AssetCatalogFilename = "assetcatalog.xml"; + AZ::IO::FixedMaxPath g_cachedEngineRoot; + const char EngineDirectoryName[] = "Engine"; const char RestrictedDirectoryName[] = "restricted"; @@ -128,7 +131,7 @@ namespace AssetBundler AZStd::unordered_map& defaultSeedLists, AzFramework::PlatformFlags platformFlags) { - AZ::IO::FixedMaxPath engineRoot(GetEngineRoot()); + AZ::IO::FixedMaxPath engineRoot(GetCachedEngineRoot()); AZ::IO::FixedMaxPath engineRestrictedRoot = engineRoot / RestrictedDirectoryName; AZ::IO::FixedMaxPath engineLocalPath = AZ::IO::PathView(engineDirectory.LexicallyRelative(engineRoot)); @@ -201,15 +204,10 @@ namespace AssetBundler } } - AZ::IO::FixedMaxPath GetEngineRoot() + AZ::IO::FixedMaxPath GetCachedEngineRoot() { - AZ::IO::FixedMaxPath engineRootPath; - if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) - { - settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder); - } - - return engineRootPath; + AZ_Error(AppWindowName, !g_cachedEngineRoot.empty(), "Cached Engine Root has not been initialized by the Bundler."); + return g_cachedEngineRoot; } void AddPlatformIdentifier(AZStd::string& filePath, const AZStd::string& platformIdentifier) @@ -276,11 +274,11 @@ namespace AssetBundler return defaultSeedLists; } - AZStd::vector GetDefaultSeeds(AZStd::string_view enginePath, AZStd::string_view projectPath, AZStd::string_view projectName) + AZStd::vector GetDefaultSeeds(AZStd::string_view projectPath, AZStd::string_view projectName) { AZStd::vector defaultSeeds; - defaultSeeds.emplace_back(GetProjectDependenciesAssetPath(enginePath, projectPath, projectName)); + defaultSeeds.emplace_back(GetProjectDependenciesAssetPath(projectPath, projectName)); return defaultSeeds; } @@ -294,34 +292,12 @@ namespace AssetBundler return projectDependenciesFilePath.LexicallyNormal(); } - AZ::IO::Path GetProjectDependenciesFileTemplate(AZStd::string_view engineRoot) - { - AZ::IO::Path projectDependenciesFileTemplate = engineRoot; - projectDependenciesFileTemplate /= DefaultProjectTemplatePath; - projectDependenciesFileTemplate /= AZStd::string::format("%s%s", ProjectName, DependenciesFileSuffix); - projectDependenciesFileTemplate.ReplaceExtension(DependenciesFileExtension); - return projectDependenciesFileTemplate.LexicallyNormal(); - } - - AZ::IO::Path GetProjectDependenciesAssetPath(AZStd::string_view enginePath, AZStd::string_view projectPath, AZStd::string_view projectName) + AZ::IO::Path GetProjectDependenciesAssetPath(AZStd::string_view projectPath, AZStd::string_view projectName) { AZ::IO::Path projectDependenciesFile = GetProjectDependenciesFile(projectPath, projectName); if (!AZ::IO::FileIOBase::GetInstance()->Exists(projectDependenciesFile.c_str())) { - AZ_TracePrintf(AssetBundler::AppWindowName, "Project dependencies file %s doesn't exist.\n", projectDependenciesFile.c_str()); - - AZ::IO::Path projectDependenciesFileTemplate = GetProjectDependenciesFileTemplate(enginePath); - if (AZ::IO::FileIOBase::GetInstance()->Copy(projectDependenciesFileTemplate.c_str(), projectDependenciesFile.c_str())) - { - AZ_TracePrintf(AssetBundler::AppWindowName, "Copied project dependencies file template %s to the current project.\n", - projectDependenciesFile.c_str()); - } - else - { - AZ_Error(AppWindowName, false, "Failed to copy project dependencies file template %s from default project" - " template to the current project.\n", projectDependenciesFileTemplate.c_str()); - return {}; - } + AZ_Error(AssetBundler::AppWindowName, false, "Project dependencies file %s doesn't exist.\n", projectDependenciesFile.c_str()); } // Turn the absolute path into a cache-relative path @@ -538,6 +514,14 @@ namespace AssetBundler return platformSpecificCacheFolderPath; } + AZStd::string GenerateKeyFromAbsolutePath(const AZStd::string& absoluteFilePath) + { + AZStd::string key(absoluteFilePath); + AzFramework::StringFunc::Path::Normalize(key); + AzFramework::StringFunc::Path::StripDrive(key); + return key; + } + void ConvertToRelativePath(AZStd::string_view parentFolderPath, AZStd::string& absoluteFilePath) { absoluteFilePath = AZ::IO::PathView(absoluteFilePath).LexicallyRelative(parentFolderPath).String(); @@ -822,4 +806,26 @@ namespace AssetBundler } return false; } + + QJsonObject ReadJson(const AZStd::string& filePath) + { + QByteArray byteArray; + QFile jsonFile; + jsonFile.setFileName(filePath.c_str()); + jsonFile.open(QIODevice::ReadOnly | QIODevice::Text); + byteArray = jsonFile.readAll(); + jsonFile.close(); + + return QJsonDocument::fromJson(byteArray).object(); + } + + void SaveJson(const AZStd::string& filePath, const QJsonObject& jsonObject) + { + QFile jsonFile(filePath.c_str()); + QJsonDocument JsonDocument; + JsonDocument.setObject(jsonObject); + jsonFile.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); + jsonFile.write(JsonDocument.toJson()); + jsonFile.close(); + } } diff --git a/Code/Tools/AssetBundler/source/utils/utils.h b/Code/Tools/AssetBundler/source/utils/utils.h index db6729098a..629fd90a31 100644 --- a/Code/Tools/AssetBundler/source/utils/utils.h +++ b/Code/Tools/AssetBundler/source/utils/utils.h @@ -19,7 +19,9 @@ #include #include #include - +#include +#include +#include namespace AssetBundler { @@ -120,8 +122,20 @@ namespace AssetBundler //////////////////////////////////////////////////////////////////////////////////////////// extern const char* AssetCatalogFilename; + extern AZ::IO::FixedMaxPath g_cachedEngineRoot; static const size_t MaxErrorMessageLength = 4096; + //! This struct stores gem related information + struct GemInfo + { + AZ_CLASS_ALLOCATOR(GemInfo, AZ::SystemAllocator, 0); + GemInfo(AZStd::string name, AZStd::string relativeFilePath, AZStd::string absoluteFilePath); + GemInfo() = default; + AZStd::string m_gemName; + AZStd::string m_relativeFilePath; + AZStd::string m_absoluteFilePath; + }; + // The Warning Absorber is used to absorb warnings // One case that this is being used is during loading of the asset catalog. @@ -137,8 +151,8 @@ namespace AssetBundler bool OnPreWarning(const char* window, const char* fileName, int line, const char* func, const char* message) override; }; - // Returns the engine root - AZ::IO::FixedMaxPath GetEngineRoot(); + // Returns the cached engine root. Throws an error if the cached path has not been initialized by the Bundler Application. + AZ::IO::FixedMaxPath GetCachedEngineRoot(); /** * Determines the name of the currently enabled game project @@ -192,6 +206,8 @@ namespace AssetBundler */ AZ::IO::Path GetPlatformSpecificCacheFolderPath(); + AZStd::string GenerateKeyFromAbsolutePath(const AZStd::string& absoluteFilePath); + void ConvertToRelativePath(AZStd::string_view parentFolderPath, AZStd::string& absoluteFilePath); AZ::Outcome MakePath(const AZStd::string& path); @@ -207,16 +223,13 @@ namespace AssetBundler const AZStd::vector& gemInfoList, AzFramework::PlatformFlags platformFlags); //! Returns a vector of relative paths to Assets that should be included as default Seeds, but are not already in a Seed List file. - AZStd::vector GetDefaultSeeds(AZStd::string_view enginePath, AZStd::string_view projectPath, AZStd::string_view projectName); + AZStd::vector GetDefaultSeeds(AZStd::string_view projectPath, AZStd::string_view projectName); //! Returns the absolute path of {ProjectName}_Dependencies.xml AZ::IO::Path GetProjectDependenciesFile(AZStd::string_view productPath, AZStd::string_view projectName); - //! Returns the absolute path of the project dependencies file in the default project template - AZ::IO::Path GetProjectDependenciesFileTemplate(AZStd::string_view enginePath); - //! Creates the ProjectName_Dependencies.xml file if it does not exist, and adds returns the relative path to the asset in the Cache. - AZ::IO::Path GetProjectDependenciesAssetPath(AZStd::string_view enginePath, AZStd::string_view projectPath, AZStd::string_view projectName); + AZ::IO::Path GetProjectDependenciesAssetPath(AZStd::string_view projectPath, AZStd::string_view projectName); //! Returns the map from gem seed list file path to gem name AZStd::unordered_map GetGemSeedListFilePathToGemNameMap(const AZStd::vector& gemInfoList, AzFramework::PlatformFlags platformFlags); @@ -229,6 +242,9 @@ namespace AssetBundler //! Please note that the game project could be in a different location to the engine therefore we need the assetRoot param. AzFramework::PlatformFlags GetEnabledPlatformFlags(AZStd::string_view enginePath, AZStd::string_view assetRoot, AZStd::string_view projectPath); + QJsonObject ReadJson(const AZStd::string& filePath); + void SaveJson(const AZStd::string& filePath, const QJsonObject& jsonObject); + //! Filepath is a helper class that is used to find the absolute path of a file //! if the inputted file path is an absolute path than it does nothing //! if the inputted file path is a relative path than based on whether the user diff --git a/Code/Tools/AssetBundler/tests/tests_main.cpp b/Code/Tools/AssetBundler/tests/tests_main.cpp index e1535bf0f5..6d874a3320 100644 --- a/Code/Tools/AssetBundler/tests/tests_main.cpp +++ b/Code/Tools/AssetBundler/tests/tests_main.cpp @@ -113,14 +113,13 @@ namespace AssetBundler AZ::SettingsRegistry::Register(&m_registry); } - const char* engineRoot = nullptr; - AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot); - if (!engineRoot) + AssetBundler::g_cachedEngineRoot = m_data->m_application.get()->GetEngineRoot(); + if (AssetBundler::g_cachedEngineRoot.empty()) { GTEST_FATAL_FAILURE_(AZStd::string::format("Unable to locate engine root.\n").c_str()); } - AzFramework::StringFunc::Path::Join(engineRoot, RelativeTestFolder, m_data->m_testEngineRoot); + AzFramework::StringFunc::Path::Join(AssetBundler::g_cachedEngineRoot.c_str(), RelativeTestFolder, m_data->m_testEngineRoot); m_data->m_localFileIO = aznew AZ::IO::LocalFileIO(); m_data->m_priorFileIO = AZ::IO::FileIOBase::GetInstance(); diff --git a/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake b/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake index e065f9a1a2..be1e85d370 100644 --- a/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake +++ b/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake @@ -9,13 +9,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_bundle_resources( - TARGET AssetProcessor - FILES - ${CMAKE_SOURCE_DIR}/Code/Tools/RC/Config/rc/xmlfilter.txt - ${CMAKE_SOURCE_DIR}/Code/Tools/RC/Config/rc/rc.ini -) - # Set resources directory for app icons target_sources(AssetProcessor PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/Platform/Mac/Images.xcassets) set_target_properties(AssetProcessor PROPERTIES diff --git a/Code/Tools/CMakeLists.txt b/Code/Tools/CMakeLists.txt index 65a1bf85ce..db5476756b 100644 --- a/Code/Tools/CMakeLists.txt +++ b/Code/Tools/CMakeLists.txt @@ -25,3 +25,4 @@ add_subdirectory(AssetBundler) add_subdirectory(GridHub) add_subdirectory(Standalone) add_subdirectory(TestImpactFramework) +add_subdirectory(ProjectManager) diff --git a/Code/Tools/ProjectManager/CMakeLists.txt b/Code/Tools/ProjectManager/CMakeLists.txt new file mode 100644 index 0000000000..8315ef831c --- /dev/null +++ b/Code/Tools/ProjectManager/CMakeLists.txt @@ -0,0 +1,41 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) + return() +endif() + +ly_add_target( + NAME ProjectManager APPLICATION + OUTPUT_NAME o3de + NAMESPACE AZ + AUTOMOC + AUTOUIC + AUTORCC + FILES_CMAKE + project_manager_files.cmake + Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake + INCLUDE_DIRECTORIES + PUBLIC + . + PRIVATE + source + + BUILD_DEPENDENCIES + PRIVATE + 3rdParty::Qt::Core + 3rdParty::Qt::Concurrent + 3rdParty::Qt::Widgets + AZ::AzCore + AZ::AzFramework + AZ::AzToolsFramework + AZ::AzQtComponents +) diff --git a/Code/Tools/ProjectManager/Platform/Android/PAL_android.cmake b/Code/Tools/ProjectManager/Platform/Android/PAL_android.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Android/PAL_android.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Code/Tools/ProjectManager/Platform/Linux/PAL_linux.cmake b/Code/Tools/ProjectManager/Platform/Linux/PAL_linux.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Linux/PAL_linux.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Code/Tools/ProjectManager/Platform/Mac/PAL_mac.cmake b/Code/Tools/ProjectManager/Platform/Mac/PAL_mac.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Mac/PAL_mac.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Code/Tools/ProjectManager/Platform/Windows/PAL_windows.cmake b/Code/Tools/ProjectManager/Platform/Windows/PAL_windows.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Windows/PAL_windows.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Code/Tools/ProjectManager/Platform/iOS/PAL_ios.cmake b/Code/Tools/ProjectManager/Platform/iOS/PAL_ios.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/iOS/PAL_ios.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Code/Tools/ProjectManager/Qt/FirstTimeUse.cpp b/Code/Tools/ProjectManager/Qt/FirstTimeUse.cpp new file mode 100644 index 0000000000..640849740e --- /dev/null +++ b/Code/Tools/ProjectManager/Qt/FirstTimeUse.cpp @@ -0,0 +1,31 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include + +#include + +namespace ProjectManager +{ + FirstTimeUse::FirstTimeUse(QWidget* parent) + : QWidget(parent) + , m_ui(new Ui::FirstTimeUseClass()) + { + m_ui->setupUi(this); + } + + FirstTimeUse::~FirstTimeUse() + { + } + + //#include +} // namespace ProjectManager diff --git a/Code/Tools/ProjectManager/Qt/FirstTimeUse.h b/Code/Tools/ProjectManager/Qt/FirstTimeUse.h new file mode 100644 index 0000000000..85f344f3fe --- /dev/null +++ b/Code/Tools/ProjectManager/Qt/FirstTimeUse.h @@ -0,0 +1,36 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#endif + +namespace Ui +{ + class FirstTimeUseClass; +} + +namespace ProjectManager +{ + class FirstTimeUse : public QWidget + { + + public: + explicit FirstTimeUse(QWidget* parent); + ~FirstTimeUse(); + + private: + QScopedPointer m_ui; + }; + +} // namespace ProjectManager diff --git a/Code/Tools/ProjectManager/Qt/FirstTimeUse.ui b/Code/Tools/ProjectManager/Qt/FirstTimeUse.ui new file mode 100644 index 0000000000..fdc195731f --- /dev/null +++ b/Code/Tools/ProjectManager/Qt/FirstTimeUse.ui @@ -0,0 +1,93 @@ + + + FirstTimeUseClass + + + + 0 + 0 + 881 + 555 + + + + Form + + + + + + + + + 30 + + + + READY. SET. CREATE! + + + + + + + <html><head/><body><p>Welcome to O3DE! Start something new by creating a project. Not sure what to create? </p><p>Explore what’s available by downloading our sample project.</p></body></html> + + + Qt::AutoText + + + + + + + + + + + + 0 + 0 + + + + Create Project + + + + :/Resources/Add.svg:/Resources/Add.svg + + + + 16 + 16 + + + + + + + + + 0 + 0 + + + + Open a Project + + + + :/Resources/Select_Folder.svg:/Resources/Select_Folder.svg + + + + + + + + + + + + diff --git a/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.cpp b/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.cpp new file mode 100644 index 0000000000..4a8486f877 --- /dev/null +++ b/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.cpp @@ -0,0 +1,49 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include + +#include +#include + +#include + +#include + +namespace ProjectManager +{ + ProjectManagerWindow::ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath) + : QMainWindow(parent) + , m_ui(new Ui::ProjectManagerWindowClass()) + { + m_ui->setupUi(this); + + QDir rootDir = QString::fromUtf8(engineRootPath.Native().data(), aznumeric_cast(engineRootPath.Native().size())); + const auto pathOnDisk = rootDir.absoluteFilePath("Code/Tools/ProjectManager/Resources"); + const auto qrcPath = QStringLiteral(":/ProjectManagerWindow"); + AzQtComponents::StyleManager::addSearchPaths("projectmanagerwindow", pathOnDisk, qrcPath, engineRootPath); + + AzQtComponents::StyleManager::setStyleSheet(this, QStringLiteral("projectlauncherwindow:ProjectManagerWindow.qss")); + + + FirstTimeUse* firstTimeUse = new FirstTimeUse(m_ui->centralwidget); + + firstTimeUse->show(); + } + + ProjectManagerWindow::~ProjectManagerWindow() + { + } + + //#include +} // namespace ProjectManager diff --git a/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.h b/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.h new file mode 100644 index 0000000000..a62e823a92 --- /dev/null +++ b/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.h @@ -0,0 +1,38 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +#include +#endif + +namespace Ui +{ + class ProjectManagerWindowClass; +} + +namespace ProjectManager +{ + class ProjectManagerWindow : public QMainWindow + { + + public: + explicit ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath); + ~ProjectManagerWindow(); + + private: + QScopedPointer m_ui; + }; + +} // namespace ProjectManager diff --git a/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.ui b/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.ui new file mode 100644 index 0000000000..60ec2dd674 --- /dev/null +++ b/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.ui @@ -0,0 +1,61 @@ + + + ProjectManagerWindowClass + + + + 0 + 0 + 800 + 600 + + + + O3DE Project Manager + + + + + + + + 0 + 0 + 800 + 36 + + + + + 16 + + + + + Icon + + + + :/Resources/o3de_editor.ico:/Resources/o3de_editor.ico + + + + + Projects + + + + + Engine + + + + + + + + + + + + diff --git a/Code/Tools/ProjectManager/Resources/Add.svg b/Code/Tools/ProjectManager/Resources/Add.svg new file mode 100644 index 0000000000..d2b9b2e0a6 --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/Add.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Code/Tools/ProjectManager/Resources/Select_Folder.svg b/Code/Tools/ProjectManager/Resources/Select_Folder.svg new file mode 100644 index 0000000000..72dcd3385e --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/Select_Folder.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Code/Tools/ProjectManager/Resources/o3de_editor.ico b/Code/Tools/ProjectManager/Resources/o3de_editor.ico new file mode 100644 index 0000000000..0680ceea19 --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/o3de_editor.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c042fce57915fc749abc7b37de765fd697c3c4d7de045a3d44805aa0ce29901a +size 107016 diff --git a/Code/Tools/ProjectManager/project_manager.qrc b/Code/Tools/ProjectManager/project_manager.qrc new file mode 100644 index 0000000000..408398584b --- /dev/null +++ b/Code/Tools/ProjectManager/project_manager.qrc @@ -0,0 +1,8 @@ + + + Resources/ProjectManager.qss + Resources/Add.svg + Resources/Select_Folder.svg + Resources/o3de_editor.ico + + \ No newline at end of file diff --git a/Code/CryEngine/CryFont/CMakeLists.txt b/Code/Tools/ProjectManager/project_manager_files.cmake similarity index 64% rename from Code/CryEngine/CryFont/CMakeLists.txt rename to Code/Tools/ProjectManager/project_manager_files.cmake index 9e2f29f7b6..4d36550e56 100644 --- a/Code/CryEngine/CryFont/CMakeLists.txt +++ b/Code/Tools/ProjectManager/project_manager_files.cmake @@ -9,16 +9,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_target( - NAME CryFont ${PAL_TRAIT_MONOLITHIC_DRIVEN_LIBRARY_TYPE} - NAMESPACE Legacy - FILES_CMAKE - cryfont_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - . - BUILD_DEPENDENCIES - PRIVATE - 3rdParty::freetype - Legacy::CryCommon +set(FILES + project_manager.qrc + source/main.cpp + Qt/FirstTimeUse.h + Qt/FirstTimeUse.cpp + Qt/FirstTimeUse.ui + Qt/ProjectManagerWindow.h + Qt/ProjectManagerWindow.cpp + Qt/ProjectManagerWindow.ui ) diff --git a/Code/Tools/ProjectManager/source/main.cpp b/Code/Tools/ProjectManager/source/main.cpp new file mode 100644 index 0000000000..ecfae3b28e --- /dev/null +++ b/Code/Tools/ProjectManager/source/main.cpp @@ -0,0 +1,55 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +int main(int argc, char* argv[]) +{ + QApplication::setOrganizationName("O3DE"); + QApplication::setOrganizationDomain("o3de.org"); + QCoreApplication::setApplicationName("ProjectManager"); + QCoreApplication::setApplicationVersion("1.0"); + + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); + AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware); + + QApplication app(argc, argv); + + // Need to use settings registry to get EngineRootFolder + AZ::IO::FixedMaxPath engineRootPath; + { + AZ::ComponentApplication componentApplication; + auto settingsRegistry = AZ::SettingsRegistry::Get(); + settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder); + } + + AzQtComponents::StyleManager styleManager(&app); + styleManager.initialize(&app, engineRootPath); + + ProjectManager::ProjectManagerWindow window(nullptr, engineRootPath); + window.show(); + + return app.exec(); +} diff --git a/Code/Tools/SceneAPI/SceneCore/Containers/GraphObjectProxy.cpp b/Code/Tools/SceneAPI/SceneCore/Containers/GraphObjectProxy.cpp index 4de42eb944..f2fda63ec4 100644 --- a/Code/Tools/SceneAPI/SceneCore/Containers/GraphObjectProxy.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Containers/GraphObjectProxy.cpp @@ -25,9 +25,12 @@ namespace AZ AZ::BehaviorContext* behaviorContext = azrtti_cast(context); if (behaviorContext) { + behaviorContext->Class(); + behaviorContext->Class() ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Module, "scene.graph") + ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) ->Method("CastWithTypeName", &GraphObjectProxy::CastWithTypeName) ->Method("Invoke", &GraphObjectProxy::Invoke) ; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.cpp index 14f125c283..1af6563577 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.cpp @@ -129,7 +129,7 @@ namespace ImageProcessingAtom { AZStd::string fullPath; AZ::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), fullPath); - if (RenerThumbnailFromImage(thumbnailKey, thumbnailSize, IImageObjectPtr(LoadImageFromFile(fullPath)))) + if (RenderThumbnailFromImage(thumbnailKey, thumbnailSize, IImageObjectPtr(LoadImageFromFile(fullPath)))) { return; } @@ -139,7 +139,7 @@ namespace ImageProcessingAtom auto productKey = azrtti_cast(thumbnailKey.data()); if (productKey) { - if (RenerThumbnailFromImage(thumbnailKey, thumbnailSize, Utils::LoadImageFromImageAsset(productKey->GetAssetId()))) + if (RenderThumbnailFromImage(thumbnailKey, thumbnailSize, Utils::LoadImageFromImageAsset(productKey->GetAssetId()))) { return; } @@ -149,7 +149,7 @@ namespace ImageProcessingAtom thumbnailKey, &AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender); } - bool ImageThumbnailSystemComponent::RenerThumbnailFromImage( + bool ImageThumbnailSystemComponent::RenderThumbnailFromImage( AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize, IImageObjectPtr previewImage) const { if (!previewImage) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.h index 943857fd35..ca2453b532 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.h @@ -52,7 +52,7 @@ namespace ImageProcessingAtom bool Installed() const override; void RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize) override; - bool RenerThumbnailFromImage( + bool RenderThumbnailFromImage( AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize, IImageObjectPtr previewImage) const; }; } // namespace Thumbnails diff --git a/Gems/Atom/Feature/Common/Code/CMakeLists.txt b/Gems/Atom/Feature/Common/Code/CMakeLists.txt index 93da352c6e..6f087edefe 100644 --- a/Gems/Atom/Feature/Common/Code/CMakeLists.txt +++ b/Gems/Atom/Feature/Common/Code/CMakeLists.txt @@ -30,7 +30,6 @@ ly_add_target( PUBLIC Include Source - 3rdParty/ACES COMPILE_DEFINITIONS PRIVATE IMGUI_DISABLE_OBSOLETE_FUNCTIONS @@ -58,6 +57,7 @@ ly_add_target( ${pal_source_dir} PUBLIC Include + 3rdParty/ACES COMPILE_DEFINITIONS PRIVATE IMGUI_DISABLE_OBSOLETE_FUNCTIONS diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/LightingPreset.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/LightingPreset.h index f1d8337a35..e79dc6d29e 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/LightingPreset.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/LightingPreset.h @@ -61,13 +61,14 @@ namespace AZ AZ_TYPE_INFO(AZ::Render::LightConfig, "{02644F52-9483-47A8-9028-37671695C34E}"); static void Reflect(AZ::ReflectContext* context); - AZ::Vector3 m_direction = AZ::Vector3::CreateAxisY(); + // Setting default direction to produce a visible shadow + AZ::Vector3 m_direction = AZ::Vector3(1.0f / 3.0f, 1.0f / 3.0f, -1.0f / 3.0f); AZ::Color m_color = AZ::Color::CreateOne(); float m_intensity = 1.0f; - uint16_t m_shadowCascadeCount = 1; - float m_shadowRatioLogarithmUniform = 0.5f; + uint16_t m_shadowCascadeCount = 4; + float m_shadowRatioLogarithmUniform = 1.0f; float m_shadowFarClipDistance = 20.0f; - ShadowmapSize m_shadowmapSize = ShadowmapSize::Size1024; + ShadowmapSize m_shadowmapSize = ShadowmapSize::Size2048; bool m_enableShadowDebugColoring = false; }; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index 0826739119..cfce718146 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -120,13 +120,13 @@ namespace AZ { // stencil Srg // Note: the stencil pass uses a slightly reduced inner AABB to avoid seams - Vector3 innerExtentsReduced = m_innerExtents - Vector3(0.1f, 0.1f, 0.1f); - Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_position) * Matrix3x4::CreateScale(innerExtentsReduced); + Vector3 innerExtentsReduced = m_innerExtents * m_transform.GetScale() - Vector3(0.1f, 0.1f, 0.1f); + Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(innerExtentsReduced); m_stencilSrg->SetConstant(m_reflectionRenderData->m_modelToWorldStencilConstantIndex, modelToWorldStencil); m_stencilSrg->Compile(); // blend weight Srg - Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_position) * Matrix3x4::CreateScale(m_outerExtents); + Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_outerExtents * m_transform.GetScale()); m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldOuter); m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter()); m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin()); @@ -149,7 +149,7 @@ namespace AZ m_renderOuterSrg->Compile(); // render inner Srg - Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_position) * Matrix3x4::CreateScale(m_innerExtents); + Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_innerExtents * m_transform.GetScale()); m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldInner); m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter()); m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin()); @@ -208,24 +208,29 @@ namespace AZ void ReflectionProbe::SetTransform(const AZ::Transform& transform) { - m_position = transform.GetTranslation(); - m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, transform); - m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_outerExtents / 2.0f); - m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_innerExtents / 2.0f); + m_transform = transform; + + // avoid scaling the visualization sphere + AZ::Transform visualizationTransform = m_transform; + visualizationTransform.ExtractScale(); + m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, visualizationTransform); + + m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents * m_transform.GetScale() / 2.0f); + m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents * m_transform.GetScale() / 2.0f); m_updateSrg = true; } void ReflectionProbe::SetOuterExtents(const AZ::Vector3& outerExtents) { m_outerExtents = outerExtents; - m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_outerExtents / 2.0f); + m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents * m_transform.GetScale() / 2.0f); m_updateSrg = true; } void ReflectionProbe::SetInnerExtents(const AZ::Vector3& innerExtents) { m_innerExtents = innerExtents; - m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_innerExtents / 2.0f); + m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents * m_transform.GetScale() / 2.0f); m_updateSrg = true; } @@ -261,7 +266,7 @@ namespace AZ m_environmentCubeMapPipelineId = environmentCubeMapPipeline->GetId(); AZStd::shared_ptr passData = AZStd::make_shared(); - passData->m_position = m_position; + passData->m_position = m_transform.GetTranslation(); RPI::PassDescriptor environmentCubeMapPassDescriptor(Name("EnvironmentCubeMapPass")); environmentCubeMapPassDescriptor.m_passData = passData; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h index 22645a4ed3..42b3ff5c5a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h @@ -75,13 +75,13 @@ namespace AZ void Init(RPI::Scene* scene, ReflectionRenderData* reflectionRenderData); void Simulate(uint32_t probeIndex); - const Vector3& GetPosition() const { return m_position; } + const Vector3& GetPosition() const { return m_transform.GetTranslation(); } void SetTransform(const AZ::Transform& transform); - const AZ::Vector3& GetOuterExtents() const { return m_outerExtents; } + AZ::Vector3 GetOuterExtents() const { return m_outerExtents * m_transform.GetScale(); } void SetOuterExtents(const AZ::Vector3& outerExtents); - const AZ::Vector3& GetInnerExtents() const { return m_innerExtents; } + AZ::Vector3 GetInnerExtents() const { return m_innerExtents * m_transform.GetScale(); } void SetInnerExtents(const AZ::Vector3& innerExtents); const Aabb& GetOuterAabbWs() const { return m_outerAabbWs; } @@ -122,8 +122,8 @@ namespace AZ // scene RPI::Scene* m_scene = nullptr; - // probe capture position - AZ::Vector3 m_position = AZ::Vector3(0.0f, 0.0f, 0.0f); + // probe volume transform + AZ::Transform m_transform = AZ::Transform::CreateIdentity(); // extents of the probe volume AZ::Vector3 m_outerExtents = AZ::Vector3(0.0f, 0.0f, 0.0f); diff --git a/Gems/Atom/Feature/Common/Code/Source/Utils/LightingPreset.cpp b/Gems/Atom/Feature/Common/Code/Source/Utils/LightingPreset.cpp index 77924b87a3..91ad31648b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Utils/LightingPreset.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Utils/LightingPreset.cpp @@ -30,7 +30,7 @@ namespace AZ if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(3) + ->Version(4) ->Field("compensateValue", &ExposureControlConfig::m_manualCompensationValue) ->Field("exposureControlType", &ExposureControlConfig::m_exposureControlType) ->Field("autoExposureMin", &ExposureControlConfig::m_autoExposureMin) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportNotificationBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportNotificationBus.h index 84406d8402..0727547b13 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportNotificationBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportNotificationBus.h @@ -11,6 +11,7 @@ */ #pragma once +#include #include #include #include @@ -66,6 +67,9 @@ namespace MaterialEditor //! Notify when field of view changes virtual void OnFieldOfViewChanged([[maybe_unused]] float fieldOfView) {} + + //! Notify when tone mapping changes + virtual void OnDisplayMapperOperationTypeChanged([[maybe_unused]] AZ::Render::DisplayMapperOperationType operationType) {} }; using MaterialViewportNotificationBus = AZ::EBus; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportRequestBus.h index ea6be4f21a..0c9b6e945d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportRequestBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportRequestBus.h @@ -11,6 +11,7 @@ */ #pragma once +#include #include #include #include @@ -147,6 +148,12 @@ namespace MaterialEditor //! Get field of view virtual float GetFieldOfView() const = 0; + + //! Set tone mapping type + virtual void SetDisplayMapperOperationType(AZ::Render::DisplayMapperOperationType operationType) = 0; + + //! Get tone mapping type + virtual AZ::Render::DisplayMapperOperationType GetDisplayMapperOperationType() const = 0; }; using MaterialViewportRequestBus = AZ::EBus; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp index d6f2092d27..abaf50804f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp @@ -508,6 +508,17 @@ namespace MaterialEditor return m_fieldOfView; } + void MaterialViewportComponent::SetDisplayMapperOperationType(AZ::Render::DisplayMapperOperationType operationType) + { + m_displayMapperOperationType = operationType; + MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnDisplayMapperOperationTypeChanged, operationType); + } + + AZ::Render::DisplayMapperOperationType MaterialViewportComponent::GetDisplayMapperOperationType() const + { + return m_displayMapperOperationType; + } + void MaterialViewportComponent::OnCatalogLoaded([[maybe_unused]] const char* catalogFile) { AZ::TickBus::QueueFunction([this]() { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.h index 036974e123..8332cb862c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.h @@ -12,6 +12,8 @@ #pragma once +#include + #include #include @@ -85,6 +87,8 @@ namespace MaterialEditor bool GetAlternateSkyboxEnabled() const override; void SetFieldOfView(float fieldOfView) override; float GetFieldOfView() const override; + void SetDisplayMapperOperationType(AZ::Render::DisplayMapperOperationType operationType) override; + AZ::Render::DisplayMapperOperationType GetDisplayMapperOperationType() const override; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @@ -111,5 +115,6 @@ namespace MaterialEditor bool m_gridEnabled = true; bool m_alternateSkyboxEnabled = false; float m_fieldOfView = 90.0f; + AZ::Render::DisplayMapperOperationType m_displayMapperOperationType = AZ::Render::DisplayMapperOperationType::Aces; }; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp index 53a2dc2ce6..5939a40db6 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -147,9 +148,11 @@ namespace MaterialEditor m_postProcessEntity->Activate(); // Init directional light processor - m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor(); + // Init display mapper processor + m_displayMapperFeatureProcessor = m_scene->GetFeatureProcessor(); + // Init Skybox m_skyboxFeatureProcessor = m_scene->GetFeatureProcessor(); @@ -423,6 +426,13 @@ namespace MaterialEditor MaterialEditorViewportInputControllerRequestBus::Broadcast(&MaterialEditorViewportInputControllerRequestBus::Handler::SetFieldOfView, fieldOfView); } + void MaterialViewportRenderer::OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) + { + AZ::Render::DisplayMapperConfigurationDescriptor desc; + desc.m_operationType = operationType; + m_displayMapperFeatureProcessor->RegisterDisplayMapperConfiguration(desc); + } + void MaterialViewportRenderer::OnAssetReady(AZ::Data::Asset asset) { if (m_modelAssetId == asset.GetId()) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h index e014d9eada..744a887396 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h @@ -27,6 +27,11 @@ namespace AZ { + namespace Render + { + class DisplayMapperFeatureProcessorInterface; + } + class Entity; class Component; @@ -71,6 +76,7 @@ namespace MaterialEditor void OnGridEnabledChanged(bool enable) override; void OnAlternateSkyboxEnabledChanged(bool enable) override; void OnFieldOfViewChanged(float fieldOfView) override; + void OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) override; // AZ::Data::AssetBus::Handler interface overrides... void OnAssetReady(AZ::Data::Asset asset) override; @@ -92,6 +98,7 @@ namespace MaterialEditor AZ::RPI::RenderPipelinePtr m_renderPipeline; AZ::RPI::ScenePtr m_scene; AZ::Render::DirectionalLightFeatureProcessorInterface* m_directionalLightFeatureProcessor = nullptr; + AZ::Render::DisplayMapperFeatureProcessorInterface* m_displayMapperFeatureProcessor = nullptr; AZ::Entity* m_cameraEntity = nullptr; AZ::Component* m_cameraComponent = nullptr; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp index dad4a34b1e..2af73bf436 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp @@ -38,7 +38,7 @@ namespace MaterialEditor m_toggleGrid->setCheckable(true); connect(m_toggleGrid, &QAction::triggered, [this]() { MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Events::SetGridEnabled, m_toggleGrid->isChecked()); - }); + }); bool enableGrid = false; MaterialViewportRequestBus::BroadcastResult(enableGrid, &MaterialViewportRequestBus::Events::GetGridEnabled); m_toggleGrid->setChecked(enableGrid); @@ -49,31 +49,39 @@ namespace MaterialEditor connect(m_toggleShadowCatcher, &QAction::triggered, [this]() { MaterialViewportRequestBus::Broadcast( &MaterialViewportRequestBus::Events::SetShadowCatcherEnabled, m_toggleShadowCatcher->isChecked()); - }); + }); bool enableShadowCatcher = false; MaterialViewportRequestBus::BroadcastResult(enableShadowCatcher, &MaterialViewportRequestBus::Events::GetShadowCatcherEnabled); m_toggleShadowCatcher->setChecked(enableShadowCatcher); // Add mapping selection button - //[GFX TODO][ATOM-3992] + QToolButton* toneMappingButton = new QToolButton(this); QMenu* toneMappingMenu = new QMenu(toneMappingButton); - toneMappingMenu->addAction("None", [this]() { - MaterialEditorSettingsRequestBus::Broadcast(&MaterialEditorSettingsRequests::SetStringProperty, "toneMapping", "None"); - }); - toneMappingMenu->addAction("Gamma2.2", [this]() { - MaterialEditorSettingsRequestBus::Broadcast(&MaterialEditorSettingsRequests::SetStringProperty, "toneMapping", "Gamma2.2"); - }); - toneMappingMenu->addAction("ACES", [this]() { - MaterialEditorSettingsRequestBus::Broadcast(&MaterialEditorSettingsRequests::SetStringProperty, "toneMapping", "ACES"); - }); + + m_operationNames = + { + { AZ::Render::DisplayMapperOperationType::Reinhard, "Reinhard" }, + { AZ::Render::DisplayMapperOperationType::GammaSRGB, "GammaSRGB" }, + { AZ::Render::DisplayMapperOperationType::Passthrough, "Passthrough" }, + { AZ::Render::DisplayMapperOperationType::AcesLut, "AcesLut" }, + { AZ::Render::DisplayMapperOperationType::Aces, "Aces" } + }; + for (auto operationNamePair : m_operationNames) + { + m_operationActions[operationNamePair.first] = toneMappingMenu->addAction(operationNamePair.second, [operationNamePair]() { + MaterialViewportRequestBus::Broadcast( + &MaterialViewportRequestBus::Events::SetDisplayMapperOperationType, + operationNamePair.first); + }); + m_operationActions[operationNamePair.first]->setCheckable(true); + } + m_operationActions[AZ::Render::DisplayMapperOperationType::Aces]->setChecked(true); toneMappingButton->setMenu(toneMappingMenu); toneMappingButton->setText("Tone Mapping"); toneMappingButton->setIcon(QIcon(":/Icons/toneMapping.svg")); toneMappingButton->setPopupMode(QToolButton::InstantPopup); - - // hiding button until DisplayMapper supports changing settings at run time - toneMappingButton->setVisible(false); + toneMappingButton->setVisible(true); addWidget(toneMappingButton); // Add model combo box @@ -99,6 +107,14 @@ namespace MaterialEditor m_toggleGrid->setChecked(enable); } + void MaterialEditorToolBar::OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) + { + for (auto operationActionPair : m_operationActions) + { + operationActionPair.second->setChecked(operationActionPair.first == operationType); + } + } + void MaterialEditorToolBar::OnShadowCatcherEnabledChanged(bool enable) { m_toggleShadowCatcher->setChecked(enable); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.h index 147608bc23..25077c1868 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.h @@ -33,8 +33,12 @@ namespace MaterialEditor // MaterialViewportNotificationBus::Handler overrides... void OnShadowCatcherEnabledChanged([[maybe_unused]] bool enable) override; void OnGridEnabledChanged([[maybe_unused]] bool enable) override; + void OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) override; QAction* m_toggleGrid = {}; QAction* m_toggleShadowCatcher = {}; + + AZStd::unordered_map m_operationNames; + AZStd::unordered_map m_operationActions; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp index 8efed36197..fd50ace918 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp @@ -36,6 +36,7 @@ namespace MaterialEditor ->Field("enableShadowCatcher", &GeneralViewportSettings::m_enableShadowCatcher) ->Field("enableAlternateSkybox", &GeneralViewportSettings::m_enableAlternateSkybox) ->Field("fieldOfView", &GeneralViewportSettings::m_fieldOfView) + ->Field("displayMapperOperationType", &GeneralViewportSettings::m_displayMapperOperationType) ; if (auto editContext = serializeContext->GetEditContext()) @@ -50,6 +51,12 @@ namespace MaterialEditor ->DataElement(AZ::Edit::UIHandlers::Slider, &GeneralViewportSettings::m_fieldOfView, "Field Of View", "") ->Attribute(AZ::Edit::Attributes::Min, 60.0f) ->Attribute(AZ::Edit::Attributes::Max, 120.0f) + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &GeneralViewportSettings::m_displayMapperOperationType, "Display Mapper Type", "") + ->EnumAttribute(AZ::Render::DisplayMapperOperationType::Aces, "Aces") + ->EnumAttribute(AZ::Render::DisplayMapperOperationType::AcesLut, "AcesLut") + ->EnumAttribute(AZ::Render::DisplayMapperOperationType::Passthrough, "Passthrough") + ->EnumAttribute(AZ::Render::DisplayMapperOperationType::GammaSRGB, "GammaSRGB") + ->EnumAttribute(AZ::Render::DisplayMapperOperationType::Reinhard, "Reinhard") ; } } @@ -66,6 +73,7 @@ namespace MaterialEditor ->Property("enableShadowCatcher", BehaviorValueProperty(&GeneralViewportSettings::m_enableShadowCatcher)) ->Property("enableAlternateSkybox", BehaviorValueProperty(&GeneralViewportSettings::m_enableAlternateSkybox)) ->Property("fieldOfView", BehaviorValueProperty(&GeneralViewportSettings::m_fieldOfView)) + ->Property("displayMapperOperationType", BehaviorValueProperty(&GeneralViewportSettings::m_displayMapperOperationType)) ; } } @@ -298,6 +306,7 @@ namespace MaterialEditor MaterialViewportRequestBus::BroadcastResult( m_generalSettings.m_enableAlternateSkybox, &MaterialViewportRequestBus::Events::GetAlternateSkyboxEnabled); MaterialViewportRequestBus::BroadcastResult(m_generalSettings.m_fieldOfView, &MaterialViewportRequestBus::Handler::GetFieldOfView); + MaterialViewportRequestBus::BroadcastResult(m_generalSettings.m_displayMapperOperationType, &MaterialViewportRequestBus::Handler::GetDisplayMapperOperationType); AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect(); AtomToolsFramework::InspectorWidget::Reset(); @@ -343,6 +352,12 @@ namespace MaterialEditor RefreshGroup("general"); } + void ViewportSettingsInspector::OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) + { + m_generalSettings.m_displayMapperOperationType = operationType; + RefreshGroup("general"); + } + void ViewportSettingsInspector::BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode) { AZ_UNUSED(pNode); @@ -370,6 +385,7 @@ namespace MaterialEditor MaterialViewportRequestBus::Broadcast( &MaterialViewportRequestBus::Events::SetAlternateSkyboxEnabled, m_generalSettings.m_enableAlternateSkybox); MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Handler::SetFieldOfView, m_generalSettings.m_fieldOfView); + MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Handler::SetDisplayMapperOperationType, m_generalSettings.m_displayMapperOperationType); } AZStd::string ViewportSettingsInspector::GetDefaultUniqueSaveFilePath(const AZStd::string& baseName) const diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h index 08e22a380c..c61acb2e4c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h @@ -13,6 +13,7 @@ #pragma once #if !defined(Q_MOC_RUN) +#include #include #include #include @@ -32,6 +33,7 @@ namespace MaterialEditor bool m_enableShadowCatcher = true; bool m_enableAlternateSkybox = false; float m_fieldOfView = 90.0f; + AZ::Render::DisplayMapperOperationType m_displayMapperOperationType = AZ::Render::DisplayMapperOperationType::Aces; }; //! Provides controls for viewing and editing a material document settings. @@ -74,6 +76,7 @@ namespace MaterialEditor void OnGridEnabledChanged(bool enable) override; void OnAlternateSkyboxEnabledChanged(bool enable) override; void OnFieldOfViewChanged(float fieldOfView) override; + void OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) override; // AzToolsFramework::IPropertyEditorNotify overrides... void BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode) override; diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.cpp index b1275b5b3b..dec52234bb 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.cpp @@ -65,27 +65,38 @@ namespace AZ void AtomFontSystemComponent::Activate() { - AZ::CryFontCreationRequestBus::Handler::BusConnect(); + CrySystemEventBus::Handler::BusConnect(); } void AtomFontSystemComponent::Deactivate() { - AZ::CryFontCreationRequestBus::Handler::BusDisconnect(); + CrySystemEventBus::Handler::BusDisconnect(); } - bool AtomFontSystemComponent::CreateCryFont(SSystemGlobalEnvironment& env, [[maybe_unused]] const SSystemInitParams& initParams) + void LoadFont(ICryFont& cryFont, const AZStd::string& fontName) + { + IFFont* font = cryFont.NewFont(fontName.c_str()); + AZ_Assert(font, "Could not instantiate font: %s", fontName.c_str()); + + const AZStd::string fontPath = "Fonts/" + fontName + ".font"; + if (!font->Load(fontPath.c_str())) + { + AZ_Error("AtomFont", false, "Could not load font: %s", fontPath.c_str()); + } + } + + void AtomFontSystemComponent::OnCrySystemInitialized(ISystem& system, const SSystemInitParams&) { - ISystem* system = env.pSystem; #if !defined(AZ_MONOLITHIC_BUILD) // When module is linked dynamically, we must set our gEnv pointer. // When module is linked statically, we'll share the application's gEnv pointer. - gEnv = system->GetGlobalEnvironment(); + gEnv = system.GetGlobalEnvironment(); #endif - if (env.IsDedicated()) + if (gEnv->IsDedicated()) { #if defined(USE_NULLFONT) - env.pCryFont = new AtomNullFont(); + gEnv->pCryFont = new AtomNullFont(); #else // The NULL font implementation must be present for all platforms // supporting running as a pure dedicated server. @@ -96,12 +107,17 @@ namespace AZ else { #if defined(USE_NULLFONT) && defined(USE_NULLFONT_ALWAYS) - env.pCryFont = new AtomNullFont(); + gEnv->pCryFont = new AtomNullFont(); #else - env.pCryFont = new AtomFont(system); + gEnv->pCryFont = new AtomFont(&system); #endif } - return env.pCryFont != 0; + + if (gEnv->pCryFont) + { + LoadFont(*gEnv->pCryFont, "default"); + LoadFont(*gEnv->pCryFont, "default-ui"); + } } void AtomFontSystemComponent::OnCrySystemShutdown([[maybe_unused]] ISystem& system) diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.h b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.h index 23ce20c307..05e30661f2 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.h @@ -13,7 +13,6 @@ #include -#include #include namespace AZ @@ -22,7 +21,6 @@ namespace AZ { class AtomFontSystemComponent : public AZ::Component - , private AZ::CryFontCreationRequestBus::Handler , private CrySystemEventBus::Handler { public: @@ -43,12 +41,12 @@ namespace AZ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// - // CryFontCreationBus - bool CreateCryFont(SSystemGlobalEnvironment& env, const SSystemInitParams& initParams) override; + // CrySystemEventBus + void OnCrySystemInitialized(ISystem& system, const SSystemInitParams& initParams); //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// - // CryFontCreationBus + // CrySystemEventBus void OnCrySystemShutdown(ISystem& system) override; //////////////////////////////////////////////////////////////////////// }; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp index efefcc3dc6..9d34553eba 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp @@ -172,13 +172,19 @@ namespace AZ AZ::Vector3 position = AZ::Vector3::CreateZero(); AZ::TransformBus::EventResult(position, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation); + AZ::Vector3 scale = AZ::Vector3::CreateOne(); + AZ::TransformBus::EventResult(scale, GetEntityId(), &AZ::TransformBus::Events::GetLocalScale); + // draw AABB at probe position using the inner dimensions Color color(0.0f, 0.0f, 1.0f, 1.0f); debugDisplay.SetColor(color); ReflectionProbeComponentConfig& configuration = m_controller.m_configuration; - AZ::Vector3 innerMin(position.GetX() - configuration.m_innerWidth / 2, position.GetY() - configuration.m_innerLength / 2, position.GetZ() - configuration.m_innerHeight / 2); - AZ::Vector3 innerMax(position.GetX() + configuration.m_innerWidth / 2, position.GetY() + configuration.m_innerLength / 2, position.GetZ() + configuration.m_innerHeight / 2); + AZ::Vector3 innerExtents(configuration.m_innerWidth, configuration.m_innerLength, configuration.m_innerHeight); + innerExtents *= scale; + + AZ::Vector3 innerMin(position.GetX() - innerExtents.GetX() / 2, position.GetY() - innerExtents.GetY() / 2, position.GetZ() - innerExtents.GetZ() / 2); + AZ::Vector3 innerMax(position.GetX() + innerExtents.GetX() / 2, position.GetY() + innerExtents.GetY() / 2, position.GetZ() + innerExtents.GetZ() / 2); debugDisplay.DrawWireBox(innerMin, innerMax); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.cpp index f3c74629c2..16baf16886 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.cpp @@ -37,6 +37,15 @@ namespace AZ void CaptureStep::Start() { + if (!m_context->GetData()->m_materialAsset || + !m_context->GetData()->m_modelAsset) + { + AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event( + m_context->GetData()->m_thumbnailKeyRendered, + &AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender); + m_context->SetStep(Step::FindThumbnailToRender); + return; + } Render::MaterialComponentRequestBus::Event( m_context->GetData()->m_modelEntity->GetId(), &Render::MaterialComponentRequestBus::Events::SetDefaultMaterialOverride, diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp index 100b0f61cd..322c765f1b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp @@ -189,6 +189,7 @@ namespace AZ m_context->GetData()->DefaultModelPath, RPI::ModelAsset::RTTI_Type(), false); + AZ_Error("ThumbnailRenderer", defaultModelAssetId.IsValid(), "Default model asset is invalid. Verify the asset %s exists.", m_context->GetData()->DefaultModelPath); if (m_context->GetData()->m_assetsToLoad.emplace(defaultModelAssetId).second) { data->m_defaultModelAsset.Create(defaultModelAssetId); @@ -203,6 +204,7 @@ namespace AZ m_context->GetData()->DefaultMaterialPath, RPI::MaterialAsset::RTTI_Type(), false); + AZ_Error("ThumbnailRenderer", defaultMaterialAssetId.IsValid(), "Default material asset is invalid. Verify the asset %s exists.", m_context->GetData()->DefaultMaterialPath); if (m_context->GetData()->m_assetsToLoad.emplace(defaultMaterialAssetId).second) { data->m_defaultMaterialAsset.Create(defaultMaterialAssetId); diff --git a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/ImguiAtomSystemComponent.cpp b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/ImguiAtomSystemComponent.cpp index 34e7af688c..8493b78171 100644 --- a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/ImguiAtomSystemComponent.cpp +++ b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/ImguiAtomSystemComponent.cpp @@ -99,7 +99,7 @@ namespace AZ #endif } - void ImguiAtomSystemComponent::OnViewportSizeChanged(AzFramework::WindowSize size) + void ImguiAtomSystemComponent::OnViewportSizeChanged([[maybe_unused]] AzFramework::WindowSize size) { #if defined(IMGUI_ENABLED) ImGui::ImGuiManagerBus::Broadcast([this, size](ImGui::ImGuiManagerBus::Events* imgui) diff --git a/Gems/LyShine/Code/Source/LyShineDebug.cpp b/Gems/LyShine/Code/Source/LyShineDebug.cpp index 5ea01c5c1e..76b4030106 100644 --- a/Gems/LyShine/Code/Source/LyShineDebug.cpp +++ b/Gems/LyShine/Code/Source/LyShineDebug.cpp @@ -115,11 +115,13 @@ static int Create2DTexture(int width, int height, byte* data, ETEX_Format format #endif #endif +#if !defined(_RELEASE) static AZ::Vector2 GetTextureSize(AZ::Data::Instance image) { AZ::RHI::Size size = image->GetDescriptor().m_size; return AZ::Vector2(size.m_width, size.m_height); } +#endif //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) diff --git a/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp b/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp index a2fdfa201f..e54f61fbfa 100644 --- a/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp +++ b/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp @@ -764,9 +764,6 @@ void UiParticleEmitterComponent::InGamePostActivate() //////////////////////////////////////////////////////////////////////////////////////////////////// void UiParticleEmitterComponent::Render(LyShine::IRenderGraph* renderGraph) { - const char* profileMarker = "UI_PARTICLESYS"; - gEnv->pRenderer->PushProfileMarker(profileMarker); - AZ::Matrix4x4 transform = AZ::Matrix4x4::CreateIdentity(); AZ::Vector2 emitterOffset = AZ::Vector2::CreateZero(); @@ -840,8 +837,6 @@ void UiParticleEmitterComponent::Render(LyShine::IRenderGraph* renderGraph) m_cachedPrimitive.m_numVertices = totalVerticesInserted; m_cachedPrimitive.m_numIndices = totalParticlesInserted * indicesPerParticle; renderGraph->AddPrimitive(&m_cachedPrimitive, texture, isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, m_blendMode); - - gEnv->pRenderer->PopProfileMarker(profileMarker); } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp index b1092ab92f..937f323b01 100644 --- a/Gems/LyShine/Code/Source/UiTextComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp @@ -1911,9 +1911,6 @@ void UiTextComponent::Render(LyShine::IRenderGraph* renderGraph) for (RenderCacheBatch* batch : m_renderCache.m_batches) { - const char* profileMarker = "UI_TEXT"; - gEnv->pRenderer->PushProfileMarker(profileMarker); - AZ::FFont* font = static_cast(batch->m_font); // LYSHINE_ATOM_TODO - find a different solution from downcasting FFont to IFont AZ::Data::Instance fontImage = font->GetFontImage(); if (fontImage) @@ -1944,8 +1941,6 @@ void UiTextComponent::Render(LyShine::IRenderGraph* renderGraph) isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, blendMode); } } - - gEnv->pRenderer->PopProfileMarker(profileMarker); } } diff --git a/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp b/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp index 80750efe7f..cb33ccac98 100644 --- a/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp +++ b/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp @@ -97,7 +97,8 @@ namespace LyShineExamples if (!texture) { // if there is no texture we will just use a white texture - texture = gEnv->pRenderer->EF_GetTextureByID(gEnv->pRenderer->GetWhiteTextureId()); + // TODO: Get a default atom texture here when possible + //texture = gEnv->pRenderer->EF_GetTextureByID(gEnv->pRenderer->GetWhiteTextureId()); } if (m_isRenderCacheDirty) diff --git a/Gems/WhiteBox/Code/Tests/WhiteBoxPhysicsTest.cpp b/Gems/WhiteBox/Code/Tests/WhiteBoxPhysicsTest.cpp index 6b2ba9ae4b..013b05fc3c 100644 --- a/Gems/WhiteBox/Code/Tests/WhiteBoxPhysicsTest.cpp +++ b/Gems/WhiteBox/Code/Tests/WhiteBoxPhysicsTest.cpp @@ -53,7 +53,7 @@ namespace UnitTest void EditorWhiteBoxPhysicsTestEnvironment::AddGemsAndComponents() { - AddDynamicModulePaths({"PhysX.Editor"}); + AddDynamicModulePaths({"PhysX.Editor.Gem"}); AddComponentDescriptors( {AzToolsFramework::EditorEntityContextComponent::CreateDescriptor(), WhiteBox::EditorWhiteBoxComponent::CreateDescriptor(), WhiteBox::WhiteBoxComponent::CreateDescriptor(), diff --git a/README.md b/README.md index caed4b515c..333ca795e8 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ It is highly recommended you check that you have a [credential manager installed ### Clone the repository ```shell -> git clone https://github.com/aws/o3de.git +> git clone https://github.com/aws-lumberyard/o3de.git Cloning into 'o3de'... # initial prompt for credentials to download the repository code diff --git a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake index bd2fd969eb..fbe24d382d 100644 --- a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake +++ b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake @@ -11,7 +11,6 @@ set(FILES BuiltInPackages_linux.cmake - dyad_linux.cmake FbxSdk_linux.cmake Wwise_linux.cmake ) diff --git a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake index 57dc8ed604..64d58e912f 100644 --- a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake +++ b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake @@ -11,7 +11,6 @@ set(FILES BuiltInPackages_windows.cmake - dyad_windows.cmake FbxSdk_windows.cmake Wwise_windows.cmake ) diff --git a/cmake/3rdParty/cmake_files.cmake b/cmake/3rdParty/cmake_files.cmake index a4737b7020..80e1ae426a 100644 --- a/cmake/3rdParty/cmake_files.cmake +++ b/cmake/3rdParty/cmake_files.cmake @@ -12,7 +12,6 @@ set(FILES BuiltInPackages.cmake FindClang.cmake - Finddyad.cmake FindFbxSdk.cmake FindOpenGLInterface.cmake FindRadTelemetry.cmake