Fixes for building editor for Linux
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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 <fstream>
|
||||
|
||||
#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");
|
||||
|
||||
@@ -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<Scene*> 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<bool(Actor*, MeshesArray&, MeshesLookup&)> treeWalkFunction(walkTree);
|
||||
SceneQuery::TreeExecute<Array<CSG::Mesh*>&, MeshesLookup&>(treeWalkFunction, meshes, cache);
|
||||
SceneQuery::TreeExecute<Array<CSG::Mesh*>&, 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<RawDataAsset>(outputRawDataAssetId);
|
||||
scene->CSGData.Model = Content::LoadAsync<Model>(outputModelAssetId);
|
||||
scene->CSGData.CollisionData = Content::LoadAsync<CollisionData>(outputCollisionDataAssetId);
|
||||
scene->CSGData.Data = Content::LoadAsync<RawDataAsset>(data.outputRawDataAssetId);
|
||||
scene->CSGData.Model = Content::LoadAsync<Model>(data.outputModelAssetId);
|
||||
scene->CSGData.CollisionData = Content::LoadAsync<CollisionData>(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)
|
||||
|
||||
@@ -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<bool(Actor*)> function = [](Actor* actor)-> bool
|
||||
{
|
||||
if (actor->IsActiveInHierarchy())
|
||||
{
|
||||
actor->OnDebugDraw();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Function<bool(Actor*)> function;
|
||||
function.Bind(&DrawActorsTreeWalk);
|
||||
SceneQuery::TreeExecute(function);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#endif
|
||||
#include <stack>
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
|
||||
// Import UVAtlas library
|
||||
// Source: https://github.com/Microsoft/UVAtlas
|
||||
#include <ThirdParty/UVAtlas/UVAtlas.h>
|
||||
@@ -55,6 +57,8 @@ HRESULT __cdecl UVAtlasCallback(float fPercentDone)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
void RemapArrayHelper(Array<T>& target, const std::vector<uint32_t>& remap)
|
||||
{
|
||||
@@ -71,6 +75,7 @@ void RemapArrayHelper(Array<T>& target, const std::vector<uint32_t>& 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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -337,8 +337,8 @@ namespace ShaderProcessing
|
||||
|
||||
ShaderFunctionReader()
|
||||
{
|
||||
_childReaders.Add(_permutationReader = New<PermutationReader>(this));
|
||||
_childReaders.Add(New<FlagReader>(this));
|
||||
ShaderMetaReaderType::_childReaders.Add(_permutationReader = New<PermutationReader>(this));
|
||||
ShaderMetaReaderType::_childReaders.Add(New<FlagReader>(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
|
||||
|
||||
Reference in New Issue
Block a user