diff --git a/Source/Editor/ProjectInfo.cpp b/Source/Editor/ProjectInfo.cpp index a6fd26bc2..be2afb095 100644 --- a/Source/Editor/ProjectInfo.cpp +++ b/Source/Editor/ProjectInfo.cpp @@ -18,14 +18,14 @@ void ShowProjectLoadError(const Char* errorMsg, const String& projectRootFolder) Platform::Error(String::Format(TEXT("Failed to load project. {0}\nPath: '{1}'"), errorMsg, projectRootFolder)); } -Vector3 GetVector3FromXml(const xml_node& parent, const Char* name, const Vector3& defaultValue) +Vector3 GetVector3FromXml(const xml_node& parent, const PUGIXML_CHAR* name, const Vector3& defaultValue) { const auto node = parent.child(name); if (!node.empty()) { - const auto x = node.child_value(TEXT("X")); - const auto y = node.child_value(TEXT("Y")); - const auto z = node.child_value(TEXT("Z")); + const auto x = node.child_value(PUGIXML_TEXT("X")); + const auto y = node.child_value(PUGIXML_TEXT("Y")); + const auto z = node.child_value(PUGIXML_TEXT("Z")); if (x && y && z) { Vector3 v; @@ -39,7 +39,7 @@ Vector3 GetVector3FromXml(const xml_node& parent, const Char* name, const Vector return defaultValue; } -int32 GetIntFromXml(const xml_node& parent, const Char* name, const int32 defaultValue) +int32 GetIntFromXml(const xml_node& parent, const PUGIXML_CHAR* name, const int32 defaultValue) { const auto node = parent.child_value(name); if (node) @@ -242,7 +242,7 @@ bool ProjectInfo::LoadOldProject(const String& projectPath) { // Open Xml file xml_document doc; - const xml_parse_result result = doc.load_file(*projectPath); + const xml_parse_result result = doc.load_file((const PUGIXML_CHAR*)*projectPath); if (result.status) { ShowProjectLoadError(TEXT("Xml file parsing error."), projectPath); @@ -250,7 +250,7 @@ bool ProjectInfo::LoadOldProject(const String& projectPath) } // Get root node - const xml_node root = doc.child(TEXT("Project")); + const xml_node root = doc.child(PUGIXML_TEXT("Project")); if (!root) { ShowProjectLoadError(TEXT("Missing Project root node in xml file."), projectPath); @@ -258,18 +258,18 @@ bool ProjectInfo::LoadOldProject(const String& projectPath) } // Load data - Name = root.child_value(TEXT("Name")); + Name = (const Char*)root.child_value(PUGIXML_TEXT("Name")); ProjectPath = projectPath; ProjectFolderPath = StringUtils::GetDirectoryName(projectPath); DefaultScene = Guid::Empty; - const auto defaultScene = root.child_value(TEXT("DefaultSceneId")); + const auto defaultScene = root.child_value(PUGIXML_TEXT("DefaultSceneId")); if (defaultScene) { - Guid::Parse(defaultScene, DefaultScene); + Guid::Parse((const Char*)defaultScene, DefaultScene); } - DefaultSceneSpawn.Position = GetVector3FromXml(root, TEXT("DefaultSceneSpawnPos"), Vector3::Zero); - DefaultSceneSpawn.Direction = Quaternion::Euler(GetVector3FromXml(root, TEXT("DefaultSceneSpawnDir"), Vector3::Zero)) * Vector3::Forward; - MinEngineVersion = ::Version(0, 0, GetIntFromXml(root, TEXT("MinVersionSupported"), 0)); + DefaultSceneSpawn.Position = GetVector3FromXml(root, PUGIXML_TEXT("DefaultSceneSpawnPos"), Vector3::Zero); + DefaultSceneSpawn.Direction = Quaternion::Euler(GetVector3FromXml(root, PUGIXML_TEXT("DefaultSceneSpawnDir"), Vector3::Zero)) * Vector3::Forward; + MinEngineVersion = ::Version(0, 0, GetIntFromXml(root, PUGIXML_TEXT("MinVersionSupported"), 0)); // Always reference engine project auto& flaxReference = References.AddOne(); diff --git a/Source/Editor/Utilities/EditorUtilities.cpp b/Source/Editor/Utilities/EditorUtilities.cpp index f17c66875..86769eb45 100644 --- a/Source/Editor/Utilities/EditorUtilities.cpp +++ b/Source/Editor/Utilities/EditorUtilities.cpp @@ -14,6 +14,7 @@ #include "Engine/Content/Content.h" #include "Engine/Content/AssetReference.h" #include "Engine/Content/Assets/Texture.h" +#include "Engine/Utilities/StringConverter.h" #include #define MSDOS_SIGNATURE 0x5A4D @@ -390,7 +391,8 @@ bool EditorUtilities::UpdateExeIcon(const String& path, const TextureData& icon) // - icon/cursor/etc data std::fstream stream; - stream.open(path.Get(), std::ios::in | std::ios::out | std::ios::binary); + StringAsANSI<> pathAnsi(path.Get()); + stream.open(pathAnsi.Get(), std::ios::in | std::ios::out | std::ios::binary); if (!stream.is_open()) { LOG(Warning, "Cannot open file"); diff --git a/Source/Engine/CSG/CSGBuilder.cpp b/Source/Engine/CSG/CSGBuilder.cpp index 419704844..56de33a1f 100644 --- a/Source/Engine/CSG/CSGBuilder.cpp +++ b/Source/Engine/CSG/CSGBuilder.cpp @@ -28,11 +28,14 @@ using namespace CSG; // Enable/disable locking scene during building CSG brushes nodes #define CSG_USE_SCENE_LOCKS 0 +struct BuildData; + namespace CSGBuilderImpl { Array ScenesToRebuild; void onSceneUnloading(Scene* scene, const Guid& sceneId); + bool buildInner(Scene* scene, BuildData& data); void build(Scene* scene); bool generateRawDataAsset(Scene* scene, RawData& meshData, Guid& assetId, const String& assetPath); } @@ -232,33 +235,35 @@ namespace CSG } } -void CSGBuilderImpl::build(Scene* scene) +struct BuildData { - // Start - auto startTime = DateTime::Now(); - LOG(Info, "Start building CSG..."); - - // Temporary data - int32 lastBuildMeshesCount = 0; // TODO: cache this - MeshesArray meshes(Math::Min(lastBuildMeshesCount, 32)); - MeshesLookup cache(Math::Min(lastBuildMeshesCount * 4, 32)); + MeshesArray meshes; + MeshesLookup cache; Guid outputModelAssetId = Guid::Empty; Guid outputRawDataAssetId = Guid::Empty; Guid outputCollisionDataAssetId = Guid::Empty; + BuildData(int32 meshesCapacity = 32) + : meshes(meshesCapacity, 32) + , cache(meshesCapacity * 4) + { + } +}; + +bool CSGBuilderImpl::buildInner(Scene* scene, BuildData& data) +{ // Setup CSG meshes list and build them { Function treeWalkFunction(walkTree); - SceneQuery::TreeExecute&, MeshesLookup&>(treeWalkFunction, meshes, cache); + SceneQuery::TreeExecute&, MeshesLookup&>(treeWalkFunction, data.meshes, data.cache); } - lastBuildMeshesCount = meshes.Count(); - if (meshes.IsEmpty()) - goto BUILDING_END; + if (data.meshes.IsEmpty()) + return false; // Process all meshes (performs actual CSG opterations on geometry in tree structure) - CSG::Mesh* combinedMesh = Combine(scene, cache); + CSG::Mesh* combinedMesh = Combine(scene, data.cache); if (combinedMesh == nullptr) - goto BUILDING_END; + return false; // TODO: split too big meshes (too many verts, to far parts, etc.) @@ -296,9 +301,9 @@ void CSGBuilderImpl::build(Scene* scene) if (AssetsImportingManager::Create(AssetsImportingManager::CreateModelTag, modelDataAssetPath, modelDataAssetId, &modelData)) { LOG(Warning, "Failed to import CSG mesh data"); - goto BUILDING_END; + return true; } - outputModelAssetId = modelDataAssetId; + data.outputModelAssetId = modelDataAssetId; } // Generate asset with CSG mesh metadata (for collisions and brush queries) @@ -310,9 +315,9 @@ void CSGBuilderImpl::build(Scene* scene) if (generateRawDataAsset(scene, meshData, rawDataAssetId, rawDataAssetPath)) { LOG(Warning, "Failed to create raw CSG data"); - goto BUILDING_END; + return true; } - outputRawDataAssetId = rawDataAssetId; + data.outputRawDataAssetId = rawDataAssetId; } // Generate CSG mesh collision asset @@ -346,29 +351,40 @@ void CSGBuilderImpl::build(Scene* scene) if (AssetsImportingManager::Create(AssetsImportingManager::CreateCollisionDataTag, collisionDataAssetPath, collisionDataAssetId, &arg)) { LOG(Warning, "Failed to cook CSG mesh collision data"); - goto BUILDING_END; + return true; } - outputCollisionDataAssetId = collisionDataAssetId; + data.outputCollisionDataAssetId = collisionDataAssetId; #else - outputCollisionDataAssetId = Guid::Empty; + data.outputCollisionDataAssetId = Guid::Empty; #endif } } } -BUILDING_END: + return false; +} + +void CSGBuilderImpl::build(Scene* scene) +{ + // Start + auto startTime = DateTime::Now(); + LOG(Info, "Start building CSG..."); + + // Build + BuildData data; + bool failed = buildInner(scene, data); // Link new (or empty) CSG mesh - scene->CSGData.Data = Content::LoadAsync(outputRawDataAssetId); - scene->CSGData.Model = Content::LoadAsync(outputModelAssetId); - scene->CSGData.CollisionData = Content::LoadAsync(outputCollisionDataAssetId); + scene->CSGData.Data = Content::LoadAsync(data.outputRawDataAssetId); + scene->CSGData.Model = Content::LoadAsync(data.outputModelAssetId); + scene->CSGData.CollisionData = Content::LoadAsync(data.outputCollisionDataAssetId); // TODO: also set CSGData.InstanceBuffer - lightmap scales for the entries so csg mesh gets better quality in lightmaps scene->CSGData.PostCSGBuild(); // End - meshes.ClearDelete(); + data.meshes.ClearDelete(); auto endTime = DateTime::Now(); - LOG(Info, "CSG build in {0} ms! {1} brush(es)", (endTime - startTime).GetTotalMilliseconds(), lastBuildMeshesCount); + LOG(Info, "CSG build in {0} ms! {1} brush(es)", (endTime - startTime).GetTotalMilliseconds(), data.meshes.Count()); } bool CSGBuilderImpl::generateRawDataAsset(Scene* scene, RawData& meshData, Guid& assetId, const String& assetPath) diff --git a/Source/Engine/Debug/DebugDraw.cpp b/Source/Engine/Debug/DebugDraw.cpp index 63cb5f601..c147f104d 100644 --- a/Source/Engine/Debug/DebugDraw.cpp +++ b/Source/Engine/Debug/DebugDraw.cpp @@ -591,6 +591,19 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe #undef DRAW } +namespace +{ + bool DrawActorsTreeWalk(Actor* actor) + { + if (actor->IsActiveInHierarchy()) + { + actor->OnDebugDraw(); + return true; + } + return false; + } +} + void DebugDraw::DrawActors(Actor** selectedActors, int32 selectedActorsCount) { if (selectedActors) @@ -603,15 +616,8 @@ void DebugDraw::DrawActors(Actor** selectedActors, int32 selectedActorsCount) } } - Function function = [](Actor* actor)-> bool - { - if (actor->IsActiveInHierarchy()) - { - actor->OnDebugDraw(); - return true; - } - return false; - }; + Function function; + function.Bind(&DrawActorsTreeWalk); SceneQuery::TreeExecute(function); } diff --git a/Source/Engine/Engine/Engine.cpp b/Source/Engine/Engine/Engine.cpp index 338d2ff4c..093b4080d 100644 --- a/Source/Engine/Engine/Engine.cpp +++ b/Source/Engine/Engine/Engine.cpp @@ -548,6 +548,8 @@ void EngineImpl::InitPaths() Globals::EngineContentFolder = Globals::StartupFolder / TEXT("Content"); #if PLATFORM_WINDOWS Globals::MonoPath = Globals::StartupFolder / TEXT("Source/Platforms/Editor/Windows/Mono"); +#elif PLATFORM_LINUX + Globals::MonoPath = Globals::StartupFolder / TEXT("Source/Platforms/Editor/Linux/Mono"); #else #error "Please specify the Mono data location for Editor on this platform." #endif diff --git a/Source/Engine/Graphics/Models/ModelData.Tool.cpp b/Source/Engine/Graphics/Models/ModelData.Tool.cpp index 814e0d4ba..ea9a066d3 100644 --- a/Source/Engine/Graphics/Models/ModelData.Tool.cpp +++ b/Source/Engine/Graphics/Models/ModelData.Tool.cpp @@ -20,6 +20,8 @@ #endif #include +#if PLATFORM_WINDOWS + // Import UVAtlas library // Source: https://github.com/Microsoft/UVAtlas #include @@ -55,6 +57,8 @@ HRESULT __cdecl UVAtlasCallback(float fPercentDone) return S_OK; } +#endif + template void RemapArrayHelper(Array& target, const std::vector& remap) { @@ -71,6 +75,7 @@ void RemapArrayHelper(Array& target, const std::vector& remap) bool MeshData::GenerateLightmapUVs() { +#if PLATFORM_WINDOWS // Prepare HRESULT hr; int32 verticesCount = Positions.Count(); @@ -137,6 +142,9 @@ bool MeshData::GenerateLightmapUVs() uint32* ibP = (uint32*)ib.data(); for (int32 i = 0; i < Indices.Count(); i++) Indices[i] = *ibP++; +#else + LOG(Error, "Model lightmap UVs generation is not supported on this platform."); +#endif return false; } diff --git a/Source/Engine/Graphics/Shaders/Cache/ShaderAssetBase.cpp b/Source/Engine/Graphics/Shaders/Cache/ShaderAssetBase.cpp index cba069600..ec84250ee 100644 --- a/Source/Engine/Graphics/Shaders/Cache/ShaderAssetBase.cpp +++ b/Source/Engine/Graphics/Shaders/Cache/ShaderAssetBase.cpp @@ -230,6 +230,8 @@ bool ShaderAssetBase::LoadShaderCache(ShaderCacheResult& result) auto& platformDefine = options.Macros.AddOne(); #if PLATFORM_WINDOWS platformDefine.Name = "PLATFORM_WINDOWS"; +#elif PLATFORM_LINUX + platformDefine.Name = "PLATFORM_LINUX"; #else #error "Unknown platform." #endif diff --git a/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.h b/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.h index e48cafebb..f03ed97f4 100644 --- a/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.h +++ b/Source/Engine/ShadersCompilation/Parser/ShaderFunctionReader.h @@ -337,8 +337,8 @@ namespace ShaderProcessing ShaderFunctionReader() { - _childReaders.Add(_permutationReader = New(this)); - _childReaders.Add(New(this)); + ShaderMetaReaderType::_childReaders.Add(_permutationReader = New(this)); + ShaderMetaReaderType::_childReaders.Add(New(this)); } ~ShaderFunctionReader() @@ -353,10 +353,11 @@ namespace ShaderProcessing Token token; // Clear current meta - _current.Name.Clear(); - _current.Permutations.Clear(); - _current.Flags = ShaderFlags::Default; - _current.MinFeatureLevel = FeatureLevel::ES2; + auto& current = ShaderMetaReaderType::_current; + current.Name.Clear(); + current.Permutations.Clear(); + current.Flags = ShaderFlags::Default; + current.MinFeatureLevel = FeatureLevel::ES2; _permutationReader->Clear(); // Here we read '(x, y)\n' where 'x' is a shader function 'visible' flag, and 'y' is mini feature level @@ -369,7 +370,7 @@ namespace ShaderProcessing else if (token == "false" || token == "0") { // Hidden shader - _current.Flags = ShaderFlags::Hidden; + current.Flags = ShaderFlags::Hidden; } else { @@ -396,7 +397,7 @@ namespace ShaderProcessing { if (token == levels[i].Token) { - _current.MinFeatureLevel = levels[i].Level; + current.MinFeatureLevel = levels[i].Level; missing = false; break; } @@ -413,25 +414,27 @@ namespace ShaderProcessing void OnParseAfter(IShaderParser* parser, Reader& text) override { + auto& current = ShaderMetaReaderType::_current; + // Validate amount of permutations - if (_current.Permutations.Count() > SHADER_PERMUTATIONS_MAX_COUNT) + if (current.Permutations.Count() > SHADER_PERMUTATIONS_MAX_COUNT) { - parser->OnError(String::Format(TEXT("Function \'{0}\' uses too many permutations. Maximum allowed amount is {1}."), String(_current.Name), SHADER_PERMUTATIONS_MAX_COUNT)); + parser->OnError(String::Format(TEXT("Function \'{0}\' uses too many permutations. Maximum allowed amount is {1}."), String(current.Name), SHADER_PERMUTATIONS_MAX_COUNT)); return; } // Check if shader has no permutations - if (_current.Permutations.IsEmpty()) + if (current.Permutations.IsEmpty()) { // Just add blank permutation (rest of the code will work without any hacks for empty permutations list) - _current.Permutations.Add(ShaderPermutation()); + current.Permutations.Add(ShaderPermutation()); } // Check if use this shader program - if ((_current.Flags & ShaderFlags::Hidden) == false && _current.MinFeatureLevel <= parser->GetFeatureLevel()) + if ((current.Flags & ShaderFlags::Hidden) == false && current.MinFeatureLevel <= parser->GetFeatureLevel()) { // Cache read function - _cache.Add(_current); + ShaderMetaReaderType::_cache.Add(current); } } }; @@ -440,7 +443,7 @@ namespace ShaderProcessing #define DECLARE_SHADER_META_READER_HEADER(tokenName, shaderMetaMemberCollection) public: \ bool CheckStartToken(const Token& token) override \ { return token == tokenName; } \ - void FlushCache(IShaderParser* parser, ShaderMeta* result) \ + void FlushCache(IShaderParser* parser, ShaderMeta* result) override \ { result->shaderMetaMemberCollection.Add(_cache); } #endif