Merge remote-tracking branch 'origin/master'
This commit is contained in:
100
.github/workflows/cd.yml
vendored
Normal file
100
.github/workflows/cd.yml
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
name: Continuous Deployment
|
||||
on:
|
||||
schedule:
|
||||
- cron: '15 4 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
# Windows
|
||||
package-windows-editor:
|
||||
name: Editor (Windows)
|
||||
runs-on: "windows-latest"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
.\PackageEditor.bat -arch=x64 -platform=Windows -deployOutput=Output
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Windows-Editor
|
||||
path: Output/Editor.zip
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Windows-EditorDebugSymbols
|
||||
path: Output/EditorDebugSymbols.zip
|
||||
package-windows-game:
|
||||
name: Game (Windows)
|
||||
runs-on: "windows-latest"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
.\PackagePlatforms.bat -arch=x64 -platform=Windows -deployOutput=Output
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Windows-Game
|
||||
path: Output/Windows.zip
|
||||
|
||||
# Linux
|
||||
package-linux-editor:
|
||||
name: Editor (Linux)
|
||||
runs-on: "ubuntu-20.04"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo rm -f /etc/apt/sources.list.d/*
|
||||
sudo cp -f .github/workflows/build_linux_sources.list /etc/apt/sources.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||
- name: Build
|
||||
run: |
|
||||
./PackageEditor.sh -arch=x64 -platform=Linux -deployOutput=Output
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Linux-Editor
|
||||
path: Output/FlaxEditorLinux.zip
|
||||
package-linux-game:
|
||||
name: Game (Linux)
|
||||
runs-on: "ubuntu-20.04"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Checkout LFS
|
||||
run: |
|
||||
git lfs version
|
||||
git lfs pull
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo rm -f /etc/apt/sources.list.d/*
|
||||
sudo cp -f .github/workflows/build_linux_sources.list /etc/apt/sources.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||
- name: Build
|
||||
run: |
|
||||
./PackagePlatforms.sh -arch=x64 -platform=Linux -deployOutput=Output
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Linux-Game
|
||||
path: Output/Linux.zip
|
||||
@@ -108,6 +108,26 @@ namespace FlaxEditor.Content
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when user dags this item into editor viewport or scene tree node.
|
||||
/// </summary>
|
||||
/// <param name="context">The editor context (eg. editor viewport or scene tree node).</param>
|
||||
/// <returns>True if item can be dropped in, otherwise false.</returns>
|
||||
public virtual bool OnEditorDrag(object context)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when user drops the item into editor viewport or scene tree node.
|
||||
/// </summary>
|
||||
/// <param name="context">The editor context (eg. editor viewport or scene tree node).</param>
|
||||
/// <returns>The spawned object.</returns>
|
||||
public virtual Actor OnEditorDrop(object context)
|
||||
{
|
||||
throw new NotSupportedException($"Asset {GetType()} doesn't support dropping into viewport.");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool DrawShadow => true;
|
||||
|
||||
|
||||
@@ -103,14 +103,26 @@ namespace FlaxEditor.Content
|
||||
/// Implementation of <see cref="BinaryAssetItem"/> for <see cref="Model"/> assets.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetItem" />
|
||||
public class ModelAssetItem : BinaryAssetItem
|
||||
public class ModelItem : BinaryAssetItem
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ModelAssetItem(string path, ref Guid id, string typeName, Type type)
|
||||
public ModelItem(string path, ref Guid id, string typeName, Type type)
|
||||
: base(path, ref id, typeName, type, ContentItemSearchFilter.Model)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnEditorDrag(object context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Actor OnEditorDrop(object context)
|
||||
{
|
||||
return new StaticModel { Model = FlaxEngine.Content.LoadAsync<Model>(ID) };
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnBuildTooltipText(StringBuilder sb)
|
||||
{
|
||||
@@ -142,14 +154,26 @@ namespace FlaxEditor.Content
|
||||
/// Implementation of <see cref="BinaryAssetItem"/> for <see cref="SkinnedModel"/> assets.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetItem" />
|
||||
public class SkinnedModelAssetItem : BinaryAssetItem
|
||||
public class SkinnedModeItem : BinaryAssetItem
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public SkinnedModelAssetItem(string path, ref Guid id, string typeName, Type type)
|
||||
public SkinnedModeItem(string path, ref Guid id, string typeName, Type type)
|
||||
: base(path, ref id, typeName, type, ContentItemSearchFilter.Model)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnEditorDrag(object context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Actor OnEditorDrop(object context)
|
||||
{
|
||||
return new AnimatedModel { SkinnedModel = FlaxEngine.Content.LoadAsync<SkinnedModel>(ID) };
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnBuildTooltipText(StringBuilder sb)
|
||||
{
|
||||
|
||||
@@ -21,6 +21,18 @@ namespace FlaxEditor.Content
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnEditorDrag(object context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Actor OnEditorDrop(object context)
|
||||
{
|
||||
return PrefabManager.SpawnPrefab(FlaxEngine.Content.LoadAsync<Prefab>(ID), null);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ContentItemType ItemType => ContentItemType.Asset;
|
||||
|
||||
|
||||
@@ -538,6 +538,18 @@ namespace FlaxEditor.Content
|
||||
Editor.Instance.CodeEditing.ClearTypes();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnEditorDrag(object context)
|
||||
{
|
||||
return new ScriptType(typeof(Actor)).IsAssignableFrom(ScriptType) && ScriptType.CanCreateInstance;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Actor OnEditorDrop(object context)
|
||||
{
|
||||
return (Actor)ScriptType.CreateInstance();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override SpriteHandle DefaultThumbnail => Editor.Instance.Icons.VisualScript128;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using FlaxEditor.Content.Thumbnails;
|
||||
using FlaxEditor.Viewport.Previews;
|
||||
using FlaxEditor.Windows;
|
||||
@@ -11,11 +12,51 @@ using FlaxEngine.GUI;
|
||||
|
||||
namespace FlaxEditor.Content
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="BinaryAssetItem"/> for <see cref="AudioClip"/> assets.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetItem" />
|
||||
class AudioClipItem : BinaryAssetItem
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public AudioClipItem(string path, ref Guid id, string typeName, Type type)
|
||||
: base(path, ref id, typeName, type, ContentItemSearchFilter.Audio)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnEditorDrag(object context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Actor OnEditorDrop(object context)
|
||||
{
|
||||
return new AudioSource { Clip = FlaxEngine.Content.LoadAsync<AudioClip>(ID) };
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnBuildTooltipText(StringBuilder sb)
|
||||
{
|
||||
base.OnBuildTooltipText(sb);
|
||||
|
||||
var asset = FlaxEngine.Content.Load<AudioClip>(ID, 100);
|
||||
if (asset)
|
||||
{
|
||||
var info = asset.Info;
|
||||
sb.Append("Duration: ").Append(asset.Length).AppendLine();
|
||||
sb.Append("Channels: ").Append(info.NumChannels).AppendLine();
|
||||
sb.Append("Bit Depth: ").Append(info.BitDepth).AppendLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="AudioClip"/> asset proxy object.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||
public class AudioClipProxy : BinaryAssetProxy
|
||||
class AudioClipProxy : BinaryAssetProxy
|
||||
{
|
||||
private List<AudioClipPreview> _previews;
|
||||
|
||||
@@ -34,6 +75,12 @@ namespace FlaxEditor.Content
|
||||
return new AudioClipWindow(editor, (AssetItem)item);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
|
||||
{
|
||||
return new AudioClipItem(path, ref id, typeName, AssetType);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Color AccentColor => Color.FromRGB(0xB3452B);
|
||||
|
||||
|
||||
@@ -47,9 +47,9 @@ namespace FlaxEditor.Content
|
||||
if (typeof(TextureBase).IsAssignableFrom(type))
|
||||
return new TextureAssetItem(path, ref id, typeName, type);
|
||||
if (typeof(Model).IsAssignableFrom(type))
|
||||
return new ModelAssetItem(path, ref id, typeName, type);
|
||||
return new ModelItem(path, ref id, typeName, type);
|
||||
if (typeof(SkinnedModel).IsAssignableFrom(type))
|
||||
return new SkinnedModelAssetItem(path, ref id, typeName, type);
|
||||
return new SkinnedModeItem(path, ref id, typeName, type);
|
||||
|
||||
ContentItemSearchFilter searchFilter;
|
||||
if (typeof(MaterialBase).IsAssignableFrom(type))
|
||||
@@ -58,11 +58,9 @@ namespace FlaxEditor.Content
|
||||
searchFilter = ContentItemSearchFilter.Prefab;
|
||||
else if (typeof(SceneAsset).IsAssignableFrom(type))
|
||||
searchFilter = ContentItemSearchFilter.Scene;
|
||||
else if (typeof(AudioClip).IsAssignableFrom(type))
|
||||
searchFilter = ContentItemSearchFilter.Audio;
|
||||
else if (typeof(Animation).IsAssignableFrom(type))
|
||||
searchFilter = ContentItemSearchFilter.Animation;
|
||||
else if (typeof(ParticleEmitter).IsAssignableFrom(type) || typeof(ParticleSystem).IsAssignableFrom(type))
|
||||
else if (typeof(ParticleEmitter).IsAssignableFrom(type))
|
||||
searchFilter = ContentItemSearchFilter.Particles;
|
||||
else
|
||||
searchFilter = ContentItemSearchFilter.Other;
|
||||
|
||||
@@ -8,11 +8,36 @@ using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Content
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="BinaryAssetItem"/> for <see cref="CollisionData"/> assets.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetItem" />
|
||||
class CollisionDataItem : BinaryAssetItem
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public CollisionDataItem(string path, ref Guid id, string typeName, Type type)
|
||||
: base(path, ref id, typeName, type, ContentItemSearchFilter.Other)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnEditorDrag(object context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Actor OnEditorDrop(object context)
|
||||
{
|
||||
return new MeshCollider { CollisionData = FlaxEngine.Content.LoadAsync<CollisionData>(ID) };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="CollisionData"/> asset proxy object.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||
public class CollisionDataProxy : BinaryAssetProxy
|
||||
class CollisionDataProxy : BinaryAssetProxy
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Name => "Collision Data";
|
||||
@@ -23,6 +48,12 @@ namespace FlaxEditor.Content
|
||||
return new CollisionDataWindow(editor, item as AssetItem);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
|
||||
{
|
||||
return new CollisionDataItem(path, ref id, typeName, AssetType);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Color AccentColor => Color.FromRGB(0x2c3e50);
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace FlaxEditor.Content
|
||||
|
||||
menu.AddButton("Create collision data", () =>
|
||||
{
|
||||
var model = FlaxEngine.Content.LoadAsync<Model>(((ModelAssetItem)item).ID);
|
||||
var model = FlaxEngine.Content.LoadAsync<Model>(((ModelItem)item).ID);
|
||||
var collisionDataProxy = (CollisionDataProxy)Editor.Instance.ContentDatabase.GetProxy<CollisionData>();
|
||||
collisionDataProxy.CreateCollisionDataFromModel(model);
|
||||
});
|
||||
|
||||
@@ -10,6 +10,31 @@ using FlaxEngine.GUI;
|
||||
|
||||
namespace FlaxEditor.Content
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="BinaryAssetItem"/> for <see cref="ParticleSystem"/> assets.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetItem" />
|
||||
class ParticleSystemItem : BinaryAssetItem
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ParticleSystemItem(string path, ref Guid id, string typeName, Type type)
|
||||
: base(path, ref id, typeName, type, ContentItemSearchFilter.Particles)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnEditorDrag(object context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Actor OnEditorDrop(object context)
|
||||
{
|
||||
return new ParticleEffect { ParticleSystem = FlaxEngine.Content.LoadAsync<ParticleSystem>(ID) };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ParticleSystem"/> asset proxy object.
|
||||
/// </summary>
|
||||
@@ -28,6 +53,12 @@ namespace FlaxEditor.Content
|
||||
return new ParticleSystemWindow(editor, item as AssetItem);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
|
||||
{
|
||||
return new ParticleSystemItem(path, ref id, typeName, AssetType);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Color AccentColor => Color.FromRGB(0xFF790200);
|
||||
|
||||
|
||||
@@ -7,6 +7,31 @@ using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Content
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="BinaryAssetItem"/> for <see cref="SceneAnimation"/> assets.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetItem" />
|
||||
class SceneAnimationItem : BinaryAssetItem
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public SceneAnimationItem(string path, ref Guid id, string typeName, Type type)
|
||||
: base(path, ref id, typeName, type, ContentItemSearchFilter.Other)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnEditorDrag(object context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Actor OnEditorDrop(object context)
|
||||
{
|
||||
return new SceneAnimationPlayer { Animation = FlaxEngine.Content.LoadAsync<SceneAnimation>(ID) };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="SceneAnimation"/> asset proxy object.
|
||||
/// </summary>
|
||||
@@ -22,6 +47,12 @@ namespace FlaxEditor.Content
|
||||
return new SceneAnimationWindow(editor, item as AssetItem);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override AssetItem ConstructItem(string path, string typeName, ref Guid id)
|
||||
{
|
||||
return new SceneAnimationItem(path, ref id, typeName, AssetType);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Color AccentColor => Color.FromRGB(0xff5c4a87);
|
||||
|
||||
|
||||
@@ -518,7 +518,7 @@ bool Editor::Init()
|
||||
exit(failed ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// If during last lightmaps baking engine crashed we could try to restore the progress
|
||||
ShadowsOfMordor::Builder::Instance()->CheckIfRestoreState();
|
||||
|
||||
@@ -534,6 +534,12 @@ bool Editor::Init()
|
||||
// Initialize managed editor
|
||||
Managed->Init();
|
||||
|
||||
// Start play if requested by cmd line
|
||||
if (CommandLine::Options.Play.HasValue())
|
||||
{
|
||||
Managed->RequestStartPlayOnEditMode();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace FlaxEditor
|
||||
private bool _isAfterInit, _areModulesInited, _areModulesAfterInitEnd, _isHeadlessMode;
|
||||
private string _projectToOpen;
|
||||
private float _lastAutoSaveTimer;
|
||||
private Guid _startupSceneCmdLine;
|
||||
|
||||
private const string ProjectDataLastScene = "LastScene";
|
||||
private const string ProjectDataLastSceneSpawn = "LastSceneSpawn";
|
||||
@@ -271,10 +272,11 @@ namespace FlaxEditor
|
||||
module.OnEndInit();
|
||||
}
|
||||
|
||||
internal void Init(bool isHeadless, bool skipCompile)
|
||||
internal void Init(bool isHeadless, bool skipCompile, Guid startupScene)
|
||||
{
|
||||
EnsureState<LoadingState>();
|
||||
_isHeadlessMode = isHeadless;
|
||||
_startupSceneCmdLine = startupScene;
|
||||
Log("Editor init");
|
||||
if (isHeadless)
|
||||
Log("Running in headless mode");
|
||||
@@ -332,6 +334,17 @@ namespace FlaxEditor
|
||||
}
|
||||
|
||||
// Load scene
|
||||
|
||||
// scene cmd line argument
|
||||
var scene = ContentDatabase.Find(_startupSceneCmdLine);
|
||||
if (scene is SceneItem)
|
||||
{
|
||||
Editor.Log("Loading scene specified in command line");
|
||||
Scene.OpenScene(_startupSceneCmdLine);
|
||||
return;
|
||||
}
|
||||
|
||||
// if no scene cmd line argument is provided
|
||||
var startupSceneMode = Options.Options.General.StartupSceneMode;
|
||||
if (startupSceneMode == GeneralOptions.StartupSceneModes.LastOpened && !ProjectCache.HasCustomData(ProjectDataLastScene))
|
||||
{
|
||||
@@ -1309,6 +1322,19 @@ namespace FlaxEditor
|
||||
AnimGraphDebugFlow?.Invoke(debugFlow);
|
||||
}
|
||||
|
||||
private static void RequestStartPlayOnEditMode()
|
||||
{
|
||||
if (Instance.StateMachine.IsEditMode)
|
||||
Instance.Simulation.RequestStartPlay();
|
||||
if (Instance.StateMachine.IsPlayMode)
|
||||
Instance.StateMachine.StateChanged -= RequestStartPlayOnEditMode;
|
||||
}
|
||||
|
||||
internal static void Internal_RequestStartPlayOnEditMode()
|
||||
{
|
||||
Instance.StateMachine.StateChanged += RequestStartPlayOnEditMode;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern int Internal_ReadOutputLogs(string[] outMessages, byte[] outLogTypes, long[] outLogTimes);
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ MMethod* Internal_GetGameWindowSize = nullptr;
|
||||
MMethod* Internal_OnAppExit = nullptr;
|
||||
MMethod* Internal_OnVisualScriptingDebugFlow = nullptr;
|
||||
MMethod* Internal_OnAnimGraphDebugFlow = nullptr;
|
||||
MMethod* Internal_RequestStartPlayOnEditMode = nullptr;
|
||||
|
||||
void OnLightmapsBake(ShadowsOfMordor::BuildProgressStep step, float stepProgress, float totalProgress, bool isProgressEvent)
|
||||
{
|
||||
@@ -209,7 +210,7 @@ ManagedEditor::~ManagedEditor()
|
||||
void ManagedEditor::Init()
|
||||
{
|
||||
// Note: editor modules should perform quite fast init, any longer things should be done in async during 'editor splash screen time
|
||||
void* args[2];
|
||||
void* args[3];
|
||||
MClass* mclass = GetClass();
|
||||
if (mclass == nullptr)
|
||||
{
|
||||
@@ -230,6 +231,12 @@ void ManagedEditor::Init()
|
||||
bool skipCompile = CommandLine::Options.SkipCompile.IsTrue();
|
||||
args[0] = &isHeadless;
|
||||
args[1] = &skipCompile;
|
||||
Guid sceneId;
|
||||
if (!CommandLine::Options.Play.HasValue() || (CommandLine::Options.Play.HasValue() && Guid::Parse(CommandLine::Options.Play.GetValue(), sceneId)))
|
||||
{
|
||||
sceneId = Guid::Empty;
|
||||
}
|
||||
args[2] = &sceneId;
|
||||
initMethod->Invoke(instance, args, &exception);
|
||||
if (exception)
|
||||
{
|
||||
@@ -481,6 +488,18 @@ bool ManagedEditor::OnAppExit()
|
||||
return MUtils::Unbox<bool>(Internal_OnAppExit->Invoke(GetManagedInstance(), nullptr, nullptr));
|
||||
}
|
||||
|
||||
void ManagedEditor::RequestStartPlayOnEditMode()
|
||||
{
|
||||
if (!HasManagedInstance())
|
||||
return;
|
||||
if (Internal_RequestStartPlayOnEditMode == nullptr)
|
||||
{
|
||||
Internal_RequestStartPlayOnEditMode = GetClass()->GetMethod("Internal_RequestStartPlayOnEditMode");
|
||||
ASSERT(Internal_RequestStartPlayOnEditMode);
|
||||
}
|
||||
Internal_RequestStartPlayOnEditMode->Invoke(GetManagedInstance(), nullptr, nullptr);
|
||||
}
|
||||
|
||||
void ManagedEditor::OnEditorAssemblyLoaded(MAssembly* assembly)
|
||||
{
|
||||
ASSERT(!HasManagedInstance());
|
||||
|
||||
@@ -133,6 +133,11 @@ public:
|
||||
/// <returns>True if exit engine, otherwise false.</returns>
|
||||
bool OnAppExit();
|
||||
|
||||
/// <summary>
|
||||
/// Requests play mode when the editor is in edit mode ( once ).
|
||||
/// </summary>
|
||||
void RequestStartPlayOnEditMode();
|
||||
|
||||
private:
|
||||
|
||||
void OnEditorAssemblyLoaded(MAssembly* assembly);
|
||||
|
||||
@@ -203,6 +203,7 @@ namespace FlaxEditor.Modules
|
||||
else if (!gameWin.IsSelected)
|
||||
{
|
||||
gameWin.SelectTab(false);
|
||||
gameWin.RootWindow?.Window?.Focus();
|
||||
FlaxEngine.GUI.RootControl.GameRoot.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ namespace FlaxEditor.SceneGraph.GUI
|
||||
public ActorTreeNode()
|
||||
: base(true)
|
||||
{
|
||||
ChildrenIndent = 16.0f;
|
||||
}
|
||||
|
||||
internal virtual void LinkNode(ActorNode node)
|
||||
@@ -567,121 +568,12 @@ namespace FlaxEditor.SceneGraph.GUI
|
||||
{
|
||||
for (int i = 0; i < _dragAssets.Objects.Count; i++)
|
||||
{
|
||||
var assetItem = _dragAssets.Objects[i];
|
||||
|
||||
if (assetItem.IsOfType<SkinnedModel>())
|
||||
{
|
||||
// Create actor
|
||||
var model = FlaxEngine.Content.LoadAsync<SkinnedModel>(assetItem.ID);
|
||||
|
||||
var actor = new AnimatedModel
|
||||
{
|
||||
StaticFlags = Actor.StaticFlags,
|
||||
Name = assetItem.ShortName,
|
||||
SkinnedModel = model,
|
||||
Transform = Actor.Transform
|
||||
};
|
||||
|
||||
// Spawn
|
||||
ActorNode.Root.Spawn(actor, Actor);
|
||||
}
|
||||
else if (assetItem.IsOfType<Model>())
|
||||
{
|
||||
// Create actor
|
||||
var model = FlaxEngine.Content.LoadAsync<Model>(assetItem.ID);
|
||||
|
||||
var actor = new StaticModel
|
||||
{
|
||||
StaticFlags = Actor.StaticFlags,
|
||||
Name = assetItem.ShortName,
|
||||
Model = model,
|
||||
Transform = Actor.Transform
|
||||
};
|
||||
|
||||
// Spawn
|
||||
ActorNode.Root.Spawn(actor, Actor);
|
||||
}
|
||||
else if (assetItem.IsOfType<CollisionData>())
|
||||
{
|
||||
// Create actor
|
||||
var actor = new MeshCollider
|
||||
{
|
||||
StaticFlags = Actor.StaticFlags,
|
||||
Name = assetItem.ShortName,
|
||||
CollisionData = FlaxEngine.Content.LoadAsync<CollisionData>(assetItem.ID),
|
||||
Transform = Actor.Transform
|
||||
};
|
||||
|
||||
// Spawn
|
||||
ActorNode.Root.Spawn(actor, Actor);
|
||||
}
|
||||
else if (assetItem.IsOfType<ParticleSystem>())
|
||||
{
|
||||
// Create actor
|
||||
var actor = new ParticleEffect
|
||||
{
|
||||
StaticFlags = Actor.StaticFlags,
|
||||
Name = assetItem.ShortName,
|
||||
ParticleSystem = FlaxEngine.Content.LoadAsync<ParticleSystem>(assetItem.ID),
|
||||
Transform = Actor.Transform
|
||||
};
|
||||
|
||||
// Spawn
|
||||
ActorNode.Root.Spawn(actor, Actor);
|
||||
}
|
||||
else if (assetItem.IsOfType<SceneAnimation>())
|
||||
{
|
||||
// Create actor
|
||||
var actor = new SceneAnimationPlayer
|
||||
{
|
||||
StaticFlags = Actor.StaticFlags,
|
||||
Name = assetItem.ShortName,
|
||||
Animation = FlaxEngine.Content.LoadAsync<SceneAnimation>(assetItem.ID),
|
||||
Transform = Actor.Transform
|
||||
};
|
||||
|
||||
// Spawn
|
||||
ActorNode.Root.Spawn(actor, Actor);
|
||||
}
|
||||
else if (assetItem.IsOfType<AudioClip>())
|
||||
{
|
||||
// Create actor
|
||||
var actor = new AudioSource
|
||||
{
|
||||
StaticFlags = Actor.StaticFlags,
|
||||
Name = assetItem.ShortName,
|
||||
Clip = FlaxEngine.Content.LoadAsync<AudioClip>(assetItem.ID),
|
||||
Transform = Actor.Transform
|
||||
};
|
||||
|
||||
// Spawn
|
||||
ActorNode.Root.Spawn(actor, Actor);
|
||||
|
||||
break;
|
||||
}
|
||||
else if (assetItem.IsOfType<Prefab>())
|
||||
{
|
||||
// Create prefab instance
|
||||
var prefab = FlaxEngine.Content.LoadAsync<Prefab>(assetItem.ID);
|
||||
var actor = PrefabManager.SpawnPrefab(prefab, null);
|
||||
actor.StaticFlags = Actor.StaticFlags;
|
||||
actor.Name = assetItem.ShortName;
|
||||
actor.Transform = Actor.Transform;
|
||||
|
||||
// Spawn
|
||||
ActorNode.Root.Spawn(actor, Actor);
|
||||
}
|
||||
else if (assetItem is VisualScriptItem visualScriptItem && new ScriptType(typeof(Actor)).IsAssignableFrom(visualScriptItem.ScriptType) && visualScriptItem.ScriptType.CanCreateInstance)
|
||||
{
|
||||
// Create actor
|
||||
var actor = (Actor)visualScriptItem.ScriptType.CreateInstance();
|
||||
actor.StaticFlags = Actor.StaticFlags;
|
||||
actor.Name = assetItem.ShortName;
|
||||
actor.Transform = Actor.Transform;
|
||||
|
||||
// Spawn
|
||||
ActorNode.Root.Spawn(actor, Actor);
|
||||
}
|
||||
var item = _dragAssets.Objects[i];
|
||||
var actor = item.OnEditorDrop(this);
|
||||
actor.StaticFlags = Actor.StaticFlags;
|
||||
actor.Name = item.ShortName;
|
||||
actor.Transform = Actor.Transform;
|
||||
ActorNode.Root.Spawn(actor, Actor);
|
||||
}
|
||||
|
||||
result = DragDropEffect.Move;
|
||||
@@ -736,46 +628,12 @@ namespace FlaxEditor.SceneGraph.GUI
|
||||
return actorNode.Actor != null && actorNode != ActorNode && actorNode.Find(Actor) == null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the asset for drag and drop into one of the scene tree nodes.
|
||||
/// </summary>
|
||||
/// <param name="assetItem">The item.</param>
|
||||
/// <returns>True if can drag and drop it, otherwise false.</returns>
|
||||
public static bool ValidateDragAsset(AssetItem assetItem)
|
||||
private bool ValidateDragAsset(AssetItem assetItem)
|
||||
{
|
||||
if (assetItem.IsOfType<SkinnedModel>())
|
||||
return true;
|
||||
|
||||
if (assetItem.IsOfType<Model>())
|
||||
return true;
|
||||
|
||||
if (assetItem.IsOfType<AudioClip>())
|
||||
return true;
|
||||
|
||||
if (assetItem.IsOfType<Prefab>())
|
||||
return true;
|
||||
|
||||
if (assetItem.IsOfType<CollisionData>())
|
||||
return true;
|
||||
|
||||
if (assetItem.IsOfType<ParticleSystem>())
|
||||
return true;
|
||||
|
||||
if (assetItem.IsOfType<SceneAnimation>())
|
||||
return true;
|
||||
|
||||
if (assetItem is VisualScriptItem visualScriptItem && new ScriptType(typeof(Actor)).IsAssignableFrom(visualScriptItem.ScriptType) && visualScriptItem.ScriptType.CanCreateInstance)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return assetItem.OnEditorDrag(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the type of the actor for drag and drop into one of the scene tree nodes.
|
||||
/// </summary>
|
||||
/// <param name="actorType">Type of the actor.</param>
|
||||
/// <returns>True if can drag and drop it, otherwise false.</returns>
|
||||
public static bool ValidateDragActorType(ScriptType actorType)
|
||||
private static bool ValidateDragActorType(ScriptType actorType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -152,34 +152,10 @@ public:
|
||||
|
||||
namespace VisualStudio
|
||||
{
|
||||
bool SameFile(HANDLE h1, HANDLE h2)
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION bhfi1 = { 0 };
|
||||
BY_HANDLE_FILE_INFORMATION bhfi2 = { 0 };
|
||||
|
||||
if (::GetFileInformationByHandle(h1, &bhfi1) && ::GetFileInformationByHandle(h2, &bhfi2))
|
||||
{
|
||||
return ((bhfi1.nFileIndexHigh == bhfi2.nFileIndexHigh) && (bhfi1.nFileIndexLow == bhfi2.nFileIndexLow) && (bhfi1.dwVolumeSerialNumber == bhfi2.dwVolumeSerialNumber));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AreFilePathsEqual(const wchar_t* path1, const wchar_t* path2)
|
||||
{
|
||||
if (wcscmp(path1, path2) == 0)
|
||||
return true;
|
||||
|
||||
HANDLE file1 = CreateFileW(path1, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
HANDLE file2 = CreateFileW(path2, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
|
||||
bool result = SameFile(file1, file2);
|
||||
|
||||
CloseHandle(file1);
|
||||
CloseHandle(file2);
|
||||
|
||||
return result;
|
||||
}
|
||||
{
|
||||
return _wcsicmp(path1, path2) == 0;
|
||||
}
|
||||
|
||||
class ConnectionInternal
|
||||
{
|
||||
|
||||
@@ -44,6 +44,7 @@ VisualStudioEditor::VisualStudioEditor(VisualStudioVersion version, const String
|
||||
break;
|
||||
}
|
||||
_solutionPath = Globals::ProjectFolder / Editor::Project->Name + TEXT(".sln");
|
||||
_solutionPath.Replace('/', '\\'); // Use Windows-style path separators
|
||||
}
|
||||
|
||||
void VisualStudioEditor::FindEditors(Array<CodeEditor*>* output)
|
||||
@@ -145,7 +146,9 @@ void VisualStudioEditor::OpenFile(const String& path, int32 line)
|
||||
|
||||
// Open file
|
||||
const VisualStudio::Connection connection(*_CLSID, *_solutionPath);
|
||||
const auto result = connection.OpenFile(*path, line);
|
||||
String tmp = path;
|
||||
tmp.Replace('/', '\\'); // Use Windows-style path separators
|
||||
const auto result = connection.OpenFile(*tmp, line);
|
||||
if (result.Failed())
|
||||
{
|
||||
LOG(Warning, "Cannot open file \'{0}\':{1}. {2}.", path, line, String(result.Message.c_str()));
|
||||
|
||||
@@ -354,6 +354,10 @@ namespace FlaxEditor.Scripting
|
||||
|
||||
if (Type.Type == typeof(float))
|
||||
sb.Append("Float");
|
||||
else if (Type.Type == typeof(short))
|
||||
sb.Append("Int16");
|
||||
else if (Type.Type == typeof(ushort))
|
||||
sb.Append("Uint16");
|
||||
else if (Type.Type == typeof(int))
|
||||
sb.Append("Int");
|
||||
else if (Type.Type == typeof(uint))
|
||||
@@ -389,6 +393,24 @@ namespace FlaxEditor.Scripting
|
||||
else
|
||||
sb.Append(asUint);
|
||||
}
|
||||
else if (DefaultValue is short asInt16)
|
||||
{
|
||||
if (asInt16 == short.MaxValue)
|
||||
sb.Append("Int16.MaxValue");
|
||||
else if (asInt16 == short.MinValue)
|
||||
sb.Append("Int16.MinValue");
|
||||
else
|
||||
sb.Append(asInt16);
|
||||
}
|
||||
else if (DefaultValue is ushort asUint16)
|
||||
{
|
||||
if (asUint16 == ushort.MaxValue)
|
||||
sb.Append("Uint16.MaxValue");
|
||||
else if (asUint16 == ushort.MinValue)
|
||||
sb.Append("Uint16.MinValue");
|
||||
else
|
||||
sb.Append(asUint16);
|
||||
}
|
||||
else if (DefaultValue is float asFloat)
|
||||
{
|
||||
if (asFloat == float.MaxValue)
|
||||
@@ -703,6 +725,10 @@ namespace FlaxEditor.Scripting
|
||||
return "Int";
|
||||
if (_managed == typeof(uint))
|
||||
return "Uint";
|
||||
if (_managed == typeof(short))
|
||||
return "Int16";
|
||||
if (_managed == typeof(ushort))
|
||||
return "Uint16";
|
||||
if (_managed == typeof(bool))
|
||||
return "Bool";
|
||||
return _managed.Name;
|
||||
|
||||
@@ -55,7 +55,10 @@ namespace FlaxEditor.Utilities
|
||||
|
||||
Int2,
|
||||
Int3,
|
||||
Int4
|
||||
Int4,
|
||||
|
||||
Int16,
|
||||
Uint16,
|
||||
}
|
||||
|
||||
internal static VariantType ToVariantType(this Type type)
|
||||
@@ -67,6 +70,10 @@ namespace FlaxEditor.Utilities
|
||||
variantType = VariantType.Void;
|
||||
else if (type == typeof(bool))
|
||||
variantType = VariantType.Bool;
|
||||
else if (type == typeof(short))
|
||||
variantType = VariantType.Int16;
|
||||
else if (type == typeof(ushort))
|
||||
variantType = VariantType.Uint16;
|
||||
else if (type == typeof(int))
|
||||
variantType = VariantType.Int;
|
||||
else if (type == typeof(uint))
|
||||
@@ -242,6 +249,8 @@ namespace FlaxEditor.Utilities
|
||||
case VariantType.Null: return ScriptType.Null;
|
||||
case VariantType.Void: return new ScriptType(typeof(void));
|
||||
case VariantType.Bool: return new ScriptType(typeof(bool));
|
||||
case VariantType.Int16: return new ScriptType(typeof(short));
|
||||
case VariantType.Uint16: return new ScriptType(typeof(ushort));
|
||||
case VariantType.Int: return new ScriptType(typeof(int));
|
||||
case VariantType.Uint: return new ScriptType(typeof(uint));
|
||||
case VariantType.Int64: return new ScriptType(typeof(long));
|
||||
@@ -309,6 +318,8 @@ namespace FlaxEditor.Utilities
|
||||
case VariantType.Null: return null;
|
||||
case VariantType.Void: return typeof(void);
|
||||
case VariantType.Bool: return typeof(bool);
|
||||
case VariantType.Int16: return typeof(short);
|
||||
case VariantType.Uint16: return typeof(ushort);
|
||||
case VariantType.Int: return typeof(int);
|
||||
case VariantType.Uint: return typeof(uint);
|
||||
case VariantType.Int64: return typeof(long);
|
||||
@@ -378,6 +389,8 @@ namespace FlaxEditor.Utilities
|
||||
case VariantType.ManagedObject:
|
||||
case VariantType.Void: return null;
|
||||
case VariantType.Bool: return stream.ReadByte() != 0;
|
||||
case VariantType.Int16: return stream.ReadInt16();
|
||||
case VariantType.Uint16: return stream.ReadUInt16();
|
||||
case VariantType.Int: return stream.ReadInt32();
|
||||
case VariantType.Uint: return stream.ReadUInt32();
|
||||
case VariantType.Int64: return stream.ReadInt64();
|
||||
@@ -513,6 +526,12 @@ namespace FlaxEditor.Utilities
|
||||
case VariantType.Bool:
|
||||
stream.Write((byte)((bool)value ? 1 : 0));
|
||||
break;
|
||||
case VariantType.Int16:
|
||||
stream.Write((short)value);
|
||||
break;
|
||||
case VariantType.Uint16:
|
||||
stream.Write((ushort)value);
|
||||
break;
|
||||
case VariantType.Int:
|
||||
stream.Write((int)value);
|
||||
break;
|
||||
@@ -687,6 +706,12 @@ namespace FlaxEditor.Utilities
|
||||
case VariantType.Bool:
|
||||
stream.WriteValue((bool)value);
|
||||
break;
|
||||
case VariantType.Int16:
|
||||
stream.WriteValue((short)value);
|
||||
break;
|
||||
case VariantType.Uint16:
|
||||
stream.WriteValue((ushort)value);
|
||||
break;
|
||||
case VariantType.Int:
|
||||
stream.WriteValue((int)value);
|
||||
break;
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace FlaxEditor.Viewport
|
||||
private readonly ViewportWidgetButton _rotateSnapping;
|
||||
private readonly ViewportWidgetButton _scaleSnapping;
|
||||
|
||||
private readonly DragAssets<DragDropEventArgs> _dragAssets = new DragAssets<DragDropEventArgs>(ValidateDragItem);
|
||||
private readonly DragAssets<DragDropEventArgs> _dragAssets;
|
||||
private readonly DragActorType<DragDropEventArgs> _dragActorType = new DragActorType<DragDropEventArgs>(ValidateDragActorType);
|
||||
|
||||
private SelectionOutline _customSelectionOutline;
|
||||
@@ -187,6 +187,7 @@ namespace FlaxEditor.Viewport
|
||||
: base(Object.New<SceneRenderTask>(), editor.Undo)
|
||||
{
|
||||
_editor = editor;
|
||||
_dragAssets = new DragAssets<DragDropEventArgs>(ValidateDragItem);
|
||||
|
||||
// Prepare rendering task
|
||||
Task.ActorsSource = ActorsSources.Scenes;
|
||||
@@ -800,31 +801,19 @@ namespace FlaxEditor.Viewport
|
||||
return result;
|
||||
}
|
||||
|
||||
private static bool ValidateDragItem(ContentItem contentItem)
|
||||
private bool ValidateDragItem(ContentItem contentItem)
|
||||
{
|
||||
if (!Level.IsAnySceneLoaded)
|
||||
return false;
|
||||
|
||||
if (contentItem is AssetItem assetItem)
|
||||
{
|
||||
if (assetItem.IsOfType<ParticleSystem>())
|
||||
return true;
|
||||
if (assetItem.IsOfType<SceneAnimation>())
|
||||
if (assetItem.OnEditorDrag(this))
|
||||
return true;
|
||||
if (assetItem.IsOfType<MaterialBase>())
|
||||
return true;
|
||||
if (assetItem.IsOfType<ModelBase>())
|
||||
return true;
|
||||
if (assetItem.IsOfType<CollisionData>())
|
||||
return true;
|
||||
if (assetItem.IsOfType<AudioClip>())
|
||||
return true;
|
||||
if (assetItem.IsOfType<Prefab>())
|
||||
return true;
|
||||
if (assetItem.IsOfType<SceneAsset>())
|
||||
return true;
|
||||
if (assetItem is VisualScriptItem visualScriptItem && new ScriptType(typeof(Actor)).IsAssignableFrom(visualScriptItem.ScriptType) && visualScriptItem.ScriptType.CanCreateInstance)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -891,119 +880,40 @@ namespace FlaxEditor.Viewport
|
||||
|
||||
private void Spawn(AssetItem item, SceneGraphNode hit, ref Vector2 location, ref Vector3 hitLocation)
|
||||
{
|
||||
if (item is AssetItem assetItem)
|
||||
if (item.IsOfType<MaterialBase>())
|
||||
{
|
||||
if (assetItem.IsOfType<ParticleSystem>())
|
||||
if (hit is StaticModelNode staticModelNode)
|
||||
{
|
||||
var asset = FlaxEngine.Content.LoadAsync<ParticleSystem>(item.ID);
|
||||
var actor = new ParticleEffect
|
||||
{
|
||||
Name = item.ShortName,
|
||||
ParticleSystem = asset
|
||||
};
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
if (assetItem.IsOfType<SceneAnimation>())
|
||||
{
|
||||
var asset = FlaxEngine.Content.LoadAsync<SceneAnimation>(item.ID);
|
||||
var actor = new SceneAnimationPlayer
|
||||
{
|
||||
Name = item.ShortName,
|
||||
Animation = asset
|
||||
};
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
if (assetItem.IsOfType<MaterialBase>())
|
||||
{
|
||||
if (hit is StaticModelNode staticModelNode)
|
||||
{
|
||||
var staticModel = (StaticModel)staticModelNode.Actor;
|
||||
var ray = ConvertMouseToRay(ref location);
|
||||
if (staticModel.IntersectsEntry(ref ray, out _, out _, out var entryIndex))
|
||||
{
|
||||
var material = FlaxEngine.Content.LoadAsync<MaterialBase>(item.ID);
|
||||
using (new UndoBlock(Undo, staticModel, "Change material"))
|
||||
staticModel.SetMaterial(entryIndex, material);
|
||||
}
|
||||
}
|
||||
else if (hit is BoxBrushNode.SideLinkNode brushSurfaceNode)
|
||||
var staticModel = (StaticModel)staticModelNode.Actor;
|
||||
var ray = ConvertMouseToRay(ref location);
|
||||
if (staticModel.IntersectsEntry(ref ray, out _, out _, out var entryIndex))
|
||||
{
|
||||
var material = FlaxEngine.Content.LoadAsync<MaterialBase>(item.ID);
|
||||
using (new UndoBlock(Undo, brushSurfaceNode.Brush, "Change material"))
|
||||
{
|
||||
var surface = brushSurfaceNode.Surface;
|
||||
surface.Material = material;
|
||||
brushSurfaceNode.Surface = surface;
|
||||
}
|
||||
using (new UndoBlock(Undo, staticModel, "Change material"))
|
||||
staticModel.SetMaterial(entryIndex, material);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (assetItem.IsOfType<SkinnedModel>())
|
||||
else if (hit is BoxBrushNode.SideLinkNode brushSurfaceNode)
|
||||
{
|
||||
var model = FlaxEngine.Content.LoadAsync<SkinnedModel>(item.ID);
|
||||
var actor = new AnimatedModel
|
||||
var material = FlaxEngine.Content.LoadAsync<MaterialBase>(item.ID);
|
||||
using (new UndoBlock(Undo, brushSurfaceNode.Brush, "Change material"))
|
||||
{
|
||||
Name = item.ShortName,
|
||||
SkinnedModel = model
|
||||
};
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
if (assetItem.IsOfType<Model>())
|
||||
{
|
||||
var model = FlaxEngine.Content.LoadAsync<Model>(item.ID);
|
||||
var actor = new StaticModel
|
||||
{
|
||||
Name = item.ShortName,
|
||||
Model = model
|
||||
};
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
if (assetItem.IsOfType<CollisionData>())
|
||||
{
|
||||
var collisionData = FlaxEngine.Content.LoadAsync<CollisionData>(item.ID);
|
||||
var actor = new MeshCollider
|
||||
{
|
||||
Name = item.ShortName,
|
||||
CollisionData = collisionData
|
||||
};
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
if (assetItem.IsOfType<AudioClip>())
|
||||
{
|
||||
var clip = FlaxEngine.Content.LoadAsync<AudioClip>(item.ID);
|
||||
var actor = new AudioSource
|
||||
{
|
||||
Name = item.ShortName,
|
||||
Clip = clip
|
||||
};
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
if (assetItem.IsOfType<Prefab>())
|
||||
{
|
||||
var prefab = FlaxEngine.Content.LoadAsync<Prefab>(item.ID);
|
||||
var actor = PrefabManager.SpawnPrefab(prefab, null);
|
||||
actor.Name = item.ShortName;
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
if (assetItem.IsOfType<SceneAsset>())
|
||||
{
|
||||
Editor.Instance.Scene.OpenScene(item.ID, true);
|
||||
return;
|
||||
}
|
||||
if (assetItem is VisualScriptItem visualScriptItem && new ScriptType(typeof(Actor)).IsAssignableFrom(visualScriptItem.ScriptType) && visualScriptItem.ScriptType.CanCreateInstance)
|
||||
{
|
||||
var actor = (Actor)visualScriptItem.ScriptType.CreateInstance();
|
||||
actor.Name = item.ShortName;
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
var surface = brushSurfaceNode.Surface;
|
||||
surface.Material = material;
|
||||
brushSurfaceNode.Surface = surface;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (item.IsOfType<SceneAsset>())
|
||||
{
|
||||
Editor.Instance.Scene.OpenScene(item.ID, true);
|
||||
return;
|
||||
}
|
||||
{
|
||||
var actor = item.OnEditorDrop(this);
|
||||
actor.Name = item.ShortName;
|
||||
Spawn(actor, ref hitLocation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Policy;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEditor.Gizmo;
|
||||
using FlaxEditor.GUI.ContextMenu;
|
||||
@@ -53,7 +54,7 @@ namespace FlaxEditor.Viewport
|
||||
private readonly ViewportDebugDrawData _debugDrawData = new ViewportDebugDrawData(32);
|
||||
private IntPtr _debugDrawContext;
|
||||
private PrefabSpritesRenderer _spritesRenderer;
|
||||
private readonly DragAssets _dragAssets = new DragAssets(ValidateDragItem);
|
||||
private readonly DragAssets _dragAssets;
|
||||
private readonly DragActorType _dragActorType = new DragActorType(ValidateDragActorType);
|
||||
private readonly DragHandlers _dragHandlers = new DragHandlers();
|
||||
|
||||
@@ -89,6 +90,7 @@ namespace FlaxEditor.Viewport
|
||||
Undo = window.Undo;
|
||||
ViewportCamera = new FPSCamera();
|
||||
_debugDrawContext = DebugDraw.AllocateContext();
|
||||
_dragAssets = new DragAssets(ValidateDragItem);
|
||||
|
||||
// Prepare rendering task
|
||||
Task.ActorsSource = ActorsSources.CustomActors;
|
||||
@@ -673,24 +675,14 @@ namespace FlaxEditor.Viewport
|
||||
return _dragHandlers.OnDragEnter(data);
|
||||
}
|
||||
|
||||
private static bool ValidateDragItem(ContentItem contentItem)
|
||||
private bool ValidateDragItem(ContentItem contentItem)
|
||||
{
|
||||
if (contentItem is AssetItem assetItem)
|
||||
{
|
||||
if (assetItem.IsOfType<ParticleSystem>())
|
||||
if (assetItem.OnEditorDrag(this))
|
||||
return true;
|
||||
if (assetItem.IsOfType<MaterialBase>())
|
||||
return true;
|
||||
if (assetItem.IsOfType<ModelBase>())
|
||||
return true;
|
||||
if (assetItem.IsOfType<CollisionData>())
|
||||
return true;
|
||||
if (assetItem.IsOfType<AudioClip>())
|
||||
return true;
|
||||
if (assetItem.IsOfType<Prefab>())
|
||||
return true;
|
||||
if (assetItem is VisualScriptItem visualScriptItem && new ScriptType(typeof(Actor)).IsAssignableFrom(visualScriptItem.ScriptType) && visualScriptItem.ScriptType.CanCreateInstance)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -743,17 +735,6 @@ namespace FlaxEditor.Viewport
|
||||
{
|
||||
if (item is BinaryAssetItem binaryAssetItem)
|
||||
{
|
||||
if (binaryAssetItem.Type == typeof(ParticleSystem))
|
||||
{
|
||||
var particleSystem = FlaxEngine.Content.LoadAsync<ParticleSystem>(item.ID);
|
||||
var actor = new ParticleEffect
|
||||
{
|
||||
Name = item.ShortName,
|
||||
ParticleSystem = particleSystem
|
||||
};
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
if (typeof(MaterialBase).IsAssignableFrom(binaryAssetItem.Type))
|
||||
{
|
||||
if (hit is StaticModelNode staticModelNode)
|
||||
@@ -769,65 +750,11 @@ namespace FlaxEditor.Viewport
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (typeof(SkinnedModel).IsAssignableFrom(binaryAssetItem.Type))
|
||||
{
|
||||
var model = FlaxEngine.Content.LoadAsync<SkinnedModel>(item.ID);
|
||||
var actor = new AnimatedModel
|
||||
{
|
||||
Name = item.ShortName,
|
||||
SkinnedModel = model
|
||||
};
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
if (typeof(Model).IsAssignableFrom(binaryAssetItem.Type))
|
||||
{
|
||||
var model = FlaxEngine.Content.LoadAsync<Model>(item.ID);
|
||||
var actor = new StaticModel
|
||||
{
|
||||
Name = item.ShortName,
|
||||
Model = model
|
||||
};
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
if (binaryAssetItem.IsOfType<CollisionData>())
|
||||
{
|
||||
var collisionData = FlaxEngine.Content.LoadAsync<CollisionData>(item.ID);
|
||||
var actor = new MeshCollider
|
||||
{
|
||||
Name = item.ShortName,
|
||||
CollisionData = collisionData
|
||||
};
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
if (typeof(AudioClip).IsAssignableFrom(binaryAssetItem.Type))
|
||||
{
|
||||
var clip = FlaxEngine.Content.LoadAsync<AudioClip>(item.ID);
|
||||
var actor = new AudioSource
|
||||
{
|
||||
Name = item.ShortName,
|
||||
Clip = clip
|
||||
};
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
if (typeof(Prefab).IsAssignableFrom(binaryAssetItem.Type))
|
||||
{
|
||||
var prefab = FlaxEngine.Content.LoadAsync<Prefab>(item.ID);
|
||||
var actor = PrefabManager.SpawnPrefab(prefab, null);
|
||||
actor.Name = item.ShortName;
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (item is VisualScriptItem visualScriptItem && new ScriptType(typeof(Actor)).IsAssignableFrom(visualScriptItem.ScriptType) && visualScriptItem.ScriptType.CanCreateInstance)
|
||||
{
|
||||
var actor = (Actor)visualScriptItem.ScriptType.CreateInstance();
|
||||
var actor = item.OnEditorDrop(this);
|
||||
actor.Name = item.ShortName;
|
||||
Spawn(actor, ref hitLocation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -160,6 +160,10 @@ const char* VariantType::GetTypeName() const
|
||||
return "System.Void";
|
||||
case Bool:
|
||||
return "System.Boolean";
|
||||
case Int16:
|
||||
return "System.Int16";
|
||||
case Uint16:
|
||||
return "System.UInt16";
|
||||
case Int:
|
||||
return "System.Int32";
|
||||
case Uint:
|
||||
@@ -225,6 +229,12 @@ const char* VariantType::GetTypeName() const
|
||||
case Bool:
|
||||
result = TEXT("Bool");
|
||||
break;
|
||||
case Int16:
|
||||
result = TEXT("Int16");
|
||||
break;
|
||||
case Uint16:
|
||||
result = TEXT("Uint16");
|
||||
break;
|
||||
case Int:
|
||||
result = TEXT("Int");
|
||||
break;
|
||||
@@ -417,6 +427,18 @@ Variant::Variant(bool v)
|
||||
AsBool = v;
|
||||
}
|
||||
|
||||
Variant::Variant(int16 v)
|
||||
: Type(VariantType::Int16)
|
||||
{
|
||||
AsInt16 = v;
|
||||
}
|
||||
|
||||
Variant::Variant(uint16 v)
|
||||
: Type(VariantType::Uint16)
|
||||
{
|
||||
AsUint16 = v;
|
||||
}
|
||||
|
||||
Variant::Variant(int32 v)
|
||||
: Type(VariantType::Int)
|
||||
{
|
||||
@@ -896,6 +918,10 @@ bool Variant::operator==(const Variant& other) const
|
||||
return true;
|
||||
case VariantType::Bool:
|
||||
return AsBool == other.AsBool;
|
||||
case VariantType::Int16:
|
||||
return AsInt16 == other.AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return AsUint16 == other.AsUint16;
|
||||
case VariantType::Int:
|
||||
return AsInt == other.AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1004,6 +1030,10 @@ bool Variant::operator<(const Variant& other) const
|
||||
return true;
|
||||
case VariantType::Bool:
|
||||
return AsBool < other.AsBool;
|
||||
case VariantType::Int16:
|
||||
return AsInt16 < other.AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return AsUint16 < other.AsUint16;
|
||||
case VariantType::Int:
|
||||
return AsInt < other.AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1040,6 +1070,10 @@ Variant::operator bool() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return AsBool;
|
||||
case VariantType::Int16:
|
||||
return AsInt16 != 0;
|
||||
case VariantType::Uint16:
|
||||
return AsUint16 != 0;
|
||||
case VariantType::Int:
|
||||
return AsInt != 0;
|
||||
case VariantType::Uint:
|
||||
@@ -1075,6 +1109,10 @@ Variant::operator Char() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return AsBool ? 1 : 0;
|
||||
case VariantType::Int16:
|
||||
return (Char)AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return (Char)AsUint16;
|
||||
case VariantType::Int:
|
||||
return (Char)AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1101,6 +1139,10 @@ Variant::operator int8() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return AsBool ? 1 : 0;
|
||||
case VariantType::Int16:
|
||||
return (int8)AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return (int8)AsUint16;
|
||||
case VariantType::Int:
|
||||
return (int8)AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1127,6 +1169,10 @@ Variant::operator int16() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return AsBool ? 1 : 0;
|
||||
case VariantType::Int16:
|
||||
return AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return (int16)AsUint16;
|
||||
case VariantType::Int:
|
||||
return (int16)AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1153,6 +1199,10 @@ Variant::operator int32() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return AsBool ? 1 : 0;
|
||||
case VariantType::Int16:
|
||||
return (int32)AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return (int32)AsUint16;
|
||||
case VariantType::Int:
|
||||
return AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1179,6 +1229,10 @@ Variant::operator int64() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return AsBool ? 1 : 0;
|
||||
case VariantType::Int16:
|
||||
return (int64)AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return (int64)AsUint16;
|
||||
case VariantType::Int:
|
||||
return (int64)AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1205,6 +1259,10 @@ Variant::operator uint8() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return AsBool ? 1 : 0;
|
||||
case VariantType::Int16:
|
||||
return (uint8)AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return (uint8)AsUint16;
|
||||
case VariantType::Int:
|
||||
return (uint8)AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1231,6 +1289,10 @@ Variant::operator uint16() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return AsBool ? 1 : 0;
|
||||
case VariantType::Int16:
|
||||
return (uint16)AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return AsUint16;
|
||||
case VariantType::Int:
|
||||
return (uint16)AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1257,6 +1319,10 @@ Variant::operator uint32() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return AsBool ? 1 : 0;
|
||||
case VariantType::Int16:
|
||||
return (uint32)AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return (uint32)AsUint16;
|
||||
case VariantType::Int:
|
||||
return (uint32)AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1283,6 +1349,10 @@ Variant::operator uint64() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return AsBool ? 1 : 0;
|
||||
case VariantType::Int16:
|
||||
return (uint64)AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return (uint64)AsUint16;
|
||||
case VariantType::Int:
|
||||
return (uint64)AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1309,6 +1379,10 @@ Variant::operator float() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return AsBool ? 1.0f : 0.0f;
|
||||
case VariantType::Int16:
|
||||
return (float)AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return (float)AsUint16;
|
||||
case VariantType::Int:
|
||||
return (float)AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1333,6 +1407,10 @@ Variant::operator double() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return AsBool ? 1.0 : 0.0;
|
||||
case VariantType::Int16:
|
||||
return (double)AsInt16;
|
||||
case VariantType::Uint16:
|
||||
return (double)AsUint16;
|
||||
case VariantType::Int:
|
||||
return (double)AsInt;
|
||||
case VariantType::Uint:
|
||||
@@ -1423,6 +1501,10 @@ Variant::operator Vector2() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Vector2(AsBool ? 1.0f : 0.0f);
|
||||
case VariantType::Int16:
|
||||
return Vector2((float)AsInt16);
|
||||
case VariantType::Uint16:
|
||||
return Vector2((float)AsUint16);
|
||||
case VariantType::Int:
|
||||
return Vector2((float)AsInt);
|
||||
case VariantType::Uint:
|
||||
@@ -1459,6 +1541,10 @@ Variant::operator Vector3() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Vector3(AsBool ? 1.0f : 0.0f);
|
||||
case VariantType::Int16:
|
||||
return Vector3((float)AsInt16);
|
||||
case VariantType::Uint16:
|
||||
return Vector3((float)AsUint16);
|
||||
case VariantType::Int:
|
||||
return Vector3((float)AsInt);
|
||||
case VariantType::Uint:
|
||||
@@ -1495,6 +1581,10 @@ Variant::operator Vector4() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Vector4(AsBool ? 1.0f : 0.0f);
|
||||
case VariantType::Int16:
|
||||
return Vector4((float)AsInt16);
|
||||
case VariantType::Uint16:
|
||||
return Vector4((float)AsUint16);
|
||||
case VariantType::Int:
|
||||
return Vector4((float)AsInt);
|
||||
case VariantType::Uint:
|
||||
@@ -1531,6 +1621,10 @@ Variant::operator Int2() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Int2((int32)(AsBool ? 1.0f : 0.0f));
|
||||
case VariantType::Int16:
|
||||
return Int2((int32)AsInt16);
|
||||
case VariantType::Uint16:
|
||||
return Int2((int32)AsUint16);
|
||||
case VariantType::Int:
|
||||
return Int2((int32)AsInt);
|
||||
case VariantType::Uint:
|
||||
@@ -1573,6 +1667,10 @@ Variant::operator Int3() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Int3((int32)(AsBool ? 1 : 0));
|
||||
case VariantType::Int16:
|
||||
return Int3((int32)AsInt16);
|
||||
case VariantType::Uint16:
|
||||
return Int3((int32)AsUint16);
|
||||
case VariantType::Int:
|
||||
return Int3((int32)AsInt);
|
||||
case VariantType::Uint:
|
||||
@@ -1615,6 +1713,10 @@ Variant::operator Int4() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Int4((int32)(AsBool ? 1 : 0));
|
||||
case VariantType::Int16:
|
||||
return Int4(AsInt16);
|
||||
case VariantType::Uint16:
|
||||
return Int4((int32)AsUint16);
|
||||
case VariantType::Int:
|
||||
return Int4(AsInt);
|
||||
case VariantType::Uint:
|
||||
@@ -1657,6 +1759,10 @@ Variant::operator Color() const
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Color(AsBool ? 1.0f : 0.0f);
|
||||
case VariantType::Int16:
|
||||
return Color((float)AsInt16);
|
||||
case VariantType::Uint16:
|
||||
return Color((float)AsUint16);
|
||||
case VariantType::Int:
|
||||
return Color((float)AsInt);
|
||||
case VariantType::Uint:
|
||||
@@ -2139,6 +2245,10 @@ String Variant::ToString() const
|
||||
return TEXT("null");
|
||||
case VariantType::Bool:
|
||||
return AsBool ? TEXT("true") : TEXT("false");
|
||||
case VariantType::Int16:
|
||||
return StringUtils::ToString(AsInt16);
|
||||
case VariantType::Uint16:
|
||||
return StringUtils::ToString(AsUint16);
|
||||
case VariantType::Int:
|
||||
return StringUtils::ToString(AsInt);
|
||||
case VariantType::Uint:
|
||||
@@ -2207,6 +2317,8 @@ bool Variant::CanCast(const Variant& v, const VariantType& to)
|
||||
case VariantType::Bool:
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Int16:
|
||||
case VariantType::Uint16:
|
||||
case VariantType::Int:
|
||||
case VariantType::Uint:
|
||||
case VariantType::Int64:
|
||||
@@ -2221,10 +2333,50 @@ bool Variant::CanCast(const Variant& v, const VariantType& to)
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case VariantType::Int16:
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
case VariantType::Int:
|
||||
case VariantType::Int64:
|
||||
case VariantType::Uint16:
|
||||
case VariantType::Uint:
|
||||
case VariantType::Uint64:
|
||||
case VariantType::Float:
|
||||
case VariantType::Double:
|
||||
case VariantType::Vector2:
|
||||
case VariantType::Vector3:
|
||||
case VariantType::Vector4:
|
||||
case VariantType::Color:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case VariantType::Int:
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
case VariantType::Int16:
|
||||
case VariantType::Int64:
|
||||
case VariantType::Uint16:
|
||||
case VariantType::Uint:
|
||||
case VariantType::Uint64:
|
||||
case VariantType::Float:
|
||||
case VariantType::Double:
|
||||
case VariantType::Vector2:
|
||||
case VariantType::Vector3:
|
||||
case VariantType::Vector4:
|
||||
case VariantType::Color:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case VariantType::Uint16:
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
case VariantType::Int16:
|
||||
case VariantType::Int:
|
||||
case VariantType::Int64:
|
||||
case VariantType::Uint:
|
||||
case VariantType::Uint64:
|
||||
@@ -2242,7 +2394,9 @@ bool Variant::CanCast(const Variant& v, const VariantType& to)
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
case VariantType::Uint16:
|
||||
case VariantType::Uint64:
|
||||
case VariantType::Int16:
|
||||
case VariantType::Int:
|
||||
case VariantType::Int64:
|
||||
case VariantType::Float:
|
||||
@@ -2259,7 +2413,9 @@ bool Variant::CanCast(const Variant& v, const VariantType& to)
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
case VariantType::Int16:
|
||||
case VariantType::Int:
|
||||
case VariantType::Uint16:
|
||||
case VariantType::Uint:
|
||||
case VariantType::Uint64:
|
||||
case VariantType::Float:
|
||||
@@ -2276,7 +2432,9 @@ bool Variant::CanCast(const Variant& v, const VariantType& to)
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
case VariantType::Uint16:
|
||||
case VariantType::Uint:
|
||||
case VariantType::Int16:
|
||||
case VariantType::Int:
|
||||
case VariantType::Int64:
|
||||
case VariantType::Float:
|
||||
@@ -2293,7 +2451,9 @@ bool Variant::CanCast(const Variant& v, const VariantType& to)
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
case VariantType::Int16:
|
||||
case VariantType::Int:
|
||||
case VariantType::Uint16:
|
||||
case VariantType::Uint:
|
||||
case VariantType::Int64:
|
||||
case VariantType::Uint64:
|
||||
@@ -2310,8 +2470,10 @@ bool Variant::CanCast(const Variant& v, const VariantType& to)
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
case VariantType::Int16:
|
||||
case VariantType::Int:
|
||||
case VariantType::Uint:
|
||||
case VariantType::Uint16:
|
||||
case VariantType::Int64:
|
||||
case VariantType::Uint64:
|
||||
case VariantType::Float:
|
||||
@@ -2327,7 +2489,9 @@ bool Variant::CanCast(const Variant& v, const VariantType& to)
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
case VariantType::Uint16:
|
||||
case VariantType::Uint:
|
||||
case VariantType::Int16:
|
||||
case VariantType::Int:
|
||||
case VariantType::Int64:
|
||||
case VariantType::Float:
|
||||
@@ -2343,7 +2507,9 @@ bool Variant::CanCast(const Variant& v, const VariantType& to)
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
case VariantType::Uint16:
|
||||
case VariantType::Uint:
|
||||
case VariantType::Int16:
|
||||
case VariantType::Int:
|
||||
case VariantType::Int64:
|
||||
case VariantType::Float:
|
||||
@@ -2359,7 +2525,9 @@ bool Variant::CanCast(const Variant& v, const VariantType& to)
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
case VariantType::Uint16:
|
||||
case VariantType::Uint:
|
||||
case VariantType::Int16:
|
||||
case VariantType::Int:
|
||||
case VariantType::Int64:
|
||||
case VariantType::Float:
|
||||
@@ -2375,7 +2543,9 @@ bool Variant::CanCast(const Variant& v, const VariantType& to)
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
case VariantType::Uint16:
|
||||
case VariantType::Uint:
|
||||
case VariantType::Int16:
|
||||
case VariantType::Int:
|
||||
case VariantType::Int64:
|
||||
case VariantType::Float:
|
||||
@@ -2401,6 +2571,10 @@ Variant Variant::Cast(const Variant& v, const VariantType& to)
|
||||
case VariantType::Bool:
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Int16: // No portable literal suffix for short ( Available in MSVC but Undocumented : i16 )
|
||||
return Variant((int16)(v.AsBool ? 1 : 0));
|
||||
case VariantType::Uint16: // No portable literal suffix for short ( Available in MSVC but Undocumented : ui16 )
|
||||
return Variant((uint16)(v.AsBool ? 1 : 0));
|
||||
case VariantType::Int:
|
||||
return Variant(v.AsBool ? 1 : 0);
|
||||
case VariantType::Uint:
|
||||
@@ -2424,17 +2598,51 @@ Variant Variant::Cast(const Variant& v, const VariantType& to)
|
||||
default: ;
|
||||
}
|
||||
break;
|
||||
case VariantType::Int16:
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Variant(v.AsInt != 0);
|
||||
case VariantType::Int:
|
||||
return Variant((int32)v.AsInt16);
|
||||
case VariantType::Int64:
|
||||
return Variant((int64)v.AsInt16);
|
||||
case VariantType::Uint16:
|
||||
return Variant((uint16)v.AsInt16);
|
||||
case VariantType::Uint:
|
||||
return Variant((uint32)v.AsInt16);
|
||||
case VariantType::Uint64:
|
||||
return Variant((uint64)v.AsInt16);
|
||||
case VariantType::Float:
|
||||
return Variant((float)v.AsInt16);
|
||||
case VariantType::Double:
|
||||
return Variant((double)v.AsInt16);
|
||||
case VariantType::Vector2:
|
||||
return Variant(Vector2((float)v.AsInt16));
|
||||
case VariantType::Vector3:
|
||||
return Variant(Vector3((float)v.AsInt16));
|
||||
case VariantType::Vector4:
|
||||
return Variant(Vector4((float)v.AsInt16));
|
||||
case VariantType::Color:
|
||||
return Variant(Color((float)v.AsInt16));
|
||||
default: ;
|
||||
}
|
||||
break;
|
||||
case VariantType::Int:
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Variant(v.AsInt != 0);
|
||||
case VariantType::Int16:
|
||||
return Variant((int16)v.AsInt);
|
||||
case VariantType::Int64:
|
||||
return Variant((int64)v.AsUint);
|
||||
return Variant((int64)v.AsInt);
|
||||
case VariantType::Uint16:
|
||||
return Variant((uint16)v.AsInt);
|
||||
case VariantType::Uint:
|
||||
return Variant((uint32)v.AsInt);
|
||||
case VariantType::Uint64:
|
||||
return Variant((uint64)v.AsUint);
|
||||
return Variant((uint64)v.AsInt);
|
||||
case VariantType::Float:
|
||||
return Variant((float)v.AsInt);
|
||||
case VariantType::Double:
|
||||
@@ -2450,15 +2658,49 @@ Variant Variant::Cast(const Variant& v, const VariantType& to)
|
||||
default: ;
|
||||
}
|
||||
break;
|
||||
case VariantType::Uint16:
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Variant(v.AsUint16 != 0);
|
||||
case VariantType::Int16:
|
||||
return Variant((int16)v.AsUint16);
|
||||
case VariantType::Int:
|
||||
return Variant((int32)v.AsUint16);
|
||||
case VariantType::Int64:
|
||||
return Variant((int64)v.AsUint16);
|
||||
case VariantType::Uint16:
|
||||
return Variant((uint16)v.AsUint16);
|
||||
case VariantType::Uint64:
|
||||
return Variant((uint64)v.AsUint16);
|
||||
case VariantType::Float:
|
||||
return Variant((float)v.AsUint16);
|
||||
case VariantType::Double:
|
||||
return Variant((double)v.AsUint16);
|
||||
case VariantType::Vector2:
|
||||
return Variant(Vector2((float)v.AsUint16));
|
||||
case VariantType::Vector3:
|
||||
return Variant(Vector3((float)v.AsUint16));
|
||||
case VariantType::Vector4:
|
||||
return Variant(Vector4((float)v.AsUint16));
|
||||
case VariantType::Color:
|
||||
return Variant(Color((float)v.AsUint16));
|
||||
default: ;
|
||||
}
|
||||
break;
|
||||
case VariantType::Uint:
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Variant(v.AsUint != 0);
|
||||
case VariantType::Int16:
|
||||
return Variant((int16)v.AsUint);
|
||||
case VariantType::Int:
|
||||
return Variant((int32)v.AsUint);
|
||||
case VariantType::Int64:
|
||||
return Variant((int64)v.AsUint);
|
||||
case VariantType::Uint16:
|
||||
return Variant((uint16)v.AsUint);
|
||||
case VariantType::Uint64:
|
||||
return Variant((uint64)v.AsUint);
|
||||
case VariantType::Float:
|
||||
@@ -2481,8 +2723,12 @@ Variant Variant::Cast(const Variant& v, const VariantType& to)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Variant(v.AsInt64 != 0);
|
||||
case VariantType::Int64:
|
||||
return Variant((int64)v.AsUint);
|
||||
case VariantType::Int16:
|
||||
return Variant((int16)v.AsInt64);
|
||||
case VariantType::Int:
|
||||
return Variant((int32)v.AsInt64);
|
||||
case VariantType::Uint16:
|
||||
return Variant((uint16)v.AsInt64);
|
||||
case VariantType::Uint:
|
||||
return Variant((uint32)v.AsInt64);
|
||||
case VariantType::Uint64:
|
||||
@@ -2507,10 +2753,14 @@ Variant Variant::Cast(const Variant& v, const VariantType& to)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Variant(v.AsUint64 != 0);
|
||||
case VariantType::Int16:
|
||||
return Variant((int16)v.AsUint64);
|
||||
case VariantType::Int:
|
||||
return Variant((int32)v.AsUint64);
|
||||
case VariantType::Int64:
|
||||
return Variant((int64)v.AsUint64);
|
||||
case VariantType::Uint16:
|
||||
return Variant((uint16)v.AsUint16);
|
||||
case VariantType::Uint:
|
||||
return Variant((uint32)v.AsUint);
|
||||
case VariantType::Float:
|
||||
@@ -2533,8 +2783,12 @@ Variant Variant::Cast(const Variant& v, const VariantType& to)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Variant(Math::Abs(v.AsFloat) > ZeroTolerance);
|
||||
case VariantType::Int16:
|
||||
return Variant((int16)v.AsFloat);
|
||||
case VariantType::Int:
|
||||
return Variant((int32)v.AsFloat);
|
||||
case VariantType::Uint16:
|
||||
return Variant((uint16)v.AsFloat);
|
||||
case VariantType::Uint:
|
||||
return Variant((uint32)v.AsFloat);
|
||||
case VariantType::Int64:
|
||||
@@ -2559,8 +2813,12 @@ Variant Variant::Cast(const Variant& v, const VariantType& to)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Variant(Math::Abs(v.AsDouble) > ZeroTolerance);
|
||||
case VariantType::Int16:
|
||||
return Variant((int16)v.AsDouble);
|
||||
case VariantType::Int:
|
||||
return Variant((int32)v.AsDouble);
|
||||
case VariantType::Uint16:
|
||||
return Variant((uint16)v.AsDouble);
|
||||
case VariantType::Uint:
|
||||
return Variant((uint32)v.AsDouble);
|
||||
case VariantType::Int64:
|
||||
@@ -2585,8 +2843,12 @@ Variant Variant::Cast(const Variant& v, const VariantType& to)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Variant(Math::Abs(((Vector2*)v.AsData)->X) > ZeroTolerance);
|
||||
case VariantType::Int16:
|
||||
return Variant((int16)((Vector2*)v.AsData)->X);
|
||||
case VariantType::Int:
|
||||
return Variant((int32)((Vector2*)v.AsData)->X);
|
||||
case VariantType::Uint16:
|
||||
return Variant((uint16)((Vector2*)v.AsData)->X);
|
||||
case VariantType::Uint:
|
||||
return Variant((uint32)((Vector2*)v.AsData)->X);
|
||||
case VariantType::Int64:
|
||||
@@ -2611,8 +2873,12 @@ Variant Variant::Cast(const Variant& v, const VariantType& to)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Variant(Math::Abs(((Vector3*)v.AsData)->X) > ZeroTolerance);
|
||||
case VariantType::Int16:
|
||||
return Variant((int16)((Vector3*)v.AsData)->X);
|
||||
case VariantType::Int:
|
||||
return Variant((int32)((Vector3*)v.AsData)->X);
|
||||
case VariantType::Uint16:
|
||||
return Variant((uint16)((Vector3*)v.AsData)->X);
|
||||
case VariantType::Uint:
|
||||
return Variant((uint32)((Vector3*)v.AsData)->X);
|
||||
case VariantType::Int64:
|
||||
@@ -2637,8 +2903,12 @@ Variant Variant::Cast(const Variant& v, const VariantType& to)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Variant(Math::Abs(((Vector4*)v.AsData)->X) > ZeroTolerance);
|
||||
case VariantType::Int16:
|
||||
return Variant((int16)((Vector4*)v.AsData)->X);
|
||||
case VariantType::Int:
|
||||
return Variant((int32)((Vector4*)v.AsData)->X);
|
||||
case VariantType::Uint16:
|
||||
return Variant((uint16)((Vector4*)v.AsData)->X);
|
||||
case VariantType::Uint:
|
||||
return Variant((uint32)((Vector4*)v.AsData)->X);
|
||||
case VariantType::Int64:
|
||||
@@ -2663,8 +2933,12 @@ Variant Variant::Cast(const Variant& v, const VariantType& to)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return Variant(Math::Abs(((Color*)v.AsData)->R) > ZeroTolerance);
|
||||
case VariantType::Int16:
|
||||
return Variant((int16)((Color*)v.AsData)->R);
|
||||
case VariantType::Int:
|
||||
return Variant((int32)((Color*)v.AsData)->R);
|
||||
case VariantType::Uint16:
|
||||
return Variant((uint16)((Color*)v.AsData)->R);
|
||||
case VariantType::Uint:
|
||||
return Variant((uint32)((Color*)v.AsData)->R);
|
||||
case VariantType::Int64:
|
||||
@@ -2696,6 +2970,8 @@ bool Variant::NearEqual(const Variant& a, const Variant& b, float epsilon)
|
||||
return false;
|
||||
switch (a.Type.Type)
|
||||
{
|
||||
case VariantType::Int16:
|
||||
return Math::Abs(a.AsInt16 - b.AsInt16) <= (int32)epsilon;
|
||||
case VariantType::Int:
|
||||
return Math::Abs(a.AsInt - b.AsInt) <= (int32)epsilon;
|
||||
case VariantType::Int64:
|
||||
@@ -2737,8 +3013,12 @@ Variant Variant::Lerp(const Variant& a, const Variant& b, float alpha)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return alpha < 0.5f ? a : b;
|
||||
case VariantType::Int16:
|
||||
return Math::Lerp(a.AsInt16, b.AsInt16, alpha);
|
||||
case VariantType::Int:
|
||||
return Math::Lerp(a.AsInt, b.AsInt, alpha);
|
||||
case VariantType::Uint16:
|
||||
return Math::Lerp(a.AsUint16, b.AsUint16, alpha);
|
||||
case VariantType::Uint:
|
||||
return Math::Lerp(a.AsUint, b.AsUint, alpha);
|
||||
case VariantType::Int64:
|
||||
@@ -2844,8 +3124,12 @@ uint32 GetHash(const Variant& key)
|
||||
{
|
||||
case VariantType::Bool:
|
||||
return GetHash(key.AsBool);
|
||||
case VariantType::Int16:
|
||||
return GetHash(key.AsInt16);
|
||||
case VariantType::Int:
|
||||
return GetHash(key.AsInt);
|
||||
case VariantType::Uint16:
|
||||
return GetHash(key.AsUint16);
|
||||
case VariantType::Uint:
|
||||
return GetHash(key.AsUint);
|
||||
case VariantType::Int64:
|
||||
|
||||
@@ -58,6 +58,9 @@ API_STRUCT(InBuild) struct FLAXENGINE_API VariantType
|
||||
Int3,
|
||||
Int4,
|
||||
|
||||
Int16,
|
||||
Uint16,
|
||||
|
||||
MAX
|
||||
};
|
||||
|
||||
@@ -135,6 +138,8 @@ API_STRUCT(InBuild) struct FLAXENGINE_API Variant
|
||||
union
|
||||
{
|
||||
bool AsBool;
|
||||
int16 AsInt16;
|
||||
uint16 AsUint16;
|
||||
int32 AsInt;
|
||||
uint32 AsUint;
|
||||
int64 AsInt64;
|
||||
@@ -184,6 +189,8 @@ public:
|
||||
Variant(Variant&& other) noexcept;
|
||||
|
||||
Variant(bool v);
|
||||
Variant(int16 v);
|
||||
Variant(uint16 v);
|
||||
Variant(int32 v);
|
||||
Variant(uint32 v);
|
||||
Variant(int64 v);
|
||||
|
||||
@@ -102,6 +102,23 @@ bool CommandLine::Parse(const Char* cmdLine)
|
||||
*(end - len) = 0; \
|
||||
end -= len; \
|
||||
}
|
||||
|
||||
#define PARSE_ARG_OPT_SWITCH(text, field) \
|
||||
pos = (Char*)StringUtils::FindIgnoreCase(buffer.Get(), TEXT(text)); \
|
||||
if (pos) \
|
||||
{ \
|
||||
len = ARRAY_COUNT(text) - 1; \
|
||||
if (ParseArg(pos + len, argStart, argEnd)) \
|
||||
Options.field = String::Empty; \
|
||||
else \
|
||||
{ \
|
||||
Options.field = String(argStart, static_cast<int32>(argEnd - argStart)); \
|
||||
len = static_cast<int32>((argEnd - pos) + 1); \
|
||||
Platform::MemoryCopy(pos, pos + len, (end - pos - len) * 2); \
|
||||
*(end - len) = 0; \
|
||||
end -= len; \
|
||||
} \
|
||||
}
|
||||
|
||||
PARSE_BOOL_SWITCH("-windowed ", Windowed);
|
||||
PARSE_BOOL_SWITCH("-fullscreen ", Fullscreen);
|
||||
@@ -137,6 +154,7 @@ bool CommandLine::Parse(const Char* cmdLine)
|
||||
PARSE_ARG_SWITCH("-build ", Build);
|
||||
PARSE_BOOL_SWITCH("-skipcompile ", SkipCompile);
|
||||
PARSE_BOOL_SWITCH("-shaderdebug ", ShaderDebug);
|
||||
PARSE_ARG_OPT_SWITCH("-play ", Play);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -164,6 +164,11 @@ public:
|
||||
/// </summary>
|
||||
Nullable<bool> ShaderDebug;
|
||||
|
||||
/// <summary>
|
||||
/// -play !guid! ( Scene to play, can be empty to use default )
|
||||
/// </summary>
|
||||
Nullable<String> Play;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -363,7 +363,8 @@ void Mesh::GetDrawCallGeometry(DrawCall& drawCall) const
|
||||
|
||||
void Mesh::Render(GPUContext* context) const
|
||||
{
|
||||
ASSERT(IsInitialized());
|
||||
if (!IsInitialized())
|
||||
return;
|
||||
|
||||
context->BindVB(ToSpan((GPUBuffer**)_vertexBuffers, 3));
|
||||
context->BindIB(_indexBuffer);
|
||||
@@ -372,7 +373,7 @@ void Mesh::Render(GPUContext* context) const
|
||||
|
||||
void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, DrawPass drawModes, float perInstanceRandom) const
|
||||
{
|
||||
if (!material || !material->IsSurface())
|
||||
if (!material || !material->IsSurface() || !IsInitialized())
|
||||
return;
|
||||
|
||||
// Submit draw call
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
#include "ParticleEmitterGraph.CPU.h"
|
||||
#include "Engine/Core/Random.h"
|
||||
|
||||
// ReSharper disable CppCStyleCast
|
||||
// ReSharper disable CppClangTidyClangDiagnosticCastAlign
|
||||
// ReSharper disable CppDefaultCaseNotHandledInSwitchStatement
|
||||
// ReSharper disable CppClangTidyCppcoreguidelinesMacroUsage
|
||||
// ReSharper disable CppClangTidyClangDiagnosticOldStyleCast
|
||||
|
||||
#define RAND Random::Rand()
|
||||
#define RAND2 Vector2(RAND, RAND)
|
||||
#define RAND3 Vector3(RAND, RAND, RAND)
|
||||
@@ -62,7 +68,7 @@ namespace
|
||||
float scale = 1.0f;
|
||||
for (int32 i = 0; i < octaves; i++)
|
||||
{
|
||||
const float curWeight = Math::Pow(1.0f - ((float)i / octaves), Math::Lerp(2.0f, 0.2f, roughness));
|
||||
const float curWeight = Math::Pow(1.0f - ((float)i / (float)octaves), Math::Lerp(2.0f, 0.2f, roughness));
|
||||
|
||||
noise += Noise3D(position * scale) * curWeight;
|
||||
weight += curWeight;
|
||||
@@ -156,7 +162,7 @@ int32 ParticleEmitterGraphCPUExecutor::ProcessSpawnModule(int32 index)
|
||||
// Calculate actual spawn amount
|
||||
spawnCount = Math::Max(spawnCount, 0.0f);
|
||||
const int32 result = Math::FloorToInt(spawnCount);
|
||||
spawnCount -= result;
|
||||
spawnCount -= (float)result;
|
||||
data.SpawnCounter = spawnCount;
|
||||
|
||||
return result;
|
||||
@@ -475,7 +481,7 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode*
|
||||
|
||||
auto& velocity = _data->Buffer->Layout->Attributes[node->Attributes[0]];
|
||||
auto& mass = _data->Buffer->Layout->Attributes[node->Attributes[1]];
|
||||
byte* spriteSizePtr = useSpriteSize ? start + _data->Buffer->Layout->Attributes[node->Attributes[2]].Offset : 0;
|
||||
byte* spriteSizePtr = useSpriteSize ? start + _data->Buffer->Layout->Attributes[node->Attributes[2]].Offset : nullptr;
|
||||
|
||||
byte* velocityPtr = start + velocity.Offset;
|
||||
byte* massPtr = start + mass.Offset;
|
||||
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
// Left wheel of the rear axle.
|
||||
RearLeft,
|
||||
// Right wheel of the rear axle.
|
||||
ReadRight,
|
||||
RearRight,
|
||||
// Non-drivable wheel.
|
||||
NoDrive,
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "Engine/Platform/Platform.h"
|
||||
#include "Engine/Platform/Window.h"
|
||||
#include "Engine/Platform/FileSystem.h"
|
||||
#include "Engine/Platform/CreateWindowSettings.h"
|
||||
#include "Engine/Platform/WindowsManager.h"
|
||||
#include "Engine/Platform/MemoryStats.h"
|
||||
@@ -1118,6 +1119,19 @@ void* WindowsPlatform::LoadLibrary(const Char* filename)
|
||||
{
|
||||
ASSERT(filename);
|
||||
|
||||
// Add folder to search path to load dependency libraries
|
||||
StringView folder = StringUtils::GetDirectoryName(filename);
|
||||
if (folder.HasChars() && FileSystem::IsRelative(folder))
|
||||
folder = StringView::Empty;
|
||||
if (folder.HasChars())
|
||||
{
|
||||
Char& end = ((Char*)folder.Get())[folder.Length()];
|
||||
const Char c = end;
|
||||
end = 0;
|
||||
SetDllDirectoryW(*folder);
|
||||
end = c;
|
||||
}
|
||||
|
||||
// Avoiding windows dialog boxes if missing
|
||||
const DWORD errorMode = SEM_NOOPENFILEERRORBOX;
|
||||
DWORD prevErrorMode = 0;
|
||||
@@ -1134,12 +1148,15 @@ void* WindowsPlatform::LoadLibrary(const Char* filename)
|
||||
{
|
||||
SetThreadErrorMode(prevErrorMode, nullptr);
|
||||
}
|
||||
if (folder.HasChars())
|
||||
{
|
||||
SetDllDirectoryW(nullptr);
|
||||
}
|
||||
|
||||
#if CRASH_LOG_ENABLE
|
||||
// Refresh modules info during next stack trace collecting to have valid debug symbols information
|
||||
SymLocker.Lock();
|
||||
const auto folder = StringUtils::GetDirectoryName(filename);
|
||||
if (!SymbolsPath.Contains(folder))
|
||||
if (folder.HasChars() && !SymbolsPath.Contains(folder))
|
||||
{
|
||||
SymbolsPath.Add(folder);
|
||||
OnSymbolsPathModified();
|
||||
|
||||
@@ -287,6 +287,8 @@ bool FontManager::AddNewEntry(Font* font, Char c, FontCharacterEntry& entry)
|
||||
|
||||
void FontManager::Invalidate(FontCharacterEntry& entry)
|
||||
{
|
||||
if (entry.TextureIndex == MAX_uint8)
|
||||
return;
|
||||
auto atlas = Atlases[entry.TextureIndex];
|
||||
const uint32 padding = atlas->GetPaddingAmount();
|
||||
const uint32 slotX = static_cast<uint32>(entry.UV.X - padding);
|
||||
|
||||
@@ -154,13 +154,13 @@ VariantType MUtils::UnboxVariantType(MonoType* monoType)
|
||||
if (klass == mono_get_boolean_class() || monoType->type == MONO_TYPE_BOOLEAN)
|
||||
return VariantType(VariantType::Bool);
|
||||
if (klass == mono_get_byte_class() || monoType->type == MONO_TYPE_U1)
|
||||
return VariantType(VariantType::Int);
|
||||
return VariantType(VariantType::Int16);
|
||||
if (klass == mono_get_sbyte_class() || monoType->type == MONO_TYPE_I1)
|
||||
return VariantType(VariantType::Int);
|
||||
return VariantType(VariantType::Int16);
|
||||
if (klass == mono_get_int16_class() || monoType->type == MONO_TYPE_I2)
|
||||
return VariantType(VariantType::Int);
|
||||
return VariantType(VariantType::Int16);
|
||||
if (klass == mono_get_uint16_class() || monoType->type == MONO_TYPE_U2)
|
||||
return VariantType(VariantType::Uint);
|
||||
return VariantType(VariantType::Uint16);
|
||||
if (klass == mono_get_int32_class() || monoType->type == MONO_TYPE_I4)
|
||||
return VariantType(VariantType::Int);
|
||||
if (klass == mono_get_uint32_class() || monoType->type == MONO_TYPE_U4)
|
||||
@@ -266,13 +266,13 @@ Variant MUtils::UnboxVariant(MonoObject* value)
|
||||
if (klass == mono_get_boolean_class())
|
||||
return *static_cast<bool*>(mono_object_unbox(value));
|
||||
if (klass == mono_get_byte_class())
|
||||
return (int32)*static_cast<byte*>(mono_object_unbox(value));
|
||||
return (int16)*static_cast<byte*>(mono_object_unbox(value));
|
||||
if (klass == mono_get_sbyte_class())
|
||||
return (int32)*static_cast<int8*>(mono_object_unbox(value));
|
||||
return (int16)*static_cast<int8*>(mono_object_unbox(value));
|
||||
if (klass == mono_get_int16_class())
|
||||
return (int32)*static_cast<int16*>(mono_object_unbox(value));
|
||||
return *static_cast<int16*>(mono_object_unbox(value));
|
||||
if (klass == mono_get_uint16_class())
|
||||
return (uint32)*static_cast<uint16*>(mono_object_unbox(value));
|
||||
return *static_cast<uint16*>(mono_object_unbox(value));
|
||||
if (klass == mono_get_int32_class())
|
||||
return *static_cast<int32*>(mono_object_unbox(value));
|
||||
if (klass == mono_get_uint32_class())
|
||||
@@ -365,6 +365,10 @@ MonoObject* MUtils::BoxVariant(const Variant& value)
|
||||
return nullptr;
|
||||
case VariantType::Bool:
|
||||
return mono_value_box(mono_domain_get(), mono_get_boolean_class(), (void*)&value.AsBool);
|
||||
case VariantType::Int16:
|
||||
return mono_value_box(mono_domain_get(), mono_get_int16_class(), (void*)&value.AsInt16);
|
||||
case VariantType::Uint16:
|
||||
return mono_value_box(mono_domain_get(), mono_get_uint16_class(), (void*)&value.AsUint16);
|
||||
case VariantType::Int:
|
||||
return mono_value_box(mono_domain_get(), mono_get_int32_class(), (void*)&value.AsInt);
|
||||
case VariantType::Uint:
|
||||
@@ -534,6 +538,10 @@ MonoClass* MUtils::GetClass(const VariantType& value)
|
||||
return mono_get_void_class();
|
||||
case VariantType::Bool:
|
||||
return mono_get_boolean_class();
|
||||
case VariantType::Int16:
|
||||
return mono_get_int16_class();
|
||||
case VariantType::Uint16:
|
||||
return mono_get_uint16_class();
|
||||
case VariantType::Int:
|
||||
return mono_get_int32_class();
|
||||
case VariantType::Uint:
|
||||
@@ -600,6 +608,10 @@ MonoClass* MUtils::GetClass(const Variant& value)
|
||||
return mono_get_void_class();
|
||||
case VariantType::Bool:
|
||||
return mono_get_boolean_class();
|
||||
case VariantType::Int16:
|
||||
return mono_get_int16_class();
|
||||
case VariantType::Uint16:
|
||||
return mono_get_uint16_class();
|
||||
case VariantType::Int:
|
||||
return mono_get_int32_class();
|
||||
case VariantType::Uint:
|
||||
@@ -700,12 +712,18 @@ void* MUtils::VariantToManagedArgPtr(Variant& value, const MType& type, bool& fa
|
||||
case MONO_TYPE_CHAR:
|
||||
case MONO_TYPE_I1:
|
||||
case MONO_TYPE_I2:
|
||||
if (value.Type.Type != VariantType::Int16)
|
||||
value = (int16)value;
|
||||
return &value.AsInt16;
|
||||
case MONO_TYPE_I4:
|
||||
if (value.Type.Type != VariantType::Int)
|
||||
value = (int32)value;
|
||||
return &value.AsInt;
|
||||
case MONO_TYPE_U1:
|
||||
case MONO_TYPE_U2:
|
||||
if (value.Type.Type != VariantType::Uint16)
|
||||
value = (uint16)value;
|
||||
return &value.AsUint16;
|
||||
case MONO_TYPE_U4:
|
||||
if (value.Type.Type != VariantType::Uint)
|
||||
value = (uint32)value;
|
||||
|
||||
@@ -123,6 +123,13 @@ namespace FlaxEngine.Json
|
||||
|
||||
writer.WriteStartObject();
|
||||
{
|
||||
#if FLAX_EDITOR
|
||||
if ((serializer.TypeNameHandling & TypeNameHandling.Objects) == TypeNameHandling.Objects)
|
||||
{
|
||||
writer.WritePropertyName("$type");
|
||||
writer.WriteValue("FlaxEngine.Margin, FlaxEngine.CSharp");
|
||||
}
|
||||
#endif
|
||||
writer.WritePropertyName("Left");
|
||||
writer.WriteValue(valueMargin.Left);
|
||||
writer.WritePropertyName("Right");
|
||||
|
||||
@@ -274,6 +274,12 @@ void ReadStream::ReadVariant(Variant* data)
|
||||
case VariantType::Bool:
|
||||
data->AsBool = ReadBool();
|
||||
break;
|
||||
case VariantType::Int16:
|
||||
ReadInt16(&data->AsInt16);
|
||||
break;
|
||||
case VariantType::Uint16:
|
||||
ReadUint16(&data->AsUint16);
|
||||
break;
|
||||
case VariantType::Int:
|
||||
ReadInt32(&data->AsInt);
|
||||
break;
|
||||
@@ -573,6 +579,12 @@ void WriteStream::WriteVariant(const Variant& data)
|
||||
case VariantType::Bool:
|
||||
WriteBool(data.AsBool);
|
||||
break;
|
||||
case VariantType::Int16:
|
||||
WriteInt16(data.AsInt16);
|
||||
break;
|
||||
case VariantType::Uint16:
|
||||
WriteUint16(data.AsUint16);
|
||||
break;
|
||||
case VariantType::Int:
|
||||
WriteInt32(data.AsInt);
|
||||
break;
|
||||
|
||||
@@ -14,6 +14,12 @@ namespace FlaxEngine.GUI
|
||||
[HideInEditor]
|
||||
public GPUTexture Texture;
|
||||
|
||||
/// <summary>
|
||||
/// The texture sampling filter mode.
|
||||
/// </summary>
|
||||
[ExpandGroups, Tooltip("The texture sampling filter mode.")]
|
||||
public BrushFilter Filter = BrushFilter.Linear;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GPUTextureBrush"/> class.
|
||||
/// </summary>
|
||||
@@ -36,7 +42,10 @@ namespace FlaxEngine.GUI
|
||||
/// <inheritdoc />
|
||||
public void Draw(Rectangle rect, Color color)
|
||||
{
|
||||
Render2D.DrawTexture(Texture, rect, color);
|
||||
if (Filter == BrushFilter.Point)
|
||||
Render2D.DrawTexturePoint(Texture, rect, color);
|
||||
else
|
||||
Render2D.DrawTexture(Texture, rect, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,24 @@
|
||||
|
||||
namespace FlaxEngine.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Texture brush sampling modes.
|
||||
/// </summary>
|
||||
public enum BrushFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// The point sampling without blending.
|
||||
/// </summary>
|
||||
[Tooltip("The point sampling without blending.")]
|
||||
Point = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The linear color sampling.
|
||||
/// </summary>
|
||||
[Tooltip("The linear color sampling.")]
|
||||
Linear = 1,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Interface that unifies input source textures, sprites, render targets, and any other brushes to be used in a more generic way.
|
||||
/// </summary>
|
||||
|
||||
@@ -11,9 +11,15 @@ namespace FlaxEngine.GUI
|
||||
/// <summary>
|
||||
/// The sprite.
|
||||
/// </summary>
|
||||
[ExpandGroups]
|
||||
[ExpandGroups, EditorOrder(0), Tooltip("The sprite.")]
|
||||
public SpriteHandle Sprite;
|
||||
|
||||
/// <summary>
|
||||
/// The texture sampling filter mode.
|
||||
/// </summary>
|
||||
[ExpandGroups, EditorOrder(1), Tooltip("The texture sampling filter mode.")]
|
||||
public BrushFilter Filter = BrushFilter.Linear;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SpriteBrush"/> class.
|
||||
/// </summary>
|
||||
@@ -36,7 +42,10 @@ namespace FlaxEngine.GUI
|
||||
/// <inheritdoc />
|
||||
public void Draw(Rectangle rect, Color color)
|
||||
{
|
||||
Render2D.DrawSprite(Sprite, rect, color);
|
||||
if (Filter == BrushFilter.Point)
|
||||
Render2D.DrawSpritePoint(Sprite, rect, color);
|
||||
else
|
||||
Render2D.DrawSprite(Sprite, rect, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
|
||||
namespace FlaxEngine.GUI
|
||||
{
|
||||
/// <summary>
|
||||
@@ -11,9 +13,15 @@ namespace FlaxEngine.GUI
|
||||
/// <summary>
|
||||
/// The texture.
|
||||
/// </summary>
|
||||
[ExpandGroups, Tooltip("The texture asset.")]
|
||||
[ExpandGroups, EditorOrder(0), Tooltip("The texture asset.")]
|
||||
public Texture Texture;
|
||||
|
||||
/// <summary>
|
||||
/// The texture sampling filter mode.
|
||||
/// </summary>
|
||||
[ExpandGroups, EditorOrder(1), Tooltip("The texture sampling filter mode.")]
|
||||
public BrushFilter Filter = BrushFilter.Linear;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TextureBrush"/> class.
|
||||
/// </summary>
|
||||
@@ -36,7 +44,10 @@ namespace FlaxEngine.GUI
|
||||
/// <inheritdoc />
|
||||
public void Draw(Rectangle rect, Color color)
|
||||
{
|
||||
Render2D.DrawTexture(Texture, rect, color);
|
||||
if (Filter == BrushFilter.Point)
|
||||
Render2D.DrawTexturePoint(Texture?.Texture, rect, color);
|
||||
else
|
||||
Render2D.DrawTexture(Texture, rect, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,13 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
}
|
||||
|
||||
public void EnsureInited(Builder.BuildData buildData)
|
||||
{
|
||||
if (IsInited)
|
||||
return;
|
||||
Init(buildData);
|
||||
}
|
||||
|
||||
public virtual void Init(Builder.BuildData buildData)
|
||||
{
|
||||
IsInited = true;
|
||||
|
||||
@@ -261,7 +261,7 @@ namespace Flax.Build.Bindings
|
||||
{
|
||||
if (typeInfo == null)
|
||||
return null;
|
||||
var result = FindApiTypeInfoInner(typeInfo, caller);
|
||||
var result = FindApiTypeInfoInner(buildData, typeInfo, caller);
|
||||
if (result != null)
|
||||
return result;
|
||||
if (buildData.TypeCache.TryGetValue(typeInfo, out result))
|
||||
@@ -274,7 +274,7 @@ namespace Flax.Build.Bindings
|
||||
// Find across all loaded modules for this build
|
||||
foreach (var e in buildData.ModulesInfo)
|
||||
{
|
||||
result = FindApiTypeInfoInner(typeInfo, e.Value);
|
||||
result = FindApiTypeInfoInner(buildData, typeInfo, e.Value);
|
||||
if (result != null)
|
||||
{
|
||||
buildData.TypeCache.Add(typeInfo, result);
|
||||
@@ -291,7 +291,7 @@ namespace Flax.Build.Bindings
|
||||
{
|
||||
if (result == null)
|
||||
return null;
|
||||
result = FindApiTypeInfoInner(new TypeInfo { Type = nesting[i], }, result);
|
||||
result = FindApiTypeInfoInner(buildData, new TypeInfo { Type = nesting[i], }, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -301,14 +301,17 @@ namespace Flax.Build.Bindings
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ApiTypeInfo FindApiTypeInfoInner(TypeInfo typeInfo, ApiTypeInfo parent)
|
||||
private static ApiTypeInfo FindApiTypeInfoInner(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo parent)
|
||||
{
|
||||
foreach (var child in parent.Children)
|
||||
{
|
||||
if (child.Name == typeInfo.Type)
|
||||
{
|
||||
child.EnsureInited(buildData);
|
||||
return child;
|
||||
}
|
||||
|
||||
var result = FindApiTypeInfoInner(typeInfo, child);
|
||||
var result = FindApiTypeInfoInner(buildData, typeInfo, child);
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Flax.Build.Bindings
|
||||
private static readonly HashSet<string> CSharpUsedNamespaces = new HashSet<string>();
|
||||
private static readonly List<string> CSharpUsedNamespacesSorted = new List<string>();
|
||||
|
||||
private static readonly Dictionary<string, string> CSharpNativeToManagedBasicTypes = new Dictionary<string, string>()
|
||||
internal static readonly Dictionary<string, string> CSharpNativeToManagedBasicTypes = new Dictionary<string, string>()
|
||||
{
|
||||
// Language types
|
||||
{ "int8", "sbyte" },
|
||||
@@ -32,7 +32,7 @@ namespace Flax.Build.Bindings
|
||||
{ "double", "double" },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<string, string> CSharpNativeToManagedDefault = new Dictionary<string, string>()
|
||||
internal static readonly Dictionary<string, string> CSharpNativeToManagedDefault = new Dictionary<string, string>()
|
||||
{
|
||||
// Engine types
|
||||
{ "String", "string" },
|
||||
@@ -201,6 +201,8 @@ namespace Flax.Build.Bindings
|
||||
var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
|
||||
if (apiType != null)
|
||||
{
|
||||
CSharpUsedNamespaces.Add(apiType.Namespace);
|
||||
|
||||
if (apiType.IsScriptingObject)
|
||||
return typeInfo.Type.Replace("::", ".");
|
||||
|
||||
@@ -527,7 +529,7 @@ namespace Flax.Build.Bindings
|
||||
contents.Append("abstract ");
|
||||
contents.Append("unsafe partial class ").Append(classInfo.Name);
|
||||
if (classInfo.BaseType != null && !classInfo.IsBaseTypeHidden)
|
||||
contents.Append(" : ").Append(GenerateCSharpNativeToManaged(buildData, classInfo.BaseType, classInfo));
|
||||
contents.Append(" : ").Append(GenerateCSharpNativeToManaged(buildData, new TypeInfo { Type = classInfo.BaseType.Name }, classInfo));
|
||||
contents.AppendLine();
|
||||
contents.Append(indent + "{");
|
||||
indent += " ";
|
||||
@@ -861,7 +863,7 @@ namespace Flax.Build.Bindings
|
||||
contents.Append("private ");
|
||||
contents.Append("unsafe partial struct ").Append(structureInfo.Name);
|
||||
if (structureInfo.BaseType != null && structureInfo.IsPod)
|
||||
contents.Append(" : ").Append(GenerateCSharpNativeToManaged(buildData, structureInfo.BaseType, structureInfo));
|
||||
contents.Append(" : ").Append(GenerateCSharpNativeToManaged(buildData, new TypeInfo { Type = structureInfo.BaseType.Name }, structureInfo));
|
||||
contents.AppendLine();
|
||||
contents.Append(indent + "{");
|
||||
indent += " ";
|
||||
@@ -1048,30 +1050,6 @@ namespace Flax.Build.Bindings
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void GenerateCSharpCollectNamespaces(BuildData buildData, ApiTypeInfo apiType, HashSet<string> usedNamespaces)
|
||||
{
|
||||
if (apiType is ClassInfo classInfo)
|
||||
{
|
||||
foreach (var field in classInfo.Fields)
|
||||
{
|
||||
var fieldInfo = FindApiTypeInfo(buildData, field.Type, classInfo);
|
||||
if (fieldInfo != null && !string.IsNullOrWhiteSpace(fieldInfo.Namespace) && fieldInfo.Namespace != apiType.Namespace)
|
||||
usedNamespaces.Add(fieldInfo.Namespace);
|
||||
}
|
||||
}
|
||||
else if (apiType is StructureInfo structureInfo)
|
||||
{
|
||||
foreach (var field in structureInfo.Fields)
|
||||
{
|
||||
var fieldInfo = FindApiTypeInfo(buildData, field.Type, structureInfo);
|
||||
if (fieldInfo != null && !string.IsNullOrWhiteSpace(fieldInfo.Namespace) && fieldInfo.Namespace != apiType.Namespace)
|
||||
usedNamespaces.Add(fieldInfo.Namespace);
|
||||
}
|
||||
}
|
||||
foreach (var child in apiType.Children)
|
||||
GenerateCSharpCollectNamespaces(buildData, child, usedNamespaces);
|
||||
}
|
||||
|
||||
private static void GenerateCSharp(BuildData buildData, ModuleInfo moduleInfo, ref BindingsResult bindings)
|
||||
{
|
||||
var contents = new StringBuilder();
|
||||
@@ -1084,29 +1062,17 @@ namespace Flax.Build.Bindings
|
||||
contents.Append("true").AppendLine();
|
||||
contents.AppendLine("// This code was auto-generated. Do not modify it.");
|
||||
contents.AppendLine();
|
||||
var headerPos = contents.Length;
|
||||
|
||||
// Using declarations
|
||||
CSharpUsedNamespaces.Clear();
|
||||
CSharpUsedNamespaces.Add(null);
|
||||
CSharpUsedNamespaces.Add(string.Empty);
|
||||
CSharpUsedNamespaces.Add("System");
|
||||
CSharpUsedNamespaces.Add("System.ComponentModel");
|
||||
CSharpUsedNamespaces.Add("System.Globalization");
|
||||
CSharpUsedNamespaces.Add("System.Runtime.CompilerServices");
|
||||
CSharpUsedNamespaces.Add("System.Runtime.InteropServices");
|
||||
CSharpUsedNamespaces.Add("FlaxEngine");
|
||||
foreach (var e in moduleInfo.Children)
|
||||
{
|
||||
foreach (var apiTypeInfo in e.Children)
|
||||
{
|
||||
GenerateCSharpCollectNamespaces(buildData, apiTypeInfo, CSharpUsedNamespaces);
|
||||
}
|
||||
}
|
||||
CSharpUsedNamespacesSorted.Clear();
|
||||
CSharpUsedNamespacesSorted.AddRange(CSharpUsedNamespaces);
|
||||
CSharpUsedNamespacesSorted.Sort();
|
||||
foreach (var e in CSharpUsedNamespacesSorted)
|
||||
contents.AppendLine($"using {e};");
|
||||
// TODO: custom using declarations support
|
||||
// TODO: generate using declarations based on references modules (eg. using FlaxEngine, using Plugin1 in game API)
|
||||
|
||||
// Process all API types from the file
|
||||
var useBindings = false;
|
||||
@@ -1121,7 +1087,21 @@ namespace Flax.Build.Bindings
|
||||
if (!useBindings)
|
||||
return;
|
||||
|
||||
{
|
||||
var header = new StringBuilder();
|
||||
|
||||
// Using declarations
|
||||
CSharpUsedNamespacesSorted.Clear();
|
||||
CSharpUsedNamespacesSorted.AddRange(CSharpUsedNamespaces);
|
||||
CSharpUsedNamespacesSorted.Sort();
|
||||
for (var i = 2; i < CSharpUsedNamespacesSorted.Count; i++)
|
||||
header.AppendLine($"using {CSharpUsedNamespacesSorted[i]};");
|
||||
|
||||
contents.Insert(headerPos, header.ToString());
|
||||
}
|
||||
|
||||
// Save generated file
|
||||
contents.AppendLine();
|
||||
contents.AppendLine("#endif");
|
||||
Utilities.WriteFileIfChanged(bindings.GeneratedCSharpFilePath, contents.ToString());
|
||||
}
|
||||
|
||||
@@ -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 = 7;
|
||||
private const int CacheVersion = 8;
|
||||
|
||||
internal static void Write(BinaryWriter writer, string e)
|
||||
{
|
||||
|
||||
@@ -1095,7 +1095,7 @@ namespace Flax.Build.Bindings
|
||||
var baseType = classInfo?.BaseType ?? structureInfo?.BaseType;
|
||||
if (classInfo != null && classInfo.IsBaseTypeHidden)
|
||||
baseType = null;
|
||||
if (baseType != null && (baseType.Type == "PersistentScriptingObject" || baseType.Type == "ScriptingObject"))
|
||||
if (baseType != null && (baseType.Name == "PersistentScriptingObject" || baseType.Name == "ScriptingObject"))
|
||||
baseType = null;
|
||||
CppAutoSerializeFields.Clear();
|
||||
CppAutoSerializeProperties.Clear();
|
||||
@@ -1105,7 +1105,7 @@ namespace Flax.Build.Bindings
|
||||
contents.Append($"void {typeNameNative}::Serialize(SerializeStream& stream, const void* otherObj)").AppendLine();
|
||||
contents.Append('{').AppendLine();
|
||||
if (baseType != null)
|
||||
contents.Append($" {baseType}::Serialize(stream, otherObj);").AppendLine();
|
||||
contents.Append($" {baseType.FullNameNative}::Serialize(stream, otherObj);").AppendLine();
|
||||
contents.Append($" SERIALIZE_GET_OTHER_OBJ({typeNameNative});").AppendLine();
|
||||
|
||||
if (classInfo != null)
|
||||
@@ -1161,7 +1161,7 @@ namespace Flax.Build.Bindings
|
||||
contents.Append($"void {typeNameNative}::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)").AppendLine();
|
||||
contents.Append('{').AppendLine();
|
||||
if (baseType != null)
|
||||
contents.Append($" {baseType}::Deserialize(stream, modifier);").AppendLine();
|
||||
contents.Append($" {baseType.FullNameNative}::Deserialize(stream, modifier);").AppendLine();
|
||||
|
||||
foreach (var fieldInfo in CppAutoSerializeFields)
|
||||
{
|
||||
@@ -1554,7 +1554,7 @@ namespace Flax.Build.Bindings
|
||||
else
|
||||
contents.Append($"(ScriptingType::SpawnHandler)&{classTypeNameNative}::Spawn, ");
|
||||
if (classInfo.BaseType != null && useScripting)
|
||||
contents.Append($"&{classInfo.BaseType}::TypeInitializer, ");
|
||||
contents.Append($"&{classInfo.BaseType.FullNameNative}::TypeInitializer, ");
|
||||
else
|
||||
contents.Append("nullptr, ");
|
||||
contents.Append(setupScriptVTable);
|
||||
@@ -1566,7 +1566,7 @@ namespace Flax.Build.Bindings
|
||||
else
|
||||
contents.Append($"&{classTypeNameInternal}Internal::Ctor, &{classTypeNameInternal}Internal::Dtor, ");
|
||||
if (classInfo.BaseType != null)
|
||||
contents.Append($"&{classInfo.BaseType}::TypeInitializer");
|
||||
contents.Append($"&{classInfo.BaseType.FullNameNative}::TypeInitializer");
|
||||
else
|
||||
contents.Append("nullptr");
|
||||
}
|
||||
|
||||
@@ -416,38 +416,38 @@ namespace Flax.Build.Bindings
|
||||
token = accessToken;
|
||||
break;
|
||||
}
|
||||
|
||||
var baseTypeInfo = new TypeInfo
|
||||
var inheritType = new TypeInfo
|
||||
{
|
||||
Type = token.Value,
|
||||
};
|
||||
if (token.Value.Length > 2 && token.Value[0] == 'I' && char.IsUpper(token.Value[1]))
|
||||
{
|
||||
// Interface
|
||||
if (desc.InterfaceNames == null)
|
||||
desc.InterfaceNames = new List<TypeInfo>();
|
||||
desc.InterfaceNames.Add(baseTypeInfo);
|
||||
token = context.Tokenizer.NextToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (desc.BaseType != null)
|
||||
{
|
||||
// Allow for multiple base classes, just the first one needs to be a valid base type
|
||||
break;
|
||||
throw new Exception($"Invalid '{desc.Name}' inheritance (only single base class is allowed for scripting types, excluding interfaces).");
|
||||
}
|
||||
desc.BaseType = baseTypeInfo;
|
||||
if (desc.Inheritance == null)
|
||||
desc.Inheritance = new List<TypeInfo>();
|
||||
desc.Inheritance.Add(inheritType);
|
||||
token = context.Tokenizer.NextToken();
|
||||
if (token.Type == TokenType.LeftCurlyBrace)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (token.Type == TokenType.Colon)
|
||||
{
|
||||
token = context.Tokenizer.ExpectToken(TokenType.Colon);
|
||||
token = context.Tokenizer.NextToken();
|
||||
inheritType.Type = token.Value;
|
||||
token = context.Tokenizer.NextToken();
|
||||
continue;
|
||||
}
|
||||
if (token.Type == TokenType.DoubleColon)
|
||||
{
|
||||
token = context.Tokenizer.NextToken();
|
||||
inheritType.Type += token.Value;
|
||||
token = context.Tokenizer.NextToken();
|
||||
continue;
|
||||
}
|
||||
if (token.Type == TokenType.LeftAngleBracket)
|
||||
{
|
||||
var genericType = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
||||
token = context.Tokenizer.ExpectToken(TokenType.RightAngleBracket);
|
||||
desc.BaseType.GenericArgs = new List<TypeInfo>
|
||||
inheritType.GenericArgs = new List<TypeInfo>
|
||||
{
|
||||
new TypeInfo
|
||||
{
|
||||
@@ -456,9 +456,9 @@ namespace Flax.Build.Bindings
|
||||
};
|
||||
|
||||
// TODO: find better way to resolve this (custom base type attribute?)
|
||||
if (desc.BaseType.Type == "ShaderAssetTypeBase")
|
||||
if (inheritType.Type == "ShaderAssetTypeBase")
|
||||
{
|
||||
desc.BaseType = desc.BaseType.GenericArgs[0];
|
||||
desc.Inheritance[desc.Inheritance.Count - 1] = inheritType.GenericArgs[0];
|
||||
}
|
||||
|
||||
token = context.Tokenizer.NextToken();
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Flax.Build.NativeCpp;
|
||||
@@ -109,13 +108,6 @@ namespace Flax.Build.Bindings
|
||||
if (LoadCache(ref moduleInfo, moduleOptions, headerFiles))
|
||||
{
|
||||
buildData.ModulesInfo[module] = moduleInfo;
|
||||
|
||||
// Initialize API
|
||||
using (new ProfileEventScope("Init"))
|
||||
{
|
||||
moduleInfo.Init(buildData);
|
||||
}
|
||||
|
||||
return moduleInfo;
|
||||
}
|
||||
}
|
||||
@@ -164,12 +156,6 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize API
|
||||
using (new ProfileEventScope("Init"))
|
||||
{
|
||||
moduleInfo.Init(buildData);
|
||||
}
|
||||
|
||||
return moduleInfo;
|
||||
}
|
||||
|
||||
@@ -533,23 +519,10 @@ namespace Flax.Build.Bindings
|
||||
if (moduleInfo.IsFromCache)
|
||||
return;
|
||||
|
||||
// Process parsed API
|
||||
using (new ProfileEventScope("Process"))
|
||||
// Initialize parsed API
|
||||
using (new ProfileEventScope("Init"))
|
||||
{
|
||||
foreach (var child in moduleInfo.Children)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var apiTypeInfo in child.Children)
|
||||
ProcessAndValidate(buildData, apiTypeInfo);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (child is FileInfo fileInfo)
|
||||
Log.Error($"Failed to validate '{fileInfo.Name}' file to generate bindings.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
moduleInfo.Init(buildData);
|
||||
}
|
||||
|
||||
// Generate bindings for scripting
|
||||
@@ -583,122 +556,5 @@ namespace Flax.Build.Bindings
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessAndValidate(BuildData buildData, ApiTypeInfo apiTypeInfo)
|
||||
{
|
||||
if (apiTypeInfo is ClassInfo classInfo)
|
||||
ProcessAndValidate(buildData, classInfo);
|
||||
else if (apiTypeInfo is StructureInfo structureInfo)
|
||||
ProcessAndValidate(buildData, structureInfo);
|
||||
|
||||
foreach (var child in apiTypeInfo.Children)
|
||||
ProcessAndValidate(buildData, child);
|
||||
}
|
||||
|
||||
private static void ProcessAndValidate(BuildData buildData, ClassInfo classInfo)
|
||||
{
|
||||
if (classInfo.UniqueFunctionNames == null)
|
||||
classInfo.UniqueFunctionNames = new HashSet<string>();
|
||||
|
||||
foreach (var fieldInfo in classInfo.Fields)
|
||||
{
|
||||
if (fieldInfo.Access == AccessLevel.Private)
|
||||
continue;
|
||||
|
||||
fieldInfo.Getter = new FunctionInfo
|
||||
{
|
||||
Name = "Get" + fieldInfo.Name,
|
||||
Comment = fieldInfo.Comment,
|
||||
IsStatic = fieldInfo.IsStatic,
|
||||
Access = fieldInfo.Access,
|
||||
Attributes = fieldInfo.Attributes,
|
||||
ReturnType = fieldInfo.Type,
|
||||
Parameters = new List<FunctionInfo.ParameterInfo>(),
|
||||
IsVirtual = false,
|
||||
IsConst = true,
|
||||
Glue = new FunctionInfo.GlueInfo()
|
||||
};
|
||||
ProcessAndValidate(classInfo, fieldInfo.Getter);
|
||||
fieldInfo.Getter.Name = fieldInfo.Name;
|
||||
|
||||
if (!fieldInfo.IsReadOnly)
|
||||
{
|
||||
fieldInfo.Setter = new FunctionInfo
|
||||
{
|
||||
Name = "Set" + fieldInfo.Name,
|
||||
Comment = fieldInfo.Comment,
|
||||
IsStatic = fieldInfo.IsStatic,
|
||||
Access = fieldInfo.Access,
|
||||
Attributes = fieldInfo.Attributes,
|
||||
ReturnType = new TypeInfo
|
||||
{
|
||||
Type = "void",
|
||||
},
|
||||
Parameters = new List<FunctionInfo.ParameterInfo>
|
||||
{
|
||||
new FunctionInfo.ParameterInfo
|
||||
{
|
||||
Name = "value",
|
||||
Type = fieldInfo.Type,
|
||||
},
|
||||
},
|
||||
IsVirtual = false,
|
||||
IsConst = true,
|
||||
Glue = new FunctionInfo.GlueInfo()
|
||||
};
|
||||
ProcessAndValidate(classInfo, fieldInfo.Setter);
|
||||
fieldInfo.Setter.Name = fieldInfo.Name;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var propertyInfo in classInfo.Properties)
|
||||
{
|
||||
if (propertyInfo.Getter != null)
|
||||
ProcessAndValidate(classInfo, propertyInfo.Getter);
|
||||
if (propertyInfo.Setter != null)
|
||||
ProcessAndValidate(classInfo, propertyInfo.Setter);
|
||||
}
|
||||
|
||||
foreach (var functionInfo in classInfo.Functions)
|
||||
ProcessAndValidate(classInfo, functionInfo);
|
||||
}
|
||||
|
||||
private static void ProcessAndValidate(BuildData buildData, StructureInfo structureInfo)
|
||||
{
|
||||
foreach (var fieldInfo in structureInfo.Fields)
|
||||
{
|
||||
if (fieldInfo.Type.IsBitField)
|
||||
throw new NotImplementedException($"TODO: support bit-fields in structure fields (found field {fieldInfo} in structure {structureInfo.Name})");
|
||||
|
||||
// Pointers are fine
|
||||
if (fieldInfo.Type.IsPtr)
|
||||
continue;
|
||||
|
||||
// In-build types
|
||||
if (CSharpNativeToManagedBasicTypes.ContainsKey(fieldInfo.Type.Type))
|
||||
continue;
|
||||
if (CSharpNativeToManagedDefault.ContainsKey(fieldInfo.Type.Type))
|
||||
continue;
|
||||
|
||||
// Find API type info for this field type
|
||||
var apiType = FindApiTypeInfo(buildData, fieldInfo.Type, structureInfo);
|
||||
if (apiType != null)
|
||||
continue;
|
||||
|
||||
throw new Exception($"Unknown field type '{fieldInfo.Type} {fieldInfo.Name}' in structure '{structureInfo.Name}'.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessAndValidate(ClassInfo classInfo, FunctionInfo functionInfo)
|
||||
{
|
||||
// Ensure that methods have unique names for bindings
|
||||
if (classInfo.UniqueFunctionNames == null)
|
||||
classInfo.UniqueFunctionNames = new HashSet<string>();
|
||||
int idx = 1;
|
||||
functionInfo.UniqueName = functionInfo.Name;
|
||||
while (classInfo.UniqueFunctionNames.Contains(functionInfo.UniqueName))
|
||||
functionInfo.UniqueName = functionInfo.Name + idx++;
|
||||
classInfo.UniqueFunctionNames.Add(functionInfo.UniqueName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,22 +57,87 @@ namespace Flax.Build.Bindings
|
||||
_isScriptingObject = true;
|
||||
else if (BaseType == null)
|
||||
_isScriptingObject = false;
|
||||
else if (InBuildScriptingObjectTypes.Contains(BaseType.Type))
|
||||
else if (InBuildScriptingObjectTypes.Contains(BaseType.Name))
|
||||
_isScriptingObject = true;
|
||||
else
|
||||
_isScriptingObject = BaseType != null && BaseType.IsScriptingObject;
|
||||
|
||||
if (UniqueFunctionNames == null)
|
||||
UniqueFunctionNames = new HashSet<string>();
|
||||
|
||||
foreach (var fieldInfo in Fields)
|
||||
{
|
||||
var baseApiTypeInfo = BindingsGenerator.FindApiTypeInfo(buildData, BaseType, this);
|
||||
if (baseApiTypeInfo != null)
|
||||
if (fieldInfo.Access == AccessLevel.Private)
|
||||
continue;
|
||||
|
||||
fieldInfo.Getter = new FunctionInfo
|
||||
{
|
||||
if (!baseApiTypeInfo.IsInited)
|
||||
baseApiTypeInfo.Init(buildData);
|
||||
_isScriptingObject = baseApiTypeInfo.IsScriptingObject;
|
||||
}
|
||||
else
|
||||
Name = "Get" + fieldInfo.Name,
|
||||
Comment = fieldInfo.Comment,
|
||||
IsStatic = fieldInfo.IsStatic,
|
||||
Access = fieldInfo.Access,
|
||||
Attributes = fieldInfo.Attributes,
|
||||
ReturnType = fieldInfo.Type,
|
||||
Parameters = new List<FunctionInfo.ParameterInfo>(),
|
||||
IsVirtual = false,
|
||||
IsConst = true,
|
||||
Glue = new FunctionInfo.GlueInfo()
|
||||
};
|
||||
ProcessAndValidate(fieldInfo.Getter);
|
||||
fieldInfo.Getter.Name = fieldInfo.Name;
|
||||
|
||||
if (!fieldInfo.IsReadOnly)
|
||||
{
|
||||
_isScriptingObject = false;
|
||||
fieldInfo.Setter = new FunctionInfo
|
||||
{
|
||||
Name = "Set" + fieldInfo.Name,
|
||||
Comment = fieldInfo.Comment,
|
||||
IsStatic = fieldInfo.IsStatic,
|
||||
Access = fieldInfo.Access,
|
||||
Attributes = fieldInfo.Attributes,
|
||||
ReturnType = new TypeInfo
|
||||
{
|
||||
Type = "void",
|
||||
},
|
||||
Parameters = new List<FunctionInfo.ParameterInfo>
|
||||
{
|
||||
new FunctionInfo.ParameterInfo
|
||||
{
|
||||
Name = "value",
|
||||
Type = fieldInfo.Type,
|
||||
},
|
||||
},
|
||||
IsVirtual = false,
|
||||
IsConst = true,
|
||||
Glue = new FunctionInfo.GlueInfo()
|
||||
};
|
||||
ProcessAndValidate(fieldInfo.Setter);
|
||||
fieldInfo.Setter.Name = fieldInfo.Name;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var propertyInfo in Properties)
|
||||
{
|
||||
if (propertyInfo.Getter != null)
|
||||
ProcessAndValidate(propertyInfo.Getter);
|
||||
if (propertyInfo.Setter != null)
|
||||
ProcessAndValidate(propertyInfo.Setter);
|
||||
}
|
||||
|
||||
foreach (var functionInfo in Functions)
|
||||
ProcessAndValidate(functionInfo);
|
||||
}
|
||||
|
||||
private void ProcessAndValidate(FunctionInfo functionInfo)
|
||||
{
|
||||
// Ensure that methods have unique names for bindings
|
||||
if (UniqueFunctionNames == null)
|
||||
UniqueFunctionNames = new HashSet<string>();
|
||||
int idx = 1;
|
||||
functionInfo.UniqueName = functionInfo.Name;
|
||||
while (UniqueFunctionNames.Contains(functionInfo.UniqueName))
|
||||
functionInfo.UniqueName = functionInfo.Name + idx++;
|
||||
UniqueFunctionNames.Add(functionInfo.UniqueName);
|
||||
}
|
||||
|
||||
public override void Write(BinaryWriter writer)
|
||||
@@ -113,7 +178,7 @@ namespace Flax.Build.Bindings
|
||||
{
|
||||
if (_scriptVTableSize == -1)
|
||||
{
|
||||
if (BindingsGenerator.FindApiTypeInfo(buildData, BaseType, this) is ClassInfo baseApiTypeInfo)
|
||||
if (BaseType is ClassInfo baseApiTypeInfo)
|
||||
{
|
||||
_scriptVTableOffset = baseApiTypeInfo.GetScriptVTableSize(buildData, out _);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
@@ -12,29 +13,37 @@ namespace Flax.Build.Bindings
|
||||
{
|
||||
public AccessLevel Access;
|
||||
public AccessLevel BaseTypeInheritance;
|
||||
public TypeInfo BaseType;
|
||||
public List<InterfaceInfo> Interfaces; // Optional
|
||||
public List<TypeInfo> InterfaceNames; // Optional
|
||||
public ClassStructInfo BaseType;
|
||||
public List<InterfaceInfo> Interfaces;
|
||||
public List<TypeInfo> Inheritance; // Data from parsing, used to interfaces and base type construct in Init
|
||||
|
||||
public override void Init(Builder.BuildData buildData)
|
||||
{
|
||||
base.Init(buildData);
|
||||
|
||||
if (Interfaces == null && InterfaceNames != null && InterfaceNames.Count != 0)
|
||||
if (BaseType == null && Interfaces == null && Inheritance != null)
|
||||
{
|
||||
Interfaces = new List<InterfaceInfo>();
|
||||
for (var i = 0; i < InterfaceNames.Count; i++)
|
||||
// Extract base class and interfaces from inheritance info
|
||||
for (int i = 0; i < Inheritance.Count; i++)
|
||||
{
|
||||
var interfaceName = InterfaceNames[i];
|
||||
var apiTypeInfo = BindingsGenerator.FindApiTypeInfo(buildData, interfaceName, this);
|
||||
var apiTypeInfo = BindingsGenerator.FindApiTypeInfo(buildData, Inheritance[i], Parent);
|
||||
if (apiTypeInfo is InterfaceInfo interfaceInfo)
|
||||
{
|
||||
if (Interfaces == null)
|
||||
Interfaces = new List<InterfaceInfo>();
|
||||
Interfaces.Add(interfaceInfo);
|
||||
}
|
||||
else if (apiTypeInfo is ClassStructInfo otherInfo)
|
||||
{
|
||||
if (otherInfo == this)
|
||||
throw new Exception($"Type '{Name}' inherits from itself.");
|
||||
if (BaseType != null)
|
||||
throw new Exception($"Invalid '{Name}' inheritance (only single base class is allowed for scripting types, excluding interfaces).");
|
||||
BaseType = otherInfo;
|
||||
}
|
||||
}
|
||||
if (Interfaces.Count == 0)
|
||||
Interfaces = null;
|
||||
}
|
||||
BaseType?.EnsureInited(buildData);
|
||||
}
|
||||
|
||||
public override void Write(BinaryWriter writer)
|
||||
@@ -42,7 +51,7 @@ namespace Flax.Build.Bindings
|
||||
writer.Write((byte)Access);
|
||||
writer.Write((byte)BaseTypeInheritance);
|
||||
BindingsGenerator.Write(writer, BaseType);
|
||||
BindingsGenerator.Write(writer, InterfaceNames);
|
||||
BindingsGenerator.Write(writer, Inheritance);
|
||||
|
||||
base.Write(writer);
|
||||
}
|
||||
@@ -52,7 +61,7 @@ namespace Flax.Build.Bindings
|
||||
Access = (AccessLevel)reader.ReadByte();
|
||||
BaseTypeInheritance = (AccessLevel)reader.ReadByte();
|
||||
BaseType = BindingsGenerator.Read(reader, BaseType);
|
||||
InterfaceNames = BindingsGenerator.Read(reader, InterfaceNames);
|
||||
Inheritance = BindingsGenerator.Read(reader, Inheritance);
|
||||
|
||||
base.Read(reader);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,19 @@ namespace Flax.Build.Bindings
|
||||
base.AddChild(apiTypeInfo);
|
||||
}
|
||||
|
||||
public override void Init(Builder.BuildData buildData)
|
||||
{
|
||||
try
|
||||
{
|
||||
base.Init(buildData);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Log.Error($"Failed to init '{Name}' file scripting API.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public int CompareTo(FileInfo other)
|
||||
{
|
||||
return Name.CompareTo(other.Name);
|
||||
|
||||
@@ -26,14 +26,14 @@ namespace Flax.Build.Bindings
|
||||
{
|
||||
base.Init(buildData);
|
||||
|
||||
if (ForceNoPod || (InterfaceNames != null && InterfaceNames.Count != 0))
|
||||
if (ForceNoPod || (Interfaces != null && Interfaces.Count != 0))
|
||||
{
|
||||
_isPod = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Structure is POD (plain old data) only if all of it's fields are (and has no base type ro base type is also POD)
|
||||
_isPod = BaseType == null || (BindingsGenerator.FindApiTypeInfo(buildData, BaseType, Parent)?.IsPod ?? false);
|
||||
_isPod = BaseType == null || (BaseType?.IsPod ?? false);
|
||||
for (int i = 0; _isPod && i < Fields.Count; i++)
|
||||
{
|
||||
var field = Fields[i];
|
||||
@@ -42,6 +42,29 @@ namespace Flax.Build.Bindings
|
||||
_isPod = false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var fieldInfo in Fields)
|
||||
{
|
||||
if (fieldInfo.Type.IsBitField)
|
||||
throw new NotImplementedException($"TODO: support bit-fields in structure fields (found field {fieldInfo} in structure {Name})");
|
||||
|
||||
// Pointers are fine
|
||||
if (fieldInfo.Type.IsPtr)
|
||||
continue;
|
||||
|
||||
// In-build types
|
||||
if (BindingsGenerator.CSharpNativeToManagedBasicTypes.ContainsKey(fieldInfo.Type.Type))
|
||||
continue;
|
||||
if (BindingsGenerator.CSharpNativeToManagedDefault.ContainsKey(fieldInfo.Type.Type))
|
||||
continue;
|
||||
|
||||
// Find API type info for this field type
|
||||
var apiType = BindingsGenerator.FindApiTypeInfo(buildData, fieldInfo.Type, this);
|
||||
if (apiType != null)
|
||||
continue;
|
||||
|
||||
throw new Exception($"Unknown field type '{fieldInfo.Type} {fieldInfo.Name}' in structure '{Name}'.");
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(BinaryWriter writer)
|
||||
|
||||
@@ -36,8 +36,7 @@ namespace Flax.Build.Bindings
|
||||
var apiType = BindingsGenerator.FindApiTypeInfo(buildData, this, caller);
|
||||
if (apiType != null)
|
||||
{
|
||||
if (!apiType.IsInited)
|
||||
apiType.Init(buildData);
|
||||
apiType.EnsureInited(buildData);
|
||||
return apiType.IsPod;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,22 +46,35 @@ namespace Flax.Build
|
||||
var outputPath = Path.GetDirectoryName(buildData.Target.GetOutputFilePath(buildOptions));
|
||||
var outputFile = Path.Combine(outputPath, binaryModuleName + ".CSharp.dll");
|
||||
var outputDocFile = Path.Combine(outputPath, binaryModuleName + ".CSharp.xml");
|
||||
string monoRoot, exePath;
|
||||
string monoRoot, monoPath, cscPath;
|
||||
switch (buildPlatform)
|
||||
{
|
||||
case TargetPlatform.Windows:
|
||||
{
|
||||
monoRoot = Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Editor", "Windows", "Mono");
|
||||
exePath = Path.Combine(monoRoot, "bin", "mono.exe");
|
||||
|
||||
// Prefer installed Roslyn C# compiler over Mono one
|
||||
monoPath = null;
|
||||
cscPath = Path.Combine(Path.GetDirectoryName(Deploy.VCEnvironment.MSBuildPath), "Roslyn", "csc.exe");
|
||||
|
||||
if (!File.Exists(cscPath))
|
||||
{
|
||||
// Fallback to Mono binaries
|
||||
monoPath = Path.Combine(monoRoot, "bin", "mono.exe");
|
||||
cscPath = Path.Combine(monoRoot, "lib", "mono", "4.5", "csc.exe");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TargetPlatform.Linux:
|
||||
monoRoot = Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Editor", "Linux", "Mono");
|
||||
exePath = Path.Combine(monoRoot, "bin", "mono");
|
||||
monoPath = Path.Combine(monoRoot, "bin", "mono");
|
||||
cscPath = Path.Combine(monoRoot, "lib", "mono", "4.5", "csc.exe");
|
||||
break;
|
||||
default: throw new InvalidPlatformException(buildPlatform);
|
||||
}
|
||||
var cscPath = Path.Combine(monoRoot, "lib", "mono", "4.5", "csc.exe");
|
||||
var referenceAssemblies = Path.Combine(monoRoot, "lib", "mono", "4.5-api");
|
||||
var references = new HashSet<string>(buildOptions.ScriptingAPI.FileReferences);
|
||||
|
||||
foreach (var module in binaryModule)
|
||||
{
|
||||
if (!buildData.Modules.TryGetValue(module, out var moduleBuildOptions))
|
||||
@@ -147,11 +160,23 @@ namespace Flax.Build
|
||||
task.PrerequisiteFiles.AddRange(references);
|
||||
task.ProducedFiles.Add(outputFile);
|
||||
task.WorkingDirectory = workspaceRoot;
|
||||
task.CommandPath = exePath;
|
||||
task.CommandArguments = $"\"{cscPath}\" /noconfig @\"{responseFile}\"";
|
||||
task.InfoMessage = "Compiling " + outputFile;
|
||||
task.Cost = task.PrerequisiteFiles.Count;
|
||||
|
||||
if (monoPath != null)
|
||||
{
|
||||
task.CommandPath = monoPath;
|
||||
task.CommandArguments = $"\"{cscPath}\" /noconfig @\"{responseFile}\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
// The "/shared" flag enables the compiler server support:
|
||||
// https://github.com/dotnet/roslyn/blob/main/docs/compilers/Compiler%20Server.md
|
||||
|
||||
task.CommandPath = cscPath;
|
||||
task.CommandArguments = $"/noconfig /shared @\"{responseFile}\"";
|
||||
}
|
||||
|
||||
// Copy referenced assemblies
|
||||
foreach (var reference in buildOptions.ScriptingAPI.FileReferences)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,12 @@ namespace Flax.Build
|
||||
{
|
||||
public static partial class Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// Package deployment output path.
|
||||
/// </summary>
|
||||
[CommandLine("deployOutput", "Package deployment output path.")]
|
||||
public static string DeployOutput;
|
||||
|
||||
/// <summary>
|
||||
/// Builds and packages the editor.
|
||||
/// </summary>
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Flax.Deploy
|
||||
public static int VersionMajor;
|
||||
public static int VersionMinor;
|
||||
public static int VersionBuild;
|
||||
public static TargetConfiguration[] Configurations;
|
||||
|
||||
public static bool Run()
|
||||
{
|
||||
@@ -64,6 +65,8 @@ namespace Flax.Deploy
|
||||
|
||||
static void Initialize()
|
||||
{
|
||||
Configurations = Configuration.BuildConfigurations != null ? Configuration.BuildConfigurations : new[] { TargetConfiguration.Debug, TargetConfiguration.Development, TargetConfiguration.Release };
|
||||
|
||||
// Read the current engine version
|
||||
var engineVersion = EngineTarget.EngineVersion;
|
||||
VersionMajor = engineVersion.Major;
|
||||
@@ -81,9 +84,12 @@ namespace Flax.Deploy
|
||||
Utilities.WriteFileIfChanged(Path.Combine(Globals.EngineRoot, "Source/Engine/Core/Config.Gen.h"), buildConfigHeader.ToString());
|
||||
|
||||
// Prepare the package output
|
||||
PackageOutputPath = Path.Combine(Globals.EngineRoot, string.Format("Package_{0}_{1:00}_{2:00000}", VersionMajor, VersionMinor, VersionBuild));
|
||||
Utilities.DirectoryDelete(PackageOutputPath);
|
||||
Directory.CreateDirectory(PackageOutputPath);
|
||||
if (string.IsNullOrEmpty(Configuration.DeployOutput))
|
||||
PackageOutputPath = Path.Combine(Globals.EngineRoot, string.Format("Package_{0}_{1:00}_{2:00000}", VersionMajor, VersionMinor, VersionBuild));
|
||||
else
|
||||
PackageOutputPath = Configuration.DeployOutput;
|
||||
if (!Directory.Exists(PackageOutputPath))
|
||||
Directory.CreateDirectory(PackageOutputPath);
|
||||
|
||||
Log.Info(string.Empty);
|
||||
Log.Info(string.Empty);
|
||||
@@ -104,9 +110,10 @@ namespace Flax.Deploy
|
||||
private static void BuildEditor()
|
||||
{
|
||||
var targetPlatform = Platform.BuildPlatform.Target;
|
||||
FlaxBuild.Build(Globals.EngineRoot, "FlaxEditor", targetPlatform, TargetArchitecture.x64, TargetConfiguration.Debug);
|
||||
FlaxBuild.Build(Globals.EngineRoot, "FlaxEditor", targetPlatform, TargetArchitecture.x64, TargetConfiguration.Development);
|
||||
FlaxBuild.Build(Globals.EngineRoot, "FlaxEditor", targetPlatform, TargetArchitecture.x64, TargetConfiguration.Release);
|
||||
foreach (var configuration in Configurations)
|
||||
{
|
||||
FlaxBuild.Build(Globals.EngineRoot, "FlaxEditor", targetPlatform, TargetArchitecture.x64, configuration);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CannotBuildPlatform(TargetPlatform platform)
|
||||
@@ -129,9 +136,10 @@ namespace Flax.Deploy
|
||||
{
|
||||
if (Platform.IsPlatformSupported(platform, architecture))
|
||||
{
|
||||
FlaxBuild.Build(Globals.EngineRoot, "FlaxGame", platform, architecture, TargetConfiguration.Debug);
|
||||
FlaxBuild.Build(Globals.EngineRoot, "FlaxGame", platform, architecture, TargetConfiguration.Development);
|
||||
FlaxBuild.Build(Globals.EngineRoot, "FlaxGame", platform, architecture, TargetConfiguration.Release);
|
||||
foreach (var configuration in Configurations)
|
||||
{
|
||||
FlaxBuild.Build(Globals.EngineRoot, "FlaxGame", platform, architecture, configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,15 +34,15 @@ namespace Flax.Deploy
|
||||
// Prepare
|
||||
RootPath = Globals.EngineRoot;
|
||||
OutputPath = Path.Combine(Deployer.PackageOutputPath, "Editor");
|
||||
Utilities.DirectoryDelete(OutputPath);
|
||||
Directory.CreateDirectory(OutputPath);
|
||||
Log.Info(string.Empty);
|
||||
Log.Info("Deploy editor files");
|
||||
Log.Info(string.Empty);
|
||||
|
||||
// Deploy binaries
|
||||
DeployEditorBinaries(TargetConfiguration.Debug);
|
||||
DeployEditorBinaries(TargetConfiguration.Development);
|
||||
DeployEditorBinaries(TargetConfiguration.Release);
|
||||
foreach (var configuration in Deployer.Configurations)
|
||||
DeployEditorBinaries(configuration);
|
||||
{
|
||||
var binariesSubDir = "Binaries/Tools";
|
||||
var src = Path.Combine(RootPath, binariesSubDir);
|
||||
@@ -130,12 +130,14 @@ namespace Flax.Deploy
|
||||
{
|
||||
// Use system tool (preserves executable file attributes and link files)
|
||||
editorPackageZipPath = Path.Combine(Deployer.PackageOutputPath, "FlaxEditorLinux.zip");
|
||||
Utilities.FileDelete(editorPackageZipPath);
|
||||
Utilities.Run("zip", "Editor.zip -r .", null, OutputPath, Utilities.RunOptions.None);
|
||||
File.Move(Path.Combine(OutputPath, "Editor.zip"), editorPackageZipPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
editorPackageZipPath = Path.Combine(Deployer.PackageOutputPath, "Editor.zip");
|
||||
Utilities.FileDelete(editorPackageZipPath);
|
||||
using (ZipFile zip = new ZipFile())
|
||||
{
|
||||
zip.AddDirectory(OutputPath);
|
||||
@@ -152,6 +154,7 @@ namespace Flax.Deploy
|
||||
{
|
||||
Log.Info("Compressing editor debug symbols files...");
|
||||
editorPackageZipPath = Path.Combine(Deployer.PackageOutputPath, "EditorDebugSymbols.zip");
|
||||
Utilities.FileDelete(editorPackageZipPath);
|
||||
using (ZipFile zip = new ZipFile())
|
||||
{
|
||||
zip.AddDirectory(Path.Combine(Deployer.PackageOutputPath, "EditorDebugSymbols"));
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Flax.Deploy
|
||||
string platformName = platform.ToString();
|
||||
string src = Path.Combine(platformsRoot, platformName);
|
||||
string dst = Path.Combine(Deployer.PackageOutputPath, platformName);
|
||||
Utilities.DirectoryDelete(dst);
|
||||
|
||||
// Deploy files
|
||||
{
|
||||
@@ -69,6 +70,7 @@ namespace Flax.Deploy
|
||||
Log.Info("Compressing platform files...");
|
||||
|
||||
var packageZipPath = Path.Combine(Deployer.PackageOutputPath, platformName + ".zip");
|
||||
Utilities.FileDelete(packageZipPath);
|
||||
using (ZipFile zip = new ZipFile())
|
||||
{
|
||||
zip.AddDirectory(dst);
|
||||
|
||||
Reference in New Issue
Block a user