Fixes for building editor for Linux

This commit is contained in:
mafiesto4
2021-01-05 16:23:02 +01:00
parent e4936547e3
commit efa5d05f5f
8 changed files with 105 additions and 66 deletions

View File

@@ -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();

View File

@@ -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");

View 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)

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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