Merge remote-tracking branch 'origin/master' into gi
# Conflicts: # Flax.flaxproj # Source/Engine/Core/Math/Vector3.h # Source/Engine/Graphics/Textures/GPUTexture.cpp # Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp # Source/Engine/Terrain/Terrain.cpp # Source/Engine/Tools/ModelTool/ModelTool.Build.cs # Source/FlaxEngine.Gen.cs # Source/FlaxEngine.Gen.h
This commit is contained in:
4
.github/workflows/build_windows.yml
vendored
4
.github/workflows/build_windows.yml
vendored
@@ -6,7 +6,7 @@ jobs:
|
||||
# Editor
|
||||
editor-windows:
|
||||
name: Editor (Windows, Development x64)
|
||||
runs-on: "windows-latest"
|
||||
runs-on: "windows-2019"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
# Game
|
||||
game-windows:
|
||||
name: Game (Windows, Release x64)
|
||||
runs-on: "windows-latest"
|
||||
runs-on: "windows-2019"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
|
||||
4
.github/workflows/cd.yml
vendored
4
.github/workflows/cd.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
# Windows
|
||||
package-windows-editor:
|
||||
name: Editor (Windows)
|
||||
runs-on: "windows-latest"
|
||||
runs-on: "windows-2019"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
path: Output/EditorDebugSymbols.zip
|
||||
package-windows-game:
|
||||
name: Game (Windows)
|
||||
runs-on: "windows-latest"
|
||||
runs-on: "windows-2019"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
|
||||
@@ -163,6 +163,12 @@ namespace FlaxEditor.Content.Import
|
||||
[EditorOrder(90), DefaultValue(ModelLightmapUVsSource.Disable), EditorDisplay("Geometry", "Lightmap UVs Source"), Tooltip("Model lightmap UVs source")]
|
||||
public ModelLightmapUVsSource LightmapUVsSource { get; set; } = ModelLightmapUVsSource.Disable;
|
||||
|
||||
/// <summary>
|
||||
/// If specified, all meshes which name starts with this prefix will be imported as a separate collision data (excluded used for rendering).
|
||||
/// </summary>
|
||||
[EditorOrder(100), DefaultValue(""), EditorDisplay("Geometry")]
|
||||
public string CollisionMeshesPrefix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Custom uniform import scale.
|
||||
/// </summary>
|
||||
@@ -284,7 +290,7 @@ namespace FlaxEditor.Content.Import
|
||||
/// </summary>
|
||||
[EditorOrder(420), DefaultValue(true), EditorDisplay("Materials", "Restore Materials On Reimport"), Tooltip("If checked, the importer will try to restore the assigned materials to the model slots.")]
|
||||
public bool RestoreMaterialsOnReimport { get; set; } = true;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If checked, the imported mesh/animations are splitted into separate assets. Used if ObjectIndex is set to -1.
|
||||
/// </summary>
|
||||
@@ -314,6 +320,7 @@ namespace FlaxEditor.Content.Import
|
||||
public byte ImportVertexColors;
|
||||
public byte ImportBlendShapes;
|
||||
public ModelLightmapUVsSource LightmapUVsSource;
|
||||
public string CollisionMeshesPrefix;
|
||||
|
||||
// Transform
|
||||
public float Scale;
|
||||
@@ -364,6 +371,7 @@ namespace FlaxEditor.Content.Import
|
||||
ImportVertexColors = (byte)(ImportVertexColors ? 1 : 0),
|
||||
ImportBlendShapes = (byte)(ImportBlendShapes ? 1 : 0),
|
||||
LightmapUVsSource = LightmapUVsSource,
|
||||
CollisionMeshesPrefix = CollisionMeshesPrefix,
|
||||
Scale = Scale,
|
||||
Rotation = Rotation,
|
||||
Translation = Translation,
|
||||
@@ -403,6 +411,7 @@ namespace FlaxEditor.Content.Import
|
||||
ImportVertexColors = options.ImportVertexColors != 0;
|
||||
ImportBlendShapes = options.ImportBlendShapes != 0;
|
||||
LightmapUVsSource = options.LightmapUVsSource;
|
||||
CollisionMeshesPrefix = options.CollisionMeshesPrefix;
|
||||
Scale = options.Scale;
|
||||
Rotation = options.Rotation;
|
||||
Translation = options.Translation;
|
||||
|
||||
@@ -86,6 +86,7 @@ namespace FlaxEditor.Content
|
||||
{
|
||||
foreach (var child in modelItem.ParentFolder.Children)
|
||||
{
|
||||
// Check if there is collision that was made with this model
|
||||
if (child is BinaryAssetItem b && b.IsOfType<CollisionData>())
|
||||
{
|
||||
var collisionData = FlaxEngine.Content.Load<CollisionData>(b.ID);
|
||||
@@ -97,6 +98,25 @@ namespace FlaxEditor.Content
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there is a auto-imported collision
|
||||
if (child is ContentFolder childFolder && childFolder.ShortName == modelItem.ShortName)
|
||||
{
|
||||
foreach (var childFolderChild in childFolder.Children)
|
||||
{
|
||||
if (childFolderChild is BinaryAssetItem c && c.IsOfType<CollisionData>())
|
||||
{
|
||||
var collisionData = FlaxEngine.Content.Load<CollisionData>(c.ID);
|
||||
if (collisionData && (collisionData.Options.Model == model.ID || collisionData.Options.Model == Guid.Empty))
|
||||
{
|
||||
Editor.Instance.Windows.ContentWin.Select(c);
|
||||
if (created != null)
|
||||
FlaxEngine.Scripting.InvokeOnUpdate(() => created(collisionData));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -229,7 +229,13 @@ namespace FlaxEditor.CustomEditors
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
if (!Equals(this[i], _defaultValue))
|
||||
{
|
||||
// Special case for String (null string is kind of equal to empty string from the user perspective)
|
||||
if (this[i] == null && _defaultValue is string defaultValueStr && defaultValueStr.Length == 0)
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -227,8 +227,8 @@ namespace FlaxEditor.GUI.Tabs
|
||||
/// </summary>
|
||||
public Tab SelectedTab
|
||||
{
|
||||
get => _selectedIndex == -1 ? null : Children[_selectedIndex + 1] as Tab;
|
||||
set => SelectedTabIndex = Children.IndexOf(value) - 1;
|
||||
get => _selectedIndex == -1 && Children.Count > _selectedIndex + 1 ? null : Children[_selectedIndex + 1] as Tab;
|
||||
set => SelectedTabIndex = value != null ? Children.IndexOf(value) - 1 : -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -166,6 +166,7 @@ struct InternalModelOptions
|
||||
byte ImportVertexColors;
|
||||
byte ImportBlendShapes;
|
||||
ModelLightmapUVsSource LightmapUVsSource;
|
||||
MonoString* CollisionMeshesPrefix;
|
||||
|
||||
// Transform
|
||||
float Scale;
|
||||
@@ -213,6 +214,7 @@ struct InternalModelOptions
|
||||
to->ImportVertexColors = from->ImportVertexColors;
|
||||
to->ImportBlendShapes = from->ImportBlendShapes;
|
||||
to->LightmapUVsSource = from->LightmapUVsSource;
|
||||
to->CollisionMeshesPrefix = MUtils::ToString(from->CollisionMeshesPrefix);
|
||||
to->Scale = from->Scale;
|
||||
to->Rotation = from->Rotation;
|
||||
to->Translation = from->Translation;
|
||||
@@ -251,6 +253,7 @@ struct InternalModelOptions
|
||||
to->ImportVertexColors = from->ImportVertexColors;
|
||||
to->ImportBlendShapes = from->ImportBlendShapes;
|
||||
to->LightmapUVsSource = from->LightmapUVsSource;
|
||||
to->CollisionMeshesPrefix = MUtils::ToString(from->CollisionMeshesPrefix);
|
||||
to->Scale = from->Scale;
|
||||
to->Rotation = from->Rotation;
|
||||
to->Translation = from->Translation;
|
||||
|
||||
@@ -93,6 +93,11 @@ namespace FlaxEditor.Options
|
||||
public void Load()
|
||||
{
|
||||
Editor.Log("Loading editor options");
|
||||
if (!File.Exists(_optionsFilePath))
|
||||
{
|
||||
Editor.LogWarning("Missing editor settings");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -100,12 +105,12 @@ namespace FlaxEditor.Options
|
||||
var asset = FlaxEngine.Content.LoadAsync<JsonAsset>(_optionsFilePath);
|
||||
if (asset == null)
|
||||
{
|
||||
Editor.LogWarning("Missing or invalid editor settings");
|
||||
Editor.LogWarning("Invalid editor settings");
|
||||
return;
|
||||
}
|
||||
if (asset.WaitForLoaded())
|
||||
{
|
||||
Editor.LogWarning("Failed to load editor settings");
|
||||
Editor.LogError("Failed to load editor settings");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,22 @@ void CodeEditingManager::OpenSolution(CodeEditorTypes editorType)
|
||||
const auto editor = GetCodeEditor(editorType);
|
||||
if (editor)
|
||||
{
|
||||
OpenSolution(editor);
|
||||
// Ensure that no async task is running
|
||||
if (IsAsyncOpenRunning())
|
||||
{
|
||||
// TODO: enqueue action and handle many actions in the queue
|
||||
LOG(Warning, "Cannot use code editor during async open action.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (editor->UseAsyncForOpen())
|
||||
{
|
||||
AsyncOpenTask::OpenSolution(editor);
|
||||
}
|
||||
else
|
||||
{
|
||||
editor->OpenSolution();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -201,26 +216,6 @@ void CodeEditingManager::OnFileAdded(CodeEditorTypes editorType, const String& p
|
||||
}
|
||||
}
|
||||
|
||||
void CodeEditingManager::OpenSolution(CodeEditor* editor)
|
||||
{
|
||||
// Ensure that no async task is running
|
||||
if (IsAsyncOpenRunning())
|
||||
{
|
||||
// TODO: enqueue action and handle many actions in the queue
|
||||
LOG(Warning, "Cannot use code editor during async open action.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (editor->UseAsyncForOpen())
|
||||
{
|
||||
AsyncOpenTask::OpenSolution(editor);
|
||||
}
|
||||
else
|
||||
{
|
||||
editor->OpenSolution();
|
||||
}
|
||||
}
|
||||
|
||||
void OnAsyncBegin(Thread* thread)
|
||||
{
|
||||
ASSERT(AsyncOpenThread == nullptr);
|
||||
|
||||
@@ -193,12 +193,6 @@ public:
|
||||
/// <param name="path">The path.</param>
|
||||
API_FUNCTION() static void OnFileAdded(CodeEditorTypes editorType, const String& path);
|
||||
|
||||
/// <summary>
|
||||
/// Opens the solution project. Handles async opening.
|
||||
/// </summary>
|
||||
/// <param name="editor">The code editor.</param>
|
||||
static void OpenSolution(CodeEditor* editor);
|
||||
|
||||
/// <summary>
|
||||
/// The asynchronous open begins.
|
||||
/// </summary>
|
||||
|
||||
@@ -156,7 +156,7 @@ bool ScriptsBuilder::IsSourceWorkspaceDirty()
|
||||
return _wasProjectStructureChanged;
|
||||
}
|
||||
|
||||
bool ScriptsBuilder::IsSourceDirty(const TimeSpan& timeout)
|
||||
bool ScriptsBuilder::IsSourceDirtyFor(const TimeSpan& timeout)
|
||||
{
|
||||
ScopeLock scopeLock(_locker);
|
||||
return _lastSourceCodeEdited > (_lastCompileAction + timeout);
|
||||
@@ -626,7 +626,7 @@ void ScriptsBuilderService::Update()
|
||||
// Check if compile code (if has been edited)
|
||||
const TimeSpan timeToCallCompileIfDirty = TimeSpan::FromMilliseconds(50);
|
||||
auto mainWindow = Engine::MainWindow;
|
||||
if (ScriptsBuilder::IsSourceDirty(timeToCallCompileIfDirty) && mainWindow && mainWindow->IsFocused())
|
||||
if (ScriptsBuilder::IsSourceDirtyFor(timeToCallCompileIfDirty) && mainWindow && mainWindow->IsFocused())
|
||||
{
|
||||
// Check if auto reload is enabled
|
||||
if (Editor::Managed->CanAutoReloadScripts())
|
||||
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="timeout">Time to use for checking.</param>
|
||||
/// <returns>True if source code is dirty, otherwise false.</returns>
|
||||
static bool IsSourceDirty(const TimeSpan& timeout);
|
||||
static bool IsSourceDirtyFor(const TimeSpan& timeout);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if scripts are being now compiled/reloaded.
|
||||
|
||||
@@ -829,7 +829,13 @@ namespace FlaxEditor.Utilities
|
||||
var attr = field.GetAttribute<System.ComponentModel.DefaultValueAttribute>();
|
||||
if (attr != null)
|
||||
{
|
||||
field.SetValue(obj, attr.Value);
|
||||
// Prevent value type conflicts
|
||||
var value = attr.Value;
|
||||
var fieldType = field.ValueType.Type;
|
||||
if (value != null && value.GetType() != fieldType)
|
||||
value = Convert.ChangeType(value, fieldType);
|
||||
|
||||
field.SetValue(obj, value);
|
||||
}
|
||||
else if (isStructure)
|
||||
{
|
||||
@@ -845,7 +851,13 @@ namespace FlaxEditor.Utilities
|
||||
var attr = property.GetAttribute<System.ComponentModel.DefaultValueAttribute>();
|
||||
if (attr != null)
|
||||
{
|
||||
property.SetValue(obj, attr.Value);
|
||||
// Prevent value type conflicts
|
||||
var value = attr.Value;
|
||||
var propertyType = property.ValueType.Type;
|
||||
if (value != null && value.GetType() != propertyType)
|
||||
value = Convert.ChangeType(value, propertyType);
|
||||
|
||||
property.SetValue(obj, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Asset.h"
|
||||
#include "Content.h"
|
||||
#include "SoftAssetReference.h"
|
||||
#include "Cache/AssetsCache.h"
|
||||
#include "Loading/ContentLoadingManager.h"
|
||||
#include "Loading/Tasks/LoadAssetTask.h"
|
||||
@@ -102,6 +103,65 @@ void WeakAssetReferenceBase::OnUnloaded(Asset* asset)
|
||||
_asset = nullptr;
|
||||
}
|
||||
|
||||
String SoftAssetReferenceBase::ToString() const
|
||||
{
|
||||
return _asset ? _asset->ToString() : (_id.IsValid() ? _id.ToString() : TEXT("<null>"));
|
||||
}
|
||||
|
||||
void SoftAssetReferenceBase::OnSet(Asset* asset)
|
||||
{
|
||||
if (_asset == asset)
|
||||
return;
|
||||
if (_asset)
|
||||
{
|
||||
_asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
_asset->RemoveReference();
|
||||
}
|
||||
_asset = asset;
|
||||
_id = asset ? asset->GetID() : Guid::Empty;
|
||||
if (asset)
|
||||
{
|
||||
asset->AddReference();
|
||||
asset->OnUnloaded.Bind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
}
|
||||
Changed();
|
||||
}
|
||||
|
||||
void SoftAssetReferenceBase::OnSet(const Guid& id)
|
||||
{
|
||||
if (_id == id)
|
||||
return;
|
||||
if (_asset)
|
||||
{
|
||||
_asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
_asset->RemoveReference();
|
||||
}
|
||||
_asset = nullptr;
|
||||
_id = id;
|
||||
Changed();
|
||||
}
|
||||
|
||||
void SoftAssetReferenceBase::OnResolve(const ScriptingTypeHandle& type)
|
||||
{
|
||||
ASSERT(!_asset);
|
||||
_asset = ::LoadAsset(_id, type);
|
||||
if (_asset)
|
||||
{
|
||||
_asset->OnUnloaded.Bind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
_asset->AddReference();
|
||||
}
|
||||
}
|
||||
|
||||
void SoftAssetReferenceBase::OnUnloaded(Asset* asset)
|
||||
{
|
||||
ASSERT(_asset == asset);
|
||||
_asset->RemoveReference();
|
||||
_asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
_asset = nullptr;
|
||||
_id = Guid::Empty;
|
||||
Changed();
|
||||
}
|
||||
|
||||
Asset::Asset(const SpawnParams& params, const AssetInfo* info)
|
||||
: ManagedScriptingObject(params)
|
||||
, _refCount(0)
|
||||
|
||||
234
Source/Engine/Content/SoftAssetReference.h
Normal file
234
Source/Engine/Content/SoftAssetReference.h
Normal file
@@ -0,0 +1,234 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Content/Asset.h"
|
||||
|
||||
/// <summary>
|
||||
/// The asset soft reference. Asset gets referenced (loaded) on actual use (ID reference is resolving it).
|
||||
/// </summary>
|
||||
class FLAXENGINE_API SoftAssetReferenceBase
|
||||
{
|
||||
protected:
|
||||
Asset* _asset = nullptr;
|
||||
Guid _id = Guid::Empty;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Action fired when field gets changed (link a new asset or change to the another value).
|
||||
/// </summary>
|
||||
Delegate<> Changed;
|
||||
|
||||
public:
|
||||
NON_COPYABLE(SoftAssetReferenceBase);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SoftAssetReferenceBase"/> class.
|
||||
/// </summary>
|
||||
SoftAssetReferenceBase() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="SoftAssetReferenceBase"/> class.
|
||||
/// </summary>
|
||||
~SoftAssetReferenceBase()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the asset ID or Guid::Empty if not set.
|
||||
/// </summary>
|
||||
FORCE_INLINE Guid GetID() const
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the asset property value as string.
|
||||
/// </summary>
|
||||
String ToString() const;
|
||||
|
||||
protected:
|
||||
void OnSet(Asset* asset);
|
||||
void OnSet(const Guid& id);
|
||||
void OnResolve(const ScriptingTypeHandle& type);
|
||||
void OnUnloaded(Asset* asset);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The asset soft reference. Asset gets referenced (loaded) on actual use (ID reference is resolving it).
|
||||
/// </summary>
|
||||
template<typename T>
|
||||
API_CLASS(InBuild) class SoftAssetReference : public SoftAssetReferenceBase
|
||||
{
|
||||
public:
|
||||
typedef T AssetType;
|
||||
typedef SoftAssetReference<T> Type;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SoftAssetReference"/> class.
|
||||
/// </summary>
|
||||
SoftAssetReference()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SoftAssetReference"/> class.
|
||||
/// </summary>
|
||||
/// <param name="asset">The asset to set.</param>
|
||||
SoftAssetReference(T* asset)
|
||||
{
|
||||
OnSet(asset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SoftAssetReference"/> class.
|
||||
/// </summary>
|
||||
/// <param name="other">The other.</param>
|
||||
SoftAssetReference(const SoftAssetReference& other)
|
||||
{
|
||||
OnSet(other.Get());
|
||||
}
|
||||
|
||||
SoftAssetReference(SoftAssetReference&& other)
|
||||
{
|
||||
OnSet(other.Get());
|
||||
other.OnSet(nullptr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="SoftAssetReference"/> class.
|
||||
/// </summary>
|
||||
~SoftAssetReference()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
FORCE_INLINE bool operator==(T* other)
|
||||
{
|
||||
return Get() == other;
|
||||
}
|
||||
FORCE_INLINE bool operator==(const SoftAssetReference& other)
|
||||
{
|
||||
return GetID() == other.GetID();
|
||||
}
|
||||
FORCE_INLINE bool operator!=(T* other)
|
||||
{
|
||||
return Get() != other;
|
||||
}
|
||||
FORCE_INLINE bool operator!=(const SoftAssetReference& other)
|
||||
{
|
||||
return GetID() != other.GetID();
|
||||
}
|
||||
SoftAssetReference& operator=(const SoftAssetReference& other)
|
||||
{
|
||||
if (this != &other)
|
||||
OnSet(other.GetID());
|
||||
return *this;
|
||||
}
|
||||
SoftAssetReference& operator=(SoftAssetReference&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
OnSet(other.GetID());
|
||||
other.OnSet(nullptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
FORCE_INLINE SoftAssetReference& operator=(const T& other)
|
||||
{
|
||||
OnSet(&other);
|
||||
return *this;
|
||||
}
|
||||
FORCE_INLINE SoftAssetReference& operator=(T* other)
|
||||
{
|
||||
OnSet(other);
|
||||
return *this;
|
||||
}
|
||||
FORCE_INLINE SoftAssetReference& operator=(const Guid& id)
|
||||
{
|
||||
OnSet(id);
|
||||
return *this;
|
||||
}
|
||||
FORCE_INLINE operator T*() const
|
||||
{
|
||||
return (T*)Get();
|
||||
}
|
||||
FORCE_INLINE operator bool() const
|
||||
{
|
||||
return Get() != nullptr;
|
||||
}
|
||||
FORCE_INLINE T* operator->() const
|
||||
{
|
||||
return (T*)Get();
|
||||
}
|
||||
template<typename U>
|
||||
FORCE_INLINE U* As() const
|
||||
{
|
||||
return static_cast<U*>(Get());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets the asset (or null if unassigned).
|
||||
/// </summary>
|
||||
T* Get() const
|
||||
{
|
||||
if (!_asset)
|
||||
const_cast<SoftAssetReference*>(this)->OnResolve(T::TypeInitializer);
|
||||
return (T*)_asset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets managed instance object (or null if no asset linked).
|
||||
/// </summary>
|
||||
MObject* GetManagedInstance() const
|
||||
{
|
||||
auto asset = Get();
|
||||
return asset ? asset->GetOrCreateManagedInstance() : nullptr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether asset is assigned and managed instance of the asset is alive.
|
||||
/// </summary>
|
||||
bool HasManagedInstance() const
|
||||
{
|
||||
auto asset = Get();
|
||||
return asset && asset->HasManagedInstance();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the managed instance object or creates it if missing or null if not assigned.
|
||||
/// </summary>
|
||||
MObject* GetOrCreateManagedInstance() const
|
||||
{
|
||||
auto asset = Get();
|
||||
return asset ? asset->GetOrCreateManagedInstance() : nullptr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the asset.
|
||||
/// </summary>
|
||||
/// <param name="id">The object ID. Uses Scripting to find the registered asset of the given ID.</param>
|
||||
FORCE_INLINE void Set(const Guid& id)
|
||||
{
|
||||
OnSet(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the asset.
|
||||
/// </summary>
|
||||
/// <param name="asset">The asset.</param>
|
||||
FORCE_INLINE void Set(T* asset)
|
||||
{
|
||||
OnSet(asset);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
uint32 GetHash(const SoftAssetReference<T>& key)
|
||||
{
|
||||
return GetHash(key.GetID());
|
||||
}
|
||||
@@ -75,8 +75,8 @@ ExportAssetResult AssetExporters::ExportModel(ExportAssetContext& context)
|
||||
|
||||
for (uint32 i = 0; i < vertices; i++)
|
||||
{
|
||||
auto v = vb1[i].TexCoord;
|
||||
output->WriteText(StringAnsi::Format("vt {0} {1}\n", Float16Compressor::Decompress(v.X), Float16Compressor::Decompress(v.Y)));
|
||||
auto v = vb1[i].TexCoord.ToVector2();
|
||||
output->WriteText(StringAnsi::Format("vt {0} {1}\n", v.X, v.Y));
|
||||
}
|
||||
|
||||
output->WriteChar('\n');
|
||||
@@ -180,8 +180,8 @@ ExportAssetResult AssetExporters::ExportSkinnedModel(ExportAssetContext& context
|
||||
|
||||
for (uint32 i = 0; i < vertices; i++)
|
||||
{
|
||||
auto v = vb0[i].TexCoord;
|
||||
output->WriteText(StringAnsi::Format("vt {0} {1}\n", Float16Compressor::Decompress(v.X), Float16Compressor::Decompress(v.Y)));
|
||||
auto v = vb0[i].TexCoord.ToVector2();
|
||||
output->WriteText(StringAnsi::Format("vt {0} {1}\n", v.X, v.Y));
|
||||
}
|
||||
|
||||
output->WriteChar('\n');
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
|
||||
#if COMPILE_WITH_ASSETS_IMPORTER
|
||||
|
||||
#if COMPILE_WITH_PHYSICS_COOKING
|
||||
#include "Engine/Physics/CollisionCooking.h"
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Creating collision data asset utility
|
||||
@@ -23,7 +25,6 @@ public:
|
||||
static CreateAssetResult Create(CreateAssetContext& context);
|
||||
|
||||
#if COMPILE_WITH_PHYSICS_COOKING
|
||||
|
||||
/// <summary>
|
||||
/// Cooks the mesh collision data and saves it to the asset using <see cref="CollisionData"/> format.
|
||||
/// </summary>
|
||||
@@ -31,7 +32,6 @@ public:
|
||||
/// <param name="arg">The input argument data.</param>
|
||||
/// <returns>True if failed, otherwise false. See log file to track errors better.</returns>
|
||||
static bool CookMeshCollision(const String& outputPath, CollisionCooking::Argument& arg);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -639,7 +639,7 @@ public:
|
||||
{
|
||||
Vector3 output = input;
|
||||
const float length = input.Length();
|
||||
if (!Math::IsZero(length))
|
||||
if (Math::Abs(length) >= ZeroTolerance)
|
||||
{
|
||||
const float inv = 1.0f / length;
|
||||
output.X *= inv;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "Engine/Content/Assets/Shader.h"
|
||||
#include "Engine/Content/Assets/Material.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/SoftAssetReference.h"
|
||||
#include "Engine/Platform/Windows/WindowsWindow.h"
|
||||
#include "Engine/Render2D/Render2D.h"
|
||||
#include "Engine/Engine/CommandLine.h"
|
||||
@@ -19,7 +20,6 @@
|
||||
#include "Engine/Profiler/Profiler.h"
|
||||
#include "Engine/Renderer/RenderList.h"
|
||||
#include "Engine/Core/Utilities.h"
|
||||
#include "Engine/Scripting/SoftObjectReference.h"
|
||||
|
||||
GPUPipelineState* GPUPipelineState::Spawn(const SpawnParams& params)
|
||||
{
|
||||
@@ -253,7 +253,7 @@ struct GPUDevice::PrivateData
|
||||
GPUPipelineState* PS_Clear = nullptr;
|
||||
GPUBuffer* FullscreenTriangleVB = nullptr;
|
||||
AssetReference<Material> DefaultMaterial;
|
||||
SoftObjectReference<Material> DefaultDeformableMaterial;
|
||||
SoftAssetReference<Material> DefaultDeformableMaterial;
|
||||
AssetReference<Texture> DefaultNormalMap;
|
||||
AssetReference<Texture> DefaultWhiteTexture;
|
||||
AssetReference<Texture> DefaultBlackTexture;
|
||||
|
||||
@@ -9,7 +9,7 @@ BlendShapesInstance::MeshInstance::MeshInstance()
|
||||
: IsUsed(false)
|
||||
, IsDirty(false)
|
||||
, DirtyMinVertexIndex(0)
|
||||
, DirtyMaxVertexIndex(MAX_uint32)
|
||||
, DirtyMaxVertexIndex(MAX_uint32 - 1)
|
||||
, VertexBuffer(0, sizeof(VB0SkinnedElementType), TEXT("Skinned Mesh Blend Shape"))
|
||||
{
|
||||
}
|
||||
@@ -112,7 +112,7 @@ void BlendShapesInstance::Update(SkinnedModel* skinnedModel)
|
||||
// Initialize the dynamic vertex buffer data (use the dirty range from the previous update to be cleared with initial data)
|
||||
instance.VertexBuffer.Data.Resize(vertexBuffer.Length());
|
||||
const uint32 dirtyVertexDataStart = instance.DirtyMinVertexIndex * sizeof(VB0SkinnedElementType);
|
||||
const uint32 dirtyVertexDataLength = Math::Min<uint32>(instance.DirtyMaxVertexIndex - instance.DirtyMinVertexIndex, vertexCount) * sizeof(VB0SkinnedElementType);
|
||||
const uint32 dirtyVertexDataLength = Math::Min<uint32>(instance.DirtyMaxVertexIndex - instance.DirtyMinVertexIndex + 1, vertexCount) * sizeof(VB0SkinnedElementType);
|
||||
Platform::MemoryCopy(instance.VertexBuffer.Data.Get() + dirtyVertexDataStart, vertexBuffer.Get() + dirtyVertexDataStart, dirtyVertexDataLength);
|
||||
|
||||
// Blend all blend shapes
|
||||
|
||||
@@ -589,6 +589,17 @@ void MeshData::Merge(MeshData& other)
|
||||
}
|
||||
}
|
||||
|
||||
bool MaterialSlotEntry::UsesProperties() const
|
||||
{
|
||||
return Diffuse.Color != Color::White ||
|
||||
Diffuse.TextureIndex != -1 ||
|
||||
Emissive.Color != Color::Transparent ||
|
||||
Emissive.TextureIndex != -1 ||
|
||||
!Math::IsOne(Opacity.Value) ||
|
||||
Opacity.TextureIndex != -1 ||
|
||||
Normals.TextureIndex != -1;
|
||||
}
|
||||
|
||||
void ModelData::CalculateLODsScreenSizes()
|
||||
{
|
||||
const float autoComputeLodPowerBase = 0.5f;
|
||||
|
||||
@@ -373,16 +373,7 @@ struct FLAXENGINE_API MaterialSlotEntry
|
||||
|
||||
bool TwoSided = false;
|
||||
|
||||
bool UsesProperties() const
|
||||
{
|
||||
return Diffuse.Color != Color::White ||
|
||||
Diffuse.TextureIndex != -1 ||
|
||||
Emissive.Color != Color::Transparent ||
|
||||
Emissive.TextureIndex != -1 ||
|
||||
!Math::IsOne(Opacity.Value) ||
|
||||
Opacity.TextureIndex != -1 ||
|
||||
Normals.TextureIndex != -1;
|
||||
}
|
||||
bool UsesProperties() const;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "PixelFormatExtensions.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Core/Math/Math.h"
|
||||
|
||||
// ReSharper disable CppClangTidyClangDiagnosticSwitchEnum
|
||||
|
||||
@@ -1047,7 +1047,7 @@ void GPUContextVulkan::BindIB(GPUBuffer* indexBuffer)
|
||||
void GPUContextVulkan::BindSampler(int32 slot, GPUSampler* sampler)
|
||||
{
|
||||
ASSERT(slot >= GPU_STATIC_SAMPLERS_COUNT && slot < GPU_MAX_SAMPLER_BINDED);
|
||||
const auto handle = sampler ? ((GPUSamplerVulkan*)sampler)->Sampler : nullptr;
|
||||
const auto handle = sampler ? ((GPUSamplerVulkan*)sampler)->Sampler : VK_NULL_HANDLE;
|
||||
_samplerHandles[slot] = handle;
|
||||
}
|
||||
|
||||
|
||||
@@ -366,7 +366,7 @@ void GPUDeviceVulkan::GetInstanceLayersAndExtensions(Array<const char*>& outInst
|
||||
}
|
||||
|
||||
#if VK_EXT_debug_utils
|
||||
if (!vkTrace && outDebugUtils && FindLayerExtension(globalLayerExtensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME))
|
||||
if (!vkTrace && FindLayerExtension(globalLayerExtensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME))
|
||||
{
|
||||
outInstanceExtensions.Add(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
@@ -185,6 +185,8 @@ bool GPUSwapChainVulkan::CreateSwapChain(int32 width, int32 height)
|
||||
// Flush removed resources
|
||||
_device->DeferredDeletionQueue.ReleaseResources(true);
|
||||
}
|
||||
ASSERT(_surface == VK_NULL_HANDLE);
|
||||
ASSERT_LOW_LAYER(_backBuffers.Count() == 0);
|
||||
|
||||
// Create platform-dependent surface
|
||||
VulkanPlatform::CreateSurface(windowHandle, GPUDeviceVulkan::Instance, &_surface);
|
||||
@@ -205,7 +207,7 @@ bool GPUSwapChainVulkan::CreateSwapChain(int32 width, int32 height)
|
||||
VALIDATE_VULKAN_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, _surface, &surfaceFormatsCount, nullptr));
|
||||
ASSERT(surfaceFormatsCount > 0);
|
||||
|
||||
Array<VkSurfaceFormatKHR> surfaceFormats;
|
||||
Array<VkSurfaceFormatKHR, InlinedAllocation<16>> surfaceFormats;
|
||||
surfaceFormats.AddZeroed(surfaceFormatsCount);
|
||||
VALIDATE_VULKAN_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, _surface, &surfaceFormatsCount, surfaceFormats.Get()));
|
||||
|
||||
@@ -414,8 +416,8 @@ bool GPUSwapChainVulkan::CreateSwapChain(int32 width, int32 height)
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate memory usage
|
||||
_memoryUsage = RenderTools::CalculateTextureMemoryUsage(_format, _width, _height, 1) * _backBuffers.Count();
|
||||
// Estimate memory usage
|
||||
_memoryUsage = 1024 + RenderTools::CalculateTextureMemoryUsage(_format, _width, _height, 1) * _backBuffers.Count();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -270,6 +270,11 @@ bool GPUTextureVulkan::OnInit()
|
||||
imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
if (useUAV)
|
||||
imageInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
|
||||
#if PLATFORM_MAC
|
||||
// MoltenVK: VK_ERROR_FEATURE_NOT_PRESENT: vkCreateImageView(): 2D views on 3D images can only be used as color attachments.
|
||||
if (IsVolume() && _desc.HasPerSliceViews())
|
||||
imageInfo.usage &= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
#endif
|
||||
imageInfo.tiling = optimalTiling ? VK_IMAGE_TILING_OPTIMAL : VK_IMAGE_TILING_LINEAR;
|
||||
imageInfo.samples = (VkSampleCountFlagBits)MultiSampleLevel();
|
||||
// TODO: set initialLayout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL for IsRegularTexture() ???
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
void MacVulkanPlatform::GetInstanceExtensions(Array<const char*>& extensions, Array<const char*>& layers)
|
||||
{
|
||||
extensions.Add(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
extensions.Add(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
|
||||
@@ -1024,10 +1024,12 @@ void UpdateGPU(RenderTask* task, GPUContext* context)
|
||||
const auto& track = particleSystem->Tracks[j];
|
||||
if (track.Type != ParticleSystem::Track::Types::Emitter || track.Disabled)
|
||||
continue;
|
||||
const uint32 emitterIndex = track.AsEmitter.Index;
|
||||
auto emitter = particleSystem->Emitters[emitterIndex].Get();
|
||||
auto& data = instance.Emitters[emitterIndex];
|
||||
if (!emitter || !emitter->IsLoaded() || !data.Buffer || emitter->SimulationMode != ParticlesSimulationMode::GPU)
|
||||
const int32 emitterIndex = track.AsEmitter.Index;
|
||||
ParticleEmitter* emitter = particleSystem->Emitters[emitterIndex].Get();
|
||||
if (!emitter || !emitter->IsLoaded() || emitter->SimulationMode != ParticlesSimulationMode::GPU || instance.Emitters.Count() <= emitterIndex)
|
||||
continue;
|
||||
ParticleEmitterInstance& data = instance.Emitters[emitterIndex];
|
||||
if (!data.Buffer)
|
||||
continue;
|
||||
ASSERT(emitter->Capacity != 0 && emitter->Graph.Layout.Size != 0);
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ void CharacterController::CreateShape()
|
||||
|
||||
void CharacterController::UpdateBounds()
|
||||
{
|
||||
void* actor = PhysicsBackend::GetShapeActor(_shape);
|
||||
void* actor = _shape ? PhysicsBackend::GetShapeActor(_shape) : nullptr;
|
||||
if (actor)
|
||||
PhysicsBackend::GetActorBounds(actor, _box);
|
||||
else
|
||||
|
||||
@@ -837,8 +837,8 @@ DragDropEffect MacWindow::DoDragDrop(const StringView& data)
|
||||
void MacWindow::SetCursor(CursorType type)
|
||||
{
|
||||
WindowBase::SetCursor(type);
|
||||
if (!_isMouseOver)
|
||||
return;
|
||||
//if (!_isMouseOver)
|
||||
// return;
|
||||
NSCursor* cursor = nullptr;
|
||||
switch (type)
|
||||
{
|
||||
@@ -875,6 +875,7 @@ void MacWindow::SetCursor(CursorType type)
|
||||
if (cursor)
|
||||
{
|
||||
[cursor set];
|
||||
[NSCursor unhide];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,11 @@ public:
|
||||
static void MemoryBarrier();
|
||||
static int64 InterlockedExchange(int64 volatile* dst, int64 exchange)
|
||||
{
|
||||
#if WIN64
|
||||
return _InterlockedExchange64(dst, exchange);
|
||||
#else
|
||||
return _interlockedexchange64(dst, exchange);
|
||||
#endif
|
||||
}
|
||||
static int32 InterlockedCompareExchange(int32 volatile* dst, int32 exchange, int32 comperand)
|
||||
{
|
||||
@@ -37,15 +41,27 @@ public:
|
||||
}
|
||||
static int64 InterlockedIncrement(int64 volatile* dst)
|
||||
{
|
||||
#if WIN64
|
||||
return _InterlockedExchangeAdd64(dst, 1) + 1;
|
||||
#else
|
||||
return _interlockedexchange64(dst, 1) + 1;
|
||||
#endif
|
||||
}
|
||||
static int64 InterlockedDecrement(int64 volatile* dst)
|
||||
{
|
||||
#if WIN64
|
||||
return _InterlockedExchangeAdd64(dst, -1) - 1;
|
||||
#else
|
||||
return _interlockedexchangeadd64(dst, -1) - 1;
|
||||
#endif
|
||||
}
|
||||
static int64 InterlockedAdd(int64 volatile* dst, int64 value)
|
||||
{
|
||||
#if WIN64
|
||||
return _InterlockedExchangeAdd64(dst, value);
|
||||
#else
|
||||
return _interlockedexchangeadd64(dst, value);
|
||||
#endif
|
||||
}
|
||||
static int32 AtomicRead(int32 volatile* dst)
|
||||
{
|
||||
@@ -61,7 +77,11 @@ public:
|
||||
}
|
||||
static void AtomicStore(int64 volatile* dst, int64 value)
|
||||
{
|
||||
#if WIN64
|
||||
_InterlockedExchange64(dst, value);
|
||||
#else
|
||||
_interlockedexchange64(dst, value);
|
||||
#endif
|
||||
}
|
||||
static void Prefetch(void const* ptr);
|
||||
static void* Allocate(uint64 size, uint64 alignment);
|
||||
|
||||
@@ -18,7 +18,7 @@ class FLAXENGINE_API ScriptingEvents
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Global table for registered even binder methods (key is pair of type and event name, value is method that takes instance with event, object to bind and flag to bind or unbind).
|
||||
/// Global table for registered event binder methods (key is pair of type and event name, value is method that takes instance with event, object to bind and flag to bind or unbind).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Key: pair of event type, event name.
|
||||
|
||||
@@ -24,6 +24,7 @@ public:
|
||||
Delegate<> Changed;
|
||||
|
||||
public:
|
||||
NON_COPYABLE(SoftObjectReferenceBase);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SoftObjectReferenceBase"/> class.
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "Engine/Core/Math/Matrix.h"
|
||||
#include "Engine/Scripting/ManagedSerialization.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MUtils.h"
|
||||
#include "Engine/Scripting/ScriptingObjectReference.h"
|
||||
#include "Engine/Content/Asset.h"
|
||||
#include "Engine/Utilities/Encryption.h"
|
||||
#if USE_MONO
|
||||
#include <ThirdParty/mono-2.0/mono/metadata/object.h>
|
||||
|
||||
@@ -5,14 +5,21 @@
|
||||
#include "SerializationFwd.h"
|
||||
#include "Engine/Core/Collections/Array.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Scripting/ScriptingObjectReference.h"
|
||||
#include "Engine/Scripting/SoftObjectReference.h"
|
||||
#include "Engine/Content/AssetReference.h"
|
||||
#include "Engine/Content/WeakAssetReference.h"
|
||||
#include "Engine/Scripting/ScriptingObject.h"
|
||||
#include "Engine/Utilities/Encryption.h"
|
||||
|
||||
struct Version;
|
||||
struct VariantType;
|
||||
template<typename T>
|
||||
class ScriptingObjectReference;
|
||||
template<typename T>
|
||||
class SoftObjectReference;
|
||||
template<typename T>
|
||||
class AssetReference;
|
||||
template<typename T>
|
||||
class WeakAssetReference;
|
||||
template<typename T>
|
||||
class SoftAssetReference;
|
||||
|
||||
// @formatter:off
|
||||
|
||||
@@ -513,6 +520,26 @@ namespace Serialization
|
||||
v = id;
|
||||
}
|
||||
|
||||
// Soft Asset Reference
|
||||
|
||||
template<typename T>
|
||||
inline bool ShouldSerialize(const SoftAssetReference<T>& v, const void* otherObj)
|
||||
{
|
||||
return !otherObj || v.Get() != ((SoftAssetReference<T>*)otherObj)->Get();
|
||||
}
|
||||
template<typename T>
|
||||
inline void Serialize(ISerializable::SerializeStream& stream, const SoftAssetReference<T>& v, const void* otherObj)
|
||||
{
|
||||
stream.Guid(v.GetID());
|
||||
}
|
||||
template<typename T>
|
||||
inline void Deserialize(ISerializable::DeserializeStream& stream, SoftAssetReference<T>& v, ISerializeModifier* modifier)
|
||||
{
|
||||
Guid id;
|
||||
Deserialize(stream, id, modifier);
|
||||
v = id;
|
||||
}
|
||||
|
||||
// Array
|
||||
|
||||
template<typename T, typename AllocationType = HeapAllocation>
|
||||
|
||||
@@ -519,14 +519,12 @@ void ReadStream::ReadJson(ISerializable* obj)
|
||||
|
||||
void WriteStream::WriteText(const StringView& text)
|
||||
{
|
||||
for (int32 i = 0; i < text.Length(); i++)
|
||||
WriteChar(text[i]);
|
||||
WriteBytes(text.Get(), sizeof(Char) * text.Length());
|
||||
}
|
||||
|
||||
void WriteStream::WriteText(const StringAnsiView& text)
|
||||
{
|
||||
for (int32 i = 0; i < text.Length(); i++)
|
||||
WriteChar(text[i]);
|
||||
WriteBytes(text.Get(), sizeof(char) * text.Length());
|
||||
}
|
||||
|
||||
void WriteStream::WriteString(const StringView& data)
|
||||
|
||||
@@ -423,7 +423,7 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context)
|
||||
#endif
|
||||
|
||||
// Report progress
|
||||
float hemispheresProgress = static_cast<float>(_workerStagePosition1) / lightmapEntry.Hemispheres.Count();
|
||||
float hemispheresProgress = static_cast<float>(_workerStagePosition1) / Math::Max(lightmapEntry.Hemispheres.Count(), 1);
|
||||
float lightmapsProgress = static_cast<float>(_workerStagePosition0 + hemispheresProgress) / scene->Lightmaps.Count();
|
||||
float bouncesProgress = static_cast<float>(_giBounceRunningIndex) / _bounceCount;
|
||||
reportProgress(BuildProgressStep::RenderHemispheres, lightmapsProgress / _bounceCount + bouncesProgress);
|
||||
|
||||
@@ -42,6 +42,7 @@ void ModelTool::Options::Serialize(SerializeStream& stream, const void* otherObj
|
||||
SERIALIZE(ImportVertexColors);
|
||||
SERIALIZE(ImportBlendShapes);
|
||||
SERIALIZE(LightmapUVsSource);
|
||||
SERIALIZE(CollisionMeshesPrefix);
|
||||
SERIALIZE(Scale);
|
||||
SERIALIZE(Rotation);
|
||||
SERIALIZE(Translation);
|
||||
@@ -79,6 +80,7 @@ void ModelTool::Options::Deserialize(DeserializeStream& stream, ISerializeModifi
|
||||
DESERIALIZE(ImportVertexColors);
|
||||
DESERIALIZE(ImportBlendShapes);
|
||||
DESERIALIZE(LightmapUVsSource);
|
||||
DESERIALIZE(CollisionMeshesPrefix);
|
||||
DESERIALIZE(Scale);
|
||||
DESERIALIZE(Rotation);
|
||||
DESERIALIZE(Translation);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "Engine/Tools/TextureTool/TextureTool.h"
|
||||
#include "Engine/ContentImporters/AssetsImportingManager.h"
|
||||
#include "Engine/ContentImporters/CreateMaterial.h"
|
||||
#include "Engine/ContentImporters/CreateCollisionData.h"
|
||||
#include "Editor/Utilities/EditorUtilities.h"
|
||||
#include <ThirdParty/meshoptimizer/meshoptimizer.h>
|
||||
|
||||
@@ -562,7 +563,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
|
||||
materialOptions.Opacity.Texture = data.Textures[material.Opacity.TextureIndex].AssetID;
|
||||
if (material.Normals.TextureIndex != -1)
|
||||
materialOptions.Normals.Texture = data.Textures[material.Normals.TextureIndex].AssetID;
|
||||
if (material.TwoSided | material.Diffuse.HasAlphaMask)
|
||||
if (material.TwoSided || material.Diffuse.HasAlphaMask)
|
||||
materialOptions.Info.CullMode = CullMode::TwoSided;
|
||||
if (!Math::IsOne(material.Opacity.Value) || material.Opacity.TextureIndex != -1)
|
||||
materialOptions.Info.BlendMode = MaterialBlendMode::Transparent;
|
||||
@@ -624,6 +625,41 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
|
||||
}
|
||||
}
|
||||
|
||||
// Collision mesh output
|
||||
if (options.CollisionMeshesPrefix.HasChars())
|
||||
{
|
||||
// Extract collision meshes
|
||||
ModelData collisionModel;
|
||||
for (auto& lod : data.LODs)
|
||||
{
|
||||
for (int32 i = lod.Meshes.Count() - 1; i >= 0; i--)
|
||||
{
|
||||
auto mesh = lod.Meshes[i];
|
||||
if (mesh->Name.StartsWith(options.CollisionMeshesPrefix, StringSearchCase::IgnoreCase))
|
||||
{
|
||||
if (collisionModel.LODs.Count() == 0)
|
||||
collisionModel.LODs.AddOne();
|
||||
collisionModel.LODs[0].Meshes.Add(mesh);
|
||||
lod.Meshes.RemoveAtKeepOrder(i);
|
||||
if (lod.Meshes.IsEmpty())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (collisionModel.LODs.HasItems())
|
||||
{
|
||||
// Create collision
|
||||
CollisionCooking::Argument arg;
|
||||
arg.Type = CollisionDataType::TriangleMesh;
|
||||
arg.OverrideModelData = &collisionModel;
|
||||
auto assetPath = autoImportOutput / StringUtils::GetFileNameWithoutExtension(path) + TEXT("Collision") ASSET_FILES_EXTENSION_WITH_DOT;
|
||||
if (CreateCollisionData::CookMeshCollision(assetPath, arg))
|
||||
{
|
||||
LOG(Error, "Failed to create collision mesh.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For generated lightmap UVs coordinates needs to be moved so all meshes are in unique locations in [0-1]x[0-1] coordinates space
|
||||
if (options.LightmapUVsSource == ModelLightmapUVsSource::Generate && data.LODs.HasItems() && data.LODs[0].Meshes.Count() > 1)
|
||||
{
|
||||
|
||||
@@ -177,6 +177,7 @@ public:
|
||||
bool ImportVertexColors = true;
|
||||
bool ImportBlendShapes = false;
|
||||
ModelLightmapUVsSource LightmapUVsSource = ModelLightmapUVsSource::Disable;
|
||||
String CollisionMeshesPrefix;
|
||||
|
||||
// Transform
|
||||
float Scale = 1.0f;
|
||||
|
||||
1
Source/ThirdParty/fmt/core.h
vendored
1
Source/ThirdParty/fmt/core.h
vendored
@@ -18,6 +18,7 @@
|
||||
#define FMT_USE_WINDOWS_H 0
|
||||
//#define FMT_USE_STRING_VIEW 1
|
||||
#define FMT_USE_STRING 0
|
||||
#define FMT_USE_LONG_DOUBLE 0
|
||||
#define FMT_USE_ITERATOR 0
|
||||
#define FMT_USE_LOCALE_GROUPING 0
|
||||
#define FMT_EXCEPTIONS 0
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Flax.Build.Bindings
|
||||
internal static readonly Dictionary<string, string> CSharpNativeToManagedBasicTypes = new Dictionary<string, string>()
|
||||
{
|
||||
// Language types
|
||||
{ "bool", "bool" },
|
||||
{ "int8", "sbyte" },
|
||||
{ "int16", "short" },
|
||||
{ "int32", "int" },
|
||||
@@ -233,8 +234,12 @@ namespace Flax.Build.Bindings
|
||||
return result;
|
||||
}
|
||||
|
||||
// ScriptingObjectReference or AssetReference or WeakAssetReference or SoftObjectReference
|
||||
if ((typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference" || typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
|
||||
// Object reference property
|
||||
if ((typeInfo.Type == "ScriptingObjectReference" ||
|
||||
typeInfo.Type == "AssetReference" ||
|
||||
typeInfo.Type == "WeakAssetReference" ||
|
||||
typeInfo.Type == "SoftAssetReference" ||
|
||||
typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
|
||||
return GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller);
|
||||
|
||||
// Array or Span
|
||||
@@ -310,8 +315,12 @@ namespace Flax.Build.Bindings
|
||||
return "IntPtr";
|
||||
}
|
||||
|
||||
// ScriptingObjectReference or AssetReference or WeakAssetReference or SoftObjectReference
|
||||
if ((typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference" || typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
|
||||
// Object reference property
|
||||
if ((typeInfo.Type == "ScriptingObjectReference" ||
|
||||
typeInfo.Type == "AssetReference" ||
|
||||
typeInfo.Type == "WeakAssetReference" ||
|
||||
typeInfo.Type == "SoftAssetReference" ||
|
||||
typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
|
||||
return "IntPtr";
|
||||
|
||||
// Function
|
||||
@@ -364,8 +373,12 @@ namespace Flax.Build.Bindings
|
||||
return string.Format("FlaxEngine.Object.GetUnmanagedInterface({{0}}, typeof({0}))", apiType.FullNameManaged);
|
||||
}
|
||||
|
||||
// ScriptingObjectReference or AssetReference or WeakAssetReference or SoftObjectReference
|
||||
if ((typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference" || typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
|
||||
// Object reference property
|
||||
if ((typeInfo.Type == "ScriptingObjectReference" ||
|
||||
typeInfo.Type == "AssetReference" ||
|
||||
typeInfo.Type == "WeakAssetReference" ||
|
||||
typeInfo.Type == "SoftAssetReference" ||
|
||||
typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
|
||||
return "FlaxEngine.Object.GetUnmanagedPtr({0})";
|
||||
|
||||
// Default
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Flax.Build.Bindings
|
||||
partial class BindingsGenerator
|
||||
{
|
||||
private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
|
||||
private const int CacheVersion = 11;
|
||||
private const int CacheVersion = 12;
|
||||
|
||||
internal static void Write(BinaryWriter writer, string e)
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Flax.Build.Bindings
|
||||
private static readonly string[] CppParamsThatNeedConversionWrappers = new string[64];
|
||||
private static readonly string[] CppParamsThatNeedConversionTypes = new string[64];
|
||||
private static readonly string[] CppParamsWrappersCache = new string[64];
|
||||
public static readonly List<KeyValuePair<string, string>> CppInternalCalls = new List<KeyValuePair<string, string>>();
|
||||
public static readonly List<ApiTypeInfo> CppUsedNonPodTypes = new List<ApiTypeInfo>();
|
||||
private static readonly List<ApiTypeInfo> CppUsedNonPodTypesList = new List<ApiTypeInfo>();
|
||||
public static readonly HashSet<FileInfo> CppReferencesFiles = new HashSet<FileInfo>();
|
||||
@@ -130,7 +131,11 @@ namespace Flax.Build.Bindings
|
||||
return value;
|
||||
if (typeInfo.Type == "String")
|
||||
return $"Variant(StringView({value}))";
|
||||
if (typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference" || typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "SoftObjectReference")
|
||||
if (typeInfo.Type == "AssetReference" ||
|
||||
typeInfo.Type == "WeakAssetReference" ||
|
||||
typeInfo.Type == "SoftAssetReference" ||
|
||||
typeInfo.Type == "ScriptingObjectReference" ||
|
||||
typeInfo.Type == "SoftObjectReference")
|
||||
return $"Variant({value}.Get())";
|
||||
if (typeInfo.IsArray)
|
||||
{
|
||||
@@ -177,7 +182,7 @@ namespace Flax.Build.Bindings
|
||||
return $"(StringView){value}";
|
||||
if (typeInfo.IsPtr && typeInfo.IsConst && typeInfo.Type == "Char")
|
||||
return $"((StringView){value}).GetNonTerminatedText()"; // (StringView)Variant, if not empty, is guaranteed to point to a null-terminated buffer.
|
||||
if (typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference")
|
||||
if (typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference" || typeInfo.Type == "SoftAssetReference")
|
||||
return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((Asset*){value})";
|
||||
if (typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "SoftObjectReference")
|
||||
return $"ScriptingObject::Cast<{typeInfo.GenericArgs[0].Type}>((ScriptingObject*){value})";
|
||||
@@ -400,8 +405,12 @@ namespace Flax.Build.Bindings
|
||||
type = "void*";
|
||||
return "MUtils::ToManaged({0})";
|
||||
default:
|
||||
// ScriptingObjectReference or AssetReference or WeakAssetReference or SoftObjectReference
|
||||
if ((typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference" || typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
|
||||
// Object reference property
|
||||
if ((typeInfo.Type == "ScriptingObjectReference" ||
|
||||
typeInfo.Type == "AssetReference" ||
|
||||
typeInfo.Type == "WeakAssetReference" ||
|
||||
typeInfo.Type == "SoftAssetReference" ||
|
||||
typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
|
||||
{
|
||||
type = "MonoObject*";
|
||||
return "{0}.GetManagedInstance()";
|
||||
@@ -568,8 +577,12 @@ namespace Flax.Build.Bindings
|
||||
type = "void*";
|
||||
return "MUtils::ToNative({0})";
|
||||
default:
|
||||
// ScriptingObjectReference or AssetReference or WeakAssetReference or SoftObjectReference
|
||||
if ((typeInfo.Type == "ScriptingObjectReference" || typeInfo.Type == "AssetReference" || typeInfo.Type == "WeakAssetReference" || typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
|
||||
// Object reference property
|
||||
if ((typeInfo.Type == "ScriptingObjectReference" ||
|
||||
typeInfo.Type == "AssetReference" ||
|
||||
typeInfo.Type == "WeakAssetReference" ||
|
||||
typeInfo.Type == "SoftAssetReference" ||
|
||||
typeInfo.Type == "SoftObjectReference") && typeInfo.GenericArgs != null)
|
||||
{
|
||||
// For non-pod types converting only, other API converts managed to unmanaged object in C# wrapper code)
|
||||
if (CppNonPodTypesConvertingGeneration)
|
||||
@@ -771,8 +784,53 @@ namespace Flax.Build.Bindings
|
||||
return $"MUtils::Box<{nativeType}>({value}, {GenerateCppGetNativeClass(buildData, typeInfo, caller, null)})";
|
||||
}
|
||||
|
||||
private static bool GenerateCppWrapperFunctionImplicitBinding(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller)
|
||||
{
|
||||
if (typeInfo.IsVoid)
|
||||
return true;
|
||||
if (typeInfo.IsPtr || typeInfo.IsRef || typeInfo.IsArray || typeInfo.IsBitField || (typeInfo.GenericArgs != null && typeInfo.GenericArgs.Count != 0))
|
||||
return false;
|
||||
if (CSharpNativeToManagedBasicTypes.ContainsKey(typeInfo.Type) || CSharpNativeToManagedBasicTypes.ContainsValue(typeInfo.Type))
|
||||
return true;
|
||||
var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
|
||||
if (apiType != null)
|
||||
{
|
||||
if (apiType.IsEnum)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool GenerateCppWrapperFunctionImplicitBinding(BuildData buildData, FunctionInfo functionInfo, ApiTypeInfo caller)
|
||||
{
|
||||
if (!functionInfo.IsStatic || functionInfo.Access != AccessLevel.Public || (functionInfo.Glue.CustomParameters != null && functionInfo.Glue.CustomParameters.Count != 0))
|
||||
return false;
|
||||
if (!GenerateCppWrapperFunctionImplicitBinding(buildData, functionInfo.ReturnType, caller))
|
||||
return false;
|
||||
for (int i = 0; i < functionInfo.Parameters.Count; i++)
|
||||
{
|
||||
var parameterInfo = functionInfo.Parameters[i];
|
||||
if (parameterInfo.IsOut || parameterInfo.IsRef || !GenerateCppWrapperFunctionImplicitBinding(buildData, parameterInfo.Type, caller))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void GenerateCppWrapperFunction(BuildData buildData, StringBuilder contents, ApiTypeInfo caller, FunctionInfo functionInfo, string callFormat = "{0}({1})")
|
||||
{
|
||||
// Optimize static function wrappers that match C# internal call ABI exactly
|
||||
// Use it for Engine-internally only because in games this makes it problematic to use the same function name but with different signature that is not visible to scripting
|
||||
if (CurrentModule.Module is EngineModule && callFormat == "{0}({1})" && GenerateCppWrapperFunctionImplicitBinding(buildData, functionInfo, caller))
|
||||
{
|
||||
// Ensure the function name is unique within a class/structure
|
||||
if (caller is ClassStructInfo classStructInfo && classStructInfo.Functions.All(f => f.Name != functionInfo.Name || f == functionInfo))
|
||||
{
|
||||
// Use native method binding directly (no generated wrapper)
|
||||
CppInternalCalls.Add(new KeyValuePair<string, string>(functionInfo.UniqueName, classStructInfo.Name + "::" + functionInfo.Name));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Setup function binding glue to ensure that wrapper method signature matches for C++ and C#
|
||||
functionInfo.Glue = new FunctionInfo.GlueInfo
|
||||
{
|
||||
@@ -797,6 +855,7 @@ namespace Flax.Build.Bindings
|
||||
});
|
||||
}
|
||||
|
||||
CppInternalCalls.Add(new KeyValuePair<string, string>(functionInfo.UniqueName, functionInfo.UniqueName));
|
||||
contents.AppendFormat(" static {0} {1}(", returnValueType, functionInfo.UniqueName);
|
||||
|
||||
var separator = false;
|
||||
@@ -1453,6 +1512,7 @@ namespace Flax.Build.Bindings
|
||||
var useScripting = classInfo.IsStatic || classInfo.IsScriptingObject;
|
||||
var useCSharp = EngineConfiguration.WithCSharp(buildData.TargetOptions);
|
||||
var hasInterface = classInfo.Interfaces != null && classInfo.Interfaces.Any(x => x.Access == AccessLevel.Public);
|
||||
CppInternalCalls.Clear();
|
||||
|
||||
if (classInfo.IsAutoSerialization)
|
||||
GenerateCppAutoSerialization(buildData, contents, moduleInfo, classInfo, classTypeNameNative);
|
||||
@@ -1520,7 +1580,7 @@ namespace Flax.Build.Bindings
|
||||
{
|
||||
// Convert value back from managed to native (could be modified there)
|
||||
paramType.IsRef = false;
|
||||
var managedToNative = GenerateCppWrapperManagedToNative(buildData, paramType, classInfo, out var managedType, null, out var _);
|
||||
var managedToNative = GenerateCppWrapperManagedToNative(buildData, paramType, classInfo, out var managedType, null, out _);
|
||||
var passAsParamPtr = managedType.EndsWith("*");
|
||||
var paramValue = $"({managedType}{(passAsParamPtr ? "" : "*")})params[{i}]";
|
||||
if (!string.IsNullOrEmpty(managedToNative))
|
||||
@@ -1538,6 +1598,7 @@ namespace Flax.Build.Bindings
|
||||
contents.Append(" }").AppendLine().AppendLine();
|
||||
|
||||
// C# event wrapper binding method (binds/unbinds C# wrapper to C++ delegate)
|
||||
CppInternalCalls.Add(new KeyValuePair<string, string>(eventInfo.Name + "_Bind", eventInfo.Name + "_ManagedBind"));
|
||||
contents.AppendFormat(" static void {0}_ManagedBind(", eventInfo.Name);
|
||||
if (!eventInfo.IsStatic)
|
||||
contents.AppendFormat("{0}* obj, ", classTypeNameNative);
|
||||
@@ -1685,47 +1746,9 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
if (useScripting && useCSharp)
|
||||
{
|
||||
foreach (var eventInfo in classInfo.Events)
|
||||
foreach (var e in CppInternalCalls)
|
||||
{
|
||||
if (eventInfo.IsHidden)
|
||||
continue;
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{eventInfo.Name}_Bind\", &{eventInfo.Name}_ManagedBind);");
|
||||
}
|
||||
foreach (var fieldInfo in classInfo.Fields)
|
||||
{
|
||||
if (fieldInfo.IsHidden)
|
||||
continue;
|
||||
if (fieldInfo.Getter != null)
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{fieldInfo.Getter.UniqueName}\", &{fieldInfo.Getter.UniqueName});");
|
||||
if (fieldInfo.Setter != null)
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{fieldInfo.Setter.UniqueName}\", &{fieldInfo.Setter.UniqueName});");
|
||||
}
|
||||
foreach (var propertyInfo in classInfo.Properties)
|
||||
{
|
||||
if (propertyInfo.IsHidden)
|
||||
continue;
|
||||
if (propertyInfo.Getter != null)
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{propertyInfo.Getter.UniqueName}\", &{propertyInfo.Getter.UniqueName});");
|
||||
if (propertyInfo.Setter != null)
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{propertyInfo.Setter.UniqueName}\", &{propertyInfo.Setter.UniqueName});");
|
||||
}
|
||||
foreach (var functionInfo in classInfo.Functions)
|
||||
{
|
||||
if (functionInfo.IsHidden)
|
||||
continue;
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{functionInfo.UniqueName}\", &{functionInfo.UniqueName});");
|
||||
}
|
||||
if (hasInterface)
|
||||
{
|
||||
foreach (var interfaceInfo in classInfo.Interfaces)
|
||||
{
|
||||
if (interfaceInfo.Access != AccessLevel.Public)
|
||||
continue;
|
||||
foreach (var functionInfo in interfaceInfo.Functions)
|
||||
{
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{functionInfo.UniqueName}\", &{functionInfo.UniqueName});");
|
||||
}
|
||||
}
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{classTypeNameManagedInternalCall}::Internal_{e.Key}\", &{e.Value});");
|
||||
}
|
||||
}
|
||||
GenerateCppClassInitRuntime?.Invoke(buildData, classInfo, contents);
|
||||
@@ -1801,6 +1824,7 @@ namespace Flax.Build.Bindings
|
||||
if (structureInfo.Parent != null && !(structureInfo.Parent is FileInfo))
|
||||
structureTypeNameInternal = structureInfo.Parent.FullNameNative + '_' + structureTypeNameInternal;
|
||||
var useCSharp = EngineConfiguration.WithCSharp(buildData.TargetOptions);
|
||||
CppInternalCalls.Clear();
|
||||
|
||||
if (structureInfo.IsAutoSerialization)
|
||||
GenerateCppAutoSerialization(buildData, contents, moduleInfo, structureInfo, structureTypeNameNative);
|
||||
@@ -1869,12 +1893,9 @@ namespace Flax.Build.Bindings
|
||||
|
||||
if (useCSharp)
|
||||
{
|
||||
foreach (var fieldInfo in structureInfo.Fields)
|
||||
foreach (var e in CppInternalCalls)
|
||||
{
|
||||
if (fieldInfo.Getter != null)
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{structureTypeNameManagedInternalCall}::Internal_{fieldInfo.Getter.UniqueName}\", &{fieldInfo.Getter.UniqueName});");
|
||||
if (fieldInfo.Setter != null)
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{structureTypeNameManagedInternalCall}::Internal_{fieldInfo.Setter.UniqueName}\", &{fieldInfo.Setter.UniqueName});");
|
||||
contents.AppendLine($" ADD_INTERNAL_CALL(\"{structureTypeNameManagedInternalCall}::Internal_{e.Key}\", &{e.Value});");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2189,6 +2210,7 @@ namespace Flax.Build.Bindings
|
||||
CppIncludeFilesList.Clear();
|
||||
CppVariantToTypes.Clear();
|
||||
CppVariantFromTypes.Clear();
|
||||
CurrentModule = moduleInfo;
|
||||
|
||||
// Disable C# scripting based on configuration
|
||||
ScriptingLangInfos[0].Enabled = EngineConfiguration.WithCSharp(buildData.TargetOptions);
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace Flax.Build.Bindings
|
||||
|
||||
public static event GenerateModuleBindingsDelegate GenerateModuleBindings;
|
||||
public static event GenerateBinaryModuleBindingsDelegate GenerateBinaryModuleBindings;
|
||||
public static ModuleInfo CurrentModule;
|
||||
|
||||
public static ModuleInfo ParseModule(BuildData buildData, Module module, BuildOptions moduleOptions = null)
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Flax.Build.Bindings
|
||||
public ClassStructInfo BaseType;
|
||||
public List<InterfaceInfo> Interfaces;
|
||||
public List<TypeInfo> Inheritance; // Data from parsing, used to interfaces and base type construct in Init
|
||||
public List<FunctionInfo> Functions = new List<FunctionInfo>();
|
||||
|
||||
public override void Init(Builder.BuildData buildData)
|
||||
{
|
||||
@@ -52,6 +53,7 @@ namespace Flax.Build.Bindings
|
||||
writer.Write((byte)BaseTypeInheritance);
|
||||
BindingsGenerator.Write(writer, BaseType);
|
||||
BindingsGenerator.Write(writer, Inheritance);
|
||||
BindingsGenerator.Write(writer, Functions);
|
||||
|
||||
base.Write(writer);
|
||||
}
|
||||
@@ -62,6 +64,7 @@ namespace Flax.Build.Bindings
|
||||
BaseTypeInheritance = (AccessLevel)reader.ReadByte();
|
||||
BaseType = BindingsGenerator.Read(reader, BaseType);
|
||||
Inheritance = BindingsGenerator.Read(reader, Inheritance);
|
||||
Functions = BindingsGenerator.Read(reader, Functions);
|
||||
|
||||
base.Read(reader);
|
||||
}
|
||||
@@ -72,8 +75,6 @@ namespace Flax.Build.Bindings
|
||||
/// </summary>
|
||||
public abstract class VirtualClassInfo : ClassStructInfo
|
||||
{
|
||||
public List<FunctionInfo> Functions = new List<FunctionInfo>();
|
||||
|
||||
internal HashSet<string> UniqueFunctionNames;
|
||||
|
||||
public override void Init(Builder.BuildData buildData)
|
||||
@@ -100,20 +101,6 @@ namespace Flax.Build.Bindings
|
||||
|
||||
public abstract int GetScriptVTableOffset(VirtualClassInfo classInfo);
|
||||
|
||||
public override void Write(BinaryWriter writer)
|
||||
{
|
||||
BindingsGenerator.Write(writer, Functions);
|
||||
|
||||
base.Write(writer);
|
||||
}
|
||||
|
||||
public override void Read(BinaryReader reader)
|
||||
{
|
||||
Functions = BindingsGenerator.Read(reader, Functions);
|
||||
|
||||
base.Read(reader);
|
||||
}
|
||||
|
||||
public override void AddChild(ApiTypeInfo apiTypeInfo)
|
||||
{
|
||||
apiTypeInfo.Namespace = null;
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace Flax.Build.Bindings
|
||||
public class StructureInfo : ClassStructInfo
|
||||
{
|
||||
public List<FieldInfo> Fields = new List<FieldInfo>();
|
||||
public List<FunctionInfo> Functions = new List<FunctionInfo>();
|
||||
public bool IsAutoSerialization;
|
||||
public bool ForceNoPod;
|
||||
|
||||
|
||||
@@ -271,6 +271,7 @@ namespace Flax.Build.Platforms
|
||||
|
||||
// Input libraries
|
||||
var libraryPaths = new HashSet<string>();
|
||||
var dylibs = new HashSet<string>();
|
||||
foreach (var library in linkEnvironment.InputLibraries)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(library);
|
||||
@@ -290,6 +291,7 @@ namespace Flax.Build.Platforms
|
||||
else if (ext == ".dylib")
|
||||
{
|
||||
// Link against dynamic library
|
||||
dylibs.Add(library);
|
||||
task.PrerequisiteFiles.Add(library);
|
||||
libraryPaths.Add(dir);
|
||||
args.Add(string.Format("\"{0}\"", library));
|
||||
@@ -319,6 +321,7 @@ namespace Flax.Build.Platforms
|
||||
else if (ext == ".dylib")
|
||||
{
|
||||
// Link against dynamic library
|
||||
dylibs.Add(library);
|
||||
task.PrerequisiteFiles.Add(library);
|
||||
libraryPaths.Add(dir);
|
||||
args.Add(string.Format("\"{0}\"", library));
|
||||
@@ -370,6 +373,27 @@ namespace Flax.Build.Platforms
|
||||
task.Cost = task.PrerequisiteFiles.Count;
|
||||
task.ProducedFiles.Add(outputFilePath);
|
||||
|
||||
Task lastTask = task;
|
||||
if (options.LinkEnv.Output == LinkerOutput.Executable)
|
||||
{
|
||||
// Fix rpath for dynamic libraries
|
||||
foreach (var library in dylibs)
|
||||
{
|
||||
var rpathTask = graph.Add<Task>();
|
||||
rpathTask.ProducedFiles.Add(outputFilePath);
|
||||
rpathTask.WorkingDirectory = options.WorkingDirectory;
|
||||
rpathTask.CommandPath = "install_name_tool";
|
||||
var filename = Path.GetFileName(library);
|
||||
var outputFolder = Path.GetDirectoryName(outputFilePath);
|
||||
rpathTask.CommandArguments = string.Format("-change \"{0}/{1}\" \"@loader_path/{1}\" {2}", outputFolder, filename, outputFilePath);
|
||||
rpathTask.InfoMessage = "Fixing rpath to " + filename;
|
||||
rpathTask.Cost = 1;
|
||||
rpathTask.DisableCache = true;
|
||||
rpathTask.DependentTasks = new HashSet<Task>();
|
||||
rpathTask.DependentTasks.Add(lastTask);
|
||||
lastTask = rpathTask;
|
||||
}
|
||||
}
|
||||
if (!options.LinkEnv.DebugInformation)
|
||||
{
|
||||
// Strip debug symbols
|
||||
@@ -382,7 +406,7 @@ namespace Flax.Build.Platforms
|
||||
stripTask.Cost = 1;
|
||||
stripTask.DisableCache = true;
|
||||
stripTask.DependentTasks = new HashSet<Task>();
|
||||
stripTask.DependentTasks.Add(task);
|
||||
stripTask.DependentTasks.Add(lastTask);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user