Merge remote-tracking branch 'origin/1.5' into dotnet7
This commit is contained in:
BIN
Content/Engine/Textures/DefaultLensDirt.flax
(Stored with Git LFS)
BIN
Content/Engine/Textures/DefaultLensDirt.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Engine/Textures/DefaultLensStarburst.flax
(Stored with Git LFS)
BIN
Content/Engine/Textures/DefaultLensStarburst.flax
(Stored with Git LFS)
Binary file not shown.
@@ -11,7 +11,10 @@ namespace FlaxEditor.Content
|
|||||||
/// <seealso cref="FlaxEditor.Content.AssetItem" />
|
/// <seealso cref="FlaxEditor.Content.AssetItem" />
|
||||||
public class JsonAssetItem : AssetItem
|
public class JsonAssetItem : AssetItem
|
||||||
{
|
{
|
||||||
private readonly SpriteHandle _thumbnail;
|
/// <summary>
|
||||||
|
/// Asset icon.
|
||||||
|
/// </summary>
|
||||||
|
protected SpriteHandle _thumbnail;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="JsonAssetItem"/> class.
|
/// Initializes a new instance of the <see cref="JsonAssetItem"/> class.
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ namespace FlaxEditor.Content
|
|||||||
/// Generic Json assets proxy (supports all json assets that don't have dedicated proxy).
|
/// Generic Json assets proxy (supports all json assets that don't have dedicated proxy).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
|
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
|
||||||
public sealed class GenericJsonAssetProxy : JsonAssetProxy
|
public class GenericJsonAssetProxy : JsonAssetProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string TypeName => typeof(JsonAsset).FullName;
|
public override string TypeName => typeof(JsonAsset).FullName;
|
||||||
@@ -161,7 +161,7 @@ namespace FlaxEditor.Content
|
|||||||
/// Content proxy for a json assets of the given type that can be spawned in the editor.
|
/// Content proxy for a json assets of the given type that can be spawned in the editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.JsonAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.JsonAssetProxy" />
|
||||||
public sealed class SpawnableJsonAssetProxy<T> : JsonAssetProxy where T : new()
|
public class SpawnableJsonAssetProxy<T> : JsonAssetProxy where T : new()
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string Name { get; } = Utilities.Utils.GetPropertyNameUI(typeof(T).Name);
|
public override string Name { get; } = Utilities.Utils.GetPropertyNameUI(typeof(T).Name);
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
{
|
{
|
||||||
if (Values[0] is Tag asTag)
|
if (Values[0] is Tag asTag)
|
||||||
return asTag;
|
return asTag;
|
||||||
if (Values[0] is int asInt)
|
if (Values[0] is uint asUInt)
|
||||||
return new Tag(asInt);
|
return new Tag(asUInt);
|
||||||
if (Values[0] is string asString)
|
if (Values[0] is string asString)
|
||||||
return Tags.Get(asString);
|
return Tags.Get(asString);
|
||||||
return Tag.Default;
|
return Tag.Default;
|
||||||
@@ -65,7 +65,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
{
|
{
|
||||||
if (Values[0] is Tag)
|
if (Values[0] is Tag)
|
||||||
SetValue(value);
|
SetValue(value);
|
||||||
if (Values[0] is int)
|
if (Values[0] is uint)
|
||||||
SetValue(value.Index);
|
SetValue(value.Index);
|
||||||
else if (Values[0] is string)
|
else if (Values[0] is string)
|
||||||
SetValue(value.ToString());
|
SetValue(value.ToString());
|
||||||
@@ -114,7 +114,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
private static void GetTags(TreeNode n, PickerData pickerData)
|
private static void GetTags(TreeNode n, PickerData pickerData)
|
||||||
{
|
{
|
||||||
if (n is TreeNodeWithAddons a && a.Addons.Count != 0 && a.Addons[0] is CheckBox c && c.Checked)
|
if (n is TreeNodeWithAddons a && a.Addons.Count != 0 && a.Addons[0] is CheckBox c && c.Checked)
|
||||||
pickerData.CachedTags.Add(new Tag((int)n.Tag));
|
pickerData.CachedTags.Add((Tag)n.Tag);
|
||||||
foreach (var child in n.Children)
|
foreach (var child in n.Children)
|
||||||
{
|
{
|
||||||
if (child is TreeNode treeNode)
|
if (child is TreeNode treeNode)
|
||||||
@@ -139,7 +139,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
if (pickerData.IsSingle)
|
if (pickerData.IsSingle)
|
||||||
{
|
{
|
||||||
UncheckAll(node.ParentTree, node);
|
UncheckAll(node.ParentTree, node);
|
||||||
var value = new Tag(c.Checked ? (int)node.Tag : -1);
|
var value = c.Checked ? (Tag)node.Tag : Tag.Default;
|
||||||
pickerData.SetValue?.Invoke(value);
|
pickerData.SetValue?.Invoke(value);
|
||||||
pickerData.SetValues?.Invoke(new[] { value });
|
pickerData.SetValues?.Invoke(new[] { value });
|
||||||
}
|
}
|
||||||
@@ -166,8 +166,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
if (parentNode.CustomArrowRect.HasValue)
|
if (parentNode.CustomArrowRect.HasValue)
|
||||||
{
|
{
|
||||||
indentation = (int)((parentNode.CustomArrowRect.Value.Location.X - 18) / nodeIndent) + 1;
|
indentation = (int)((parentNode.CustomArrowRect.Value.Location.X - 18) / nodeIndent) + 1;
|
||||||
var parentIndex = (int)parentNode.Tag;
|
var parentTagValue = (Tag)parentNode.Tag;
|
||||||
parentTag = Tags.List[parentIndex];
|
parentTag = parentTagValue.ToString();
|
||||||
}
|
}
|
||||||
var node = new TreeNodeWithAddons
|
var node = new TreeNodeWithAddons
|
||||||
{
|
{
|
||||||
@@ -244,7 +244,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
// Add tag
|
// Add tag
|
||||||
var tag = Tags.Get(tagName);
|
var tag = Tags.Get(tagName);
|
||||||
node.Text = name;
|
node.Text = name;
|
||||||
node.Tag = tag.Index;
|
node.Tag = tag;
|
||||||
var settingsAsset = GameSettings.LoadAsset<LayersAndTagsSettings>();
|
var settingsAsset = GameSettings.LoadAsset<LayersAndTagsSettings>();
|
||||||
if (settingsAsset && !settingsAsset.WaitForLoaded())
|
if (settingsAsset && !settingsAsset.WaitForLoaded())
|
||||||
{
|
{
|
||||||
@@ -283,7 +283,8 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
for (var i = 0; i < tags.Length; i++)
|
for (var i = 0; i < tags.Length; i++)
|
||||||
{
|
{
|
||||||
var tag = tags[i];
|
var tag = tags[i];
|
||||||
bool isSelected = pickerData.IsSingle ? value.Index == i : values.Contains(new Tag(i));
|
var tagValue = new Tag((uint)(i + 1));
|
||||||
|
bool isSelected = pickerData.IsSingle ? value == tagValue : values.Contains(tagValue);
|
||||||
|
|
||||||
// Count parent tags count
|
// Count parent tags count
|
||||||
int indentation = 0;
|
int indentation = 0;
|
||||||
@@ -296,7 +297,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
// Create node
|
// Create node
|
||||||
var node = new TreeNodeWithAddons
|
var node = new TreeNodeWithAddons
|
||||||
{
|
{
|
||||||
Tag = i,
|
Tag = tagValue,
|
||||||
Text = tag,
|
Text = tag,
|
||||||
ChildrenIndent = nodeIndent,
|
ChildrenIndent = nodeIndent,
|
||||||
CullChildren = false,
|
CullChildren = false,
|
||||||
|
|||||||
@@ -1205,6 +1205,7 @@ namespace FlaxEditor
|
|||||||
{
|
{
|
||||||
public byte AutoReloadScriptsOnMainWindowFocus;
|
public byte AutoReloadScriptsOnMainWindowFocus;
|
||||||
public byte ForceScriptCompilationOnStartup;
|
public byte ForceScriptCompilationOnStartup;
|
||||||
|
public byte UseAssetImportPathRelative;
|
||||||
public byte AutoRebuildCSG;
|
public byte AutoRebuildCSG;
|
||||||
public float AutoRebuildCSGTimeoutMs;
|
public float AutoRebuildCSGTimeoutMs;
|
||||||
public byte AutoRebuildNavMesh;
|
public byte AutoRebuildNavMesh;
|
||||||
|
|||||||
@@ -356,10 +356,15 @@ namespace FlaxEditor.GUI.ContextMenu
|
|||||||
|
|
||||||
private void OnWindowGotFocus()
|
private void OnWindowGotFocus()
|
||||||
{
|
{
|
||||||
if (_childCM != null && _window && _window.IsForegroundWindow)
|
var child = _childCM;
|
||||||
|
if (child != null && _window && _window.IsForegroundWindow)
|
||||||
{
|
{
|
||||||
// Hide child if user clicked over parent (do it next frame to process other events before - eg. child windows focus loss)
|
// Hide child if user clicked over parent (do it next frame to process other events before - eg. child windows focus loss)
|
||||||
FlaxEngine.Scripting.InvokeOnUpdate(HideChild);
|
FlaxEngine.Scripting.InvokeOnUpdate(() =>
|
||||||
|
{
|
||||||
|
if (child == _childCM)
|
||||||
|
HideChild();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -830,6 +830,9 @@ public:
|
|||||||
{
|
{
|
||||||
SCRIPTING_EXPORT("FlaxEditor.Editor::Internal_SetOptions")
|
SCRIPTING_EXPORT("FlaxEditor.Editor::Internal_SetOptions")
|
||||||
ManagedEditor::ManagedEditorOptions = *options;
|
ManagedEditor::ManagedEditorOptions = *options;
|
||||||
|
|
||||||
|
// Apply options
|
||||||
|
AssetsImportingManager::UseImportPathRelative = ManagedEditor::ManagedEditorOptions.UseAssetImportPathRelative != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawNavMesh()
|
static void DrawNavMesh()
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ public:
|
|||||||
{
|
{
|
||||||
byte AutoReloadScriptsOnMainWindowFocus = 1;
|
byte AutoReloadScriptsOnMainWindowFocus = 1;
|
||||||
byte ForceScriptCompilationOnStartup = 1;
|
byte ForceScriptCompilationOnStartup = 1;
|
||||||
|
byte UseAssetImportPathRelative = 1;
|
||||||
byte AutoRebuildCSG = 1;
|
byte AutoRebuildCSG = 1;
|
||||||
float AutoRebuildCSGTimeoutMs = 50;
|
float AutoRebuildCSGTimeoutMs = 50;
|
||||||
byte AutoRebuildNavMesh = 1;
|
byte AutoRebuildNavMesh = 1;
|
||||||
|
|||||||
@@ -148,6 +148,13 @@ namespace FlaxEditor.Options
|
|||||||
[EditorDisplay("Scripting", "Auto Save Visual Script On Play Start"), EditorOrder(505), Tooltip("Determines whether automatically save the Visual Script asset editors when starting the play mode in editor.")]
|
[EditorDisplay("Scripting", "Auto Save Visual Script On Play Start"), EditorOrder(505), Tooltip("Determines whether automatically save the Visual Script asset editors when starting the play mode in editor.")]
|
||||||
public bool AutoSaveVisualScriptOnPlayStart { get; set; } = true;
|
public bool AutoSaveVisualScriptOnPlayStart { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If checked, imported file path will be stored relative to the project folder within imported asset metadata. Otherwise will use absolute path.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(true)]
|
||||||
|
[EditorDisplay("Content"), EditorOrder(550)]
|
||||||
|
public bool UseAssetImportPathRelative { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether perform automatic CSG rebuild on brush change.
|
/// Gets or sets a value indicating whether perform automatic CSG rebuild on brush change.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -186,6 +186,7 @@ namespace FlaxEditor.Options
|
|||||||
Editor.InternalOptions internalOptions;
|
Editor.InternalOptions internalOptions;
|
||||||
internalOptions.AutoReloadScriptsOnMainWindowFocus = (byte)(Options.General.AutoReloadScriptsOnMainWindowFocus ? 1 : 0);
|
internalOptions.AutoReloadScriptsOnMainWindowFocus = (byte)(Options.General.AutoReloadScriptsOnMainWindowFocus ? 1 : 0);
|
||||||
internalOptions.ForceScriptCompilationOnStartup = (byte)(Options.General.ForceScriptCompilationOnStartup ? 1 : 0);
|
internalOptions.ForceScriptCompilationOnStartup = (byte)(Options.General.ForceScriptCompilationOnStartup ? 1 : 0);
|
||||||
|
internalOptions.UseAssetImportPathRelative = (byte)(Options.General.UseAssetImportPathRelative ? 1 : 0);
|
||||||
internalOptions.AutoRebuildCSG = (byte)(Options.General.AutoRebuildCSG ? 1 : 0);
|
internalOptions.AutoRebuildCSG = (byte)(Options.General.AutoRebuildCSG ? 1 : 0);
|
||||||
internalOptions.AutoRebuildCSGTimeoutMs = Options.General.AutoRebuildCSGTimeoutMs;
|
internalOptions.AutoRebuildCSGTimeoutMs = Options.General.AutoRebuildCSGTimeoutMs;
|
||||||
internalOptions.AutoRebuildNavMesh = (byte)(Options.General.AutoRebuildNavMesh ? 1 : 0);
|
internalOptions.AutoRebuildNavMesh = (byte)(Options.General.AutoRebuildNavMesh ? 1 : 0);
|
||||||
|
|||||||
@@ -119,7 +119,8 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = IntegerValue.Get(box.ParentNode, box.Archetype, box.Value);
|
var value = IntegerValue.Get(box.ParentNode, box.Archetype, box.Value);
|
||||||
var control = new IntValueBox(value, bounds.X, bounds.Y, 40, int.MinValue, int.MaxValue, 0.01f)
|
var width = 40;
|
||||||
|
var control = new IntValueBox(value, bounds.X, bounds.Y, width + 12, int.MinValue, int.MaxValue, 0.01f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
@@ -164,7 +165,8 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = UnsignedIntegerValue.Get(box.ParentNode, box.Archetype, box.Value);
|
var value = UnsignedIntegerValue.Get(box.ParentNode, box.Archetype, box.Value);
|
||||||
var control = new UIntValueBox(value, bounds.X, bounds.Y, 40, uint.MinValue, uint.MaxValue, 0.01f)
|
var width = 40;
|
||||||
|
var control = new UIntValueBox(value, bounds.X, bounds.Y, width + 12, uint.MinValue, uint.MaxValue, 0.01f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
@@ -209,7 +211,8 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = FloatValue.Get(box.ParentNode, box.Archetype, box.Value);
|
var value = FloatValue.Get(box.ParentNode, box.Archetype, box.Value);
|
||||||
var control = new FloatValueBox(value, bounds.X, bounds.Y, 40, float.MinValue, float.MaxValue, 0.01f)
|
var width = 40;
|
||||||
|
var control = new FloatValueBox(value, bounds.X, bounds.Y, width + 12, float.MinValue, float.MaxValue, 0.01f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
@@ -254,7 +257,7 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = box.Value as string;
|
var value = box.Value as string;
|
||||||
var control = new TextBox(false, bounds.X, bounds.Y, 40)
|
var control = new TextBox(false, bounds.X, bounds.Y, 50)
|
||||||
{
|
{
|
||||||
Text = value,
|
Text = value,
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
@@ -299,20 +302,21 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = GetValue(box);
|
var value = GetValue(box);
|
||||||
var control = new ContainerControl(bounds.X, bounds.Y, 22 * 2 - 2, bounds.Height)
|
var width = 30;
|
||||||
|
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 2 - 2, bounds.Height)
|
||||||
{
|
{
|
||||||
ClipChildren = false,
|
ClipChildren = false,
|
||||||
AutoFocus = false,
|
AutoFocus = false,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
Tag = box,
|
Tag = box,
|
||||||
};
|
};
|
||||||
var floatX = new RealValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatX = new RealValueBox(value.X, 0, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatX.BoxValueChanged += OnValueChanged;
|
floatX.BoxValueChanged += OnValueChanged;
|
||||||
var floatY = new RealValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatY = new RealValueBox(value.Y, width + 2, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
@@ -372,26 +376,27 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = GetValue(box);
|
var value = GetValue(box);
|
||||||
var control = new ContainerControl(bounds.X, bounds.Y, 22 * 3 - 2, bounds.Height)
|
var width = 30;
|
||||||
|
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 3 - 2, bounds.Height)
|
||||||
{
|
{
|
||||||
ClipChildren = false,
|
ClipChildren = false,
|
||||||
AutoFocus = false,
|
AutoFocus = false,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
Tag = box,
|
Tag = box,
|
||||||
};
|
};
|
||||||
var floatX = new RealValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatX = new RealValueBox(value.X, 0, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatX.BoxValueChanged += OnValueChanged;
|
floatX.BoxValueChanged += OnValueChanged;
|
||||||
var floatY = new RealValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatY = new RealValueBox(value.Y, width + 2, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatY.BoxValueChanged += OnValueChanged;
|
floatY.BoxValueChanged += OnValueChanged;
|
||||||
var floatZ = new RealValueBox(value.Z, 44, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatZ = new RealValueBox(value.Z, width * 2 + 4, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
@@ -454,32 +459,33 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = GetValue(box);
|
var value = GetValue(box);
|
||||||
var control = new ContainerControl(bounds.X, bounds.Y, 22 * 4 - 2, bounds.Height)
|
var width = 20;
|
||||||
|
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 4 - 2, bounds.Height)
|
||||||
{
|
{
|
||||||
ClipChildren = false,
|
ClipChildren = false,
|
||||||
AutoFocus = false,
|
AutoFocus = false,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
Tag = box,
|
Tag = box,
|
||||||
};
|
};
|
||||||
var floatX = new RealValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatX = new RealValueBox(value.X, 0, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatX.BoxValueChanged += OnValueChanged;
|
floatX.BoxValueChanged += OnValueChanged;
|
||||||
var floatY = new RealValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatY = new RealValueBox(value.Y, width + 2, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatY.BoxValueChanged += OnValueChanged;
|
floatY.BoxValueChanged += OnValueChanged;
|
||||||
var floatZ = new RealValueBox(value.Z, 44, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatZ = new RealValueBox(value.Z, width * 2 + 4, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatZ.BoxValueChanged += OnValueChanged;
|
floatZ.BoxValueChanged += OnValueChanged;
|
||||||
var floatW = new RealValueBox(value.W, 66, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatW = new RealValueBox(value.W, width * 3 + 6, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
@@ -546,20 +552,21 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = GetValue(box);
|
var value = GetValue(box);
|
||||||
var control = new ContainerControl(bounds.X, bounds.Y, 22 * 2 - 2, bounds.Height)
|
var width = 30;
|
||||||
|
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 2 - 2, bounds.Height)
|
||||||
{
|
{
|
||||||
ClipChildren = false,
|
ClipChildren = false,
|
||||||
AutoFocus = false,
|
AutoFocus = false,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
Tag = box,
|
Tag = box,
|
||||||
};
|
};
|
||||||
var floatX = new FloatValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatX = new FloatValueBox(value.X, 0, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatX.BoxValueChanged += OnValueChanged;
|
floatX.BoxValueChanged += OnValueChanged;
|
||||||
var floatY = new FloatValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatY = new FloatValueBox(value.Y, width + 2, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
@@ -619,26 +626,27 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = GetValue(box);
|
var value = GetValue(box);
|
||||||
var control = new ContainerControl(bounds.X, bounds.Y, 22 * 3 - 2, bounds.Height)
|
var width = 30;
|
||||||
|
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 3 - 2, bounds.Height)
|
||||||
{
|
{
|
||||||
ClipChildren = false,
|
ClipChildren = false,
|
||||||
AutoFocus = false,
|
AutoFocus = false,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
Tag = box,
|
Tag = box,
|
||||||
};
|
};
|
||||||
var floatX = new FloatValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatX = new FloatValueBox(value.X, 0, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatX.BoxValueChanged += OnValueChanged;
|
floatX.BoxValueChanged += OnValueChanged;
|
||||||
var floatY = new FloatValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatY = new FloatValueBox(value.Y, width + 2, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatY.BoxValueChanged += OnValueChanged;
|
floatY.BoxValueChanged += OnValueChanged;
|
||||||
var floatZ = new FloatValueBox(value.Z, 44, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatZ = new FloatValueBox(value.Z, width * 2 + 4, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
@@ -701,32 +709,33 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = GetValue(box);
|
var value = GetValue(box);
|
||||||
var control = new ContainerControl(bounds.X, bounds.Y, 22 * 4 - 2, bounds.Height)
|
var width = 20;
|
||||||
|
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 4 - 2, bounds.Height)
|
||||||
{
|
{
|
||||||
ClipChildren = false,
|
ClipChildren = false,
|
||||||
AutoFocus = false,
|
AutoFocus = false,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
Tag = box,
|
Tag = box,
|
||||||
};
|
};
|
||||||
var floatX = new FloatValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatX = new FloatValueBox(value.X, 0, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatX.BoxValueChanged += OnValueChanged;
|
floatX.BoxValueChanged += OnValueChanged;
|
||||||
var floatY = new FloatValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatY = new FloatValueBox(value.Y, width + 2, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatY.BoxValueChanged += OnValueChanged;
|
floatY.BoxValueChanged += OnValueChanged;
|
||||||
var floatZ = new FloatValueBox(value.Z, 44, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatZ = new FloatValueBox(value.Z, width * 2 + 4, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatZ.BoxValueChanged += OnValueChanged;
|
floatZ.BoxValueChanged += OnValueChanged;
|
||||||
var floatW = new FloatValueBox(value.W, 66, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatW = new FloatValueBox(value.W, width * 3 + 6, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
@@ -793,20 +802,21 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = GetValue(box);
|
var value = GetValue(box);
|
||||||
var control = new ContainerControl(bounds.X, bounds.Y, 22 * 2 - 2, bounds.Height)
|
var width = 30;
|
||||||
|
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 2 - 2, bounds.Height)
|
||||||
{
|
{
|
||||||
ClipChildren = false,
|
ClipChildren = false,
|
||||||
AutoFocus = false,
|
AutoFocus = false,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
Tag = box,
|
Tag = box,
|
||||||
};
|
};
|
||||||
var floatX = new DoubleValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatX = new DoubleValueBox(value.X, 0, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatX.BoxValueChanged += OnValueChanged;
|
floatX.BoxValueChanged += OnValueChanged;
|
||||||
var floatY = new DoubleValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatY = new DoubleValueBox(value.Y, width + 2, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
@@ -866,26 +876,27 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = GetValue(box);
|
var value = GetValue(box);
|
||||||
var control = new ContainerControl(bounds.X, bounds.Y, 22 * 3 - 2, bounds.Height)
|
var width = 30;
|
||||||
|
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 3 - 2, bounds.Height)
|
||||||
{
|
{
|
||||||
ClipChildren = false,
|
ClipChildren = false,
|
||||||
AutoFocus = false,
|
AutoFocus = false,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
Tag = box,
|
Tag = box,
|
||||||
};
|
};
|
||||||
var floatX = new DoubleValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatX = new DoubleValueBox(value.X, 0, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatX.BoxValueChanged += OnValueChanged;
|
floatX.BoxValueChanged += OnValueChanged;
|
||||||
var floatY = new DoubleValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatY = new DoubleValueBox(value.Y, width + 2, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatY.BoxValueChanged += OnValueChanged;
|
floatY.BoxValueChanged += OnValueChanged;
|
||||||
var floatZ = new DoubleValueBox(value.Z, 44, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatZ = new DoubleValueBox(value.Z, width * 2 + 4, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
@@ -948,32 +959,33 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = GetValue(box);
|
var value = GetValue(box);
|
||||||
var control = new ContainerControl(bounds.X, bounds.Y, 22 * 4 - 2, bounds.Height)
|
var width = 20;
|
||||||
|
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 4 - 2, bounds.Height)
|
||||||
{
|
{
|
||||||
ClipChildren = false,
|
ClipChildren = false,
|
||||||
AutoFocus = false,
|
AutoFocus = false,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
Tag = box,
|
Tag = box,
|
||||||
};
|
};
|
||||||
var floatX = new DoubleValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatX = new DoubleValueBox(value.X, 0, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatX.BoxValueChanged += OnValueChanged;
|
floatX.BoxValueChanged += OnValueChanged;
|
||||||
var floatY = new DoubleValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatY = new DoubleValueBox(value.Y, width + 2, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatY.BoxValueChanged += OnValueChanged;
|
floatY.BoxValueChanged += OnValueChanged;
|
||||||
var floatZ = new DoubleValueBox(value.Z, 44, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatZ = new DoubleValueBox(value.Z, width * 2 + 4, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatZ.BoxValueChanged += OnValueChanged;
|
floatZ.BoxValueChanged += OnValueChanged;
|
||||||
var floatW = new DoubleValueBox(value.W, 66, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatW = new DoubleValueBox(value.W, width * 3 + 6, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
@@ -1040,26 +1052,27 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
public Control Create(InputBox box, ref Rectangle bounds)
|
public Control Create(InputBox box, ref Rectangle bounds)
|
||||||
{
|
{
|
||||||
var value = GetValue(box).EulerAngles;
|
var value = GetValue(box).EulerAngles;
|
||||||
var control = new ContainerControl(bounds.X, bounds.Y, 22 * 3 - 2, bounds.Height)
|
var width = 20;
|
||||||
|
var control = new ContainerControl(bounds.X, bounds.Y, (width + 2) * 3 - 2, bounds.Height)
|
||||||
{
|
{
|
||||||
ClipChildren = false,
|
ClipChildren = false,
|
||||||
AutoFocus = false,
|
AutoFocus = false,
|
||||||
Parent = box.Parent,
|
Parent = box.Parent,
|
||||||
Tag = box,
|
Tag = box,
|
||||||
};
|
};
|
||||||
var floatX = new FloatValueBox(value.X, 0, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatX = new FloatValueBox(value.X, 0, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatX.BoxValueChanged += OnValueChanged;
|
floatX.BoxValueChanged += OnValueChanged;
|
||||||
var floatY = new FloatValueBox(value.Y, 22, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatY = new FloatValueBox(value.Y, width + 2, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
};
|
};
|
||||||
floatY.BoxValueChanged += OnValueChanged;
|
floatY.BoxValueChanged += OnValueChanged;
|
||||||
var floatZ = new FloatValueBox(value.Z, 44, 0, 20, float.MinValue, float.MaxValue, 0.0f)
|
var floatZ = new FloatValueBox(value.Z, width * 2 + 4, 0, width, float.MinValue, float.MaxValue, 0.0f)
|
||||||
{
|
{
|
||||||
Height = bounds.Height,
|
Height = bounds.Height,
|
||||||
Parent = control,
|
Parent = control,
|
||||||
|
|||||||
@@ -147,17 +147,8 @@ namespace FlaxEditor.Tools.Terrain.Sculpt
|
|||||||
Apply(ref p);
|
Apply(ref p);
|
||||||
}
|
}
|
||||||
|
|
||||||
var editorOptions = Editor.Instance.Options.Options;
|
|
||||||
bool isPlayMode = Editor.Instance.StateMachine.IsPlayMode;
|
|
||||||
|
|
||||||
// Auto NavMesh rebuild
|
// Auto NavMesh rebuild
|
||||||
if (!isPlayMode && editorOptions.General.AutoRebuildNavMesh)
|
gizmo.CurrentEditUndoAction.AddDirtyBounds(ref brushBounds);
|
||||||
{
|
|
||||||
if (terrain.Scene && terrain.HasStaticFlag(StaticFlags.Navigation))
|
|
||||||
{
|
|
||||||
Navigation.BuildNavMesh(terrain.Scene, brushBounds, editorOptions.General.AutoRebuildNavMeshTimeoutMs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -41,33 +41,24 @@ namespace FlaxEditor.Tools.Terrain.Undo
|
|||||||
public object Tag;
|
public object Tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The terrain (actor Id).
|
|
||||||
/// </summary>
|
|
||||||
[Serialize]
|
[Serialize]
|
||||||
protected readonly Guid _terrain;
|
protected readonly Guid _terrain;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The heightmap length (vertex count).
|
|
||||||
/// </summary>
|
|
||||||
[Serialize]
|
[Serialize]
|
||||||
protected readonly int _heightmapLength;
|
protected readonly int _heightmapLength;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The heightmap data size (in bytes).
|
|
||||||
/// </summary>
|
|
||||||
[Serialize]
|
[Serialize]
|
||||||
protected readonly int _heightmapDataSize;
|
protected readonly int _heightmapDataSize;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The terrain patches
|
|
||||||
/// </summary>
|
|
||||||
[Serialize]
|
[Serialize]
|
||||||
protected readonly List<PatchData> _patches;
|
protected readonly List<PatchData> _patches;
|
||||||
|
|
||||||
/// <summary>
|
[Serialize]
|
||||||
/// Gets a value indicating whether this action has any modification to the terrain (recorded patches changes).
|
protected readonly List<BoundingBox> _navmeshBoundsModifications;
|
||||||
/// </summary>
|
|
||||||
|
[Serialize]
|
||||||
|
protected readonly float _dirtyNavMeshTimeoutMs;
|
||||||
|
|
||||||
[NoSerialize]
|
[NoSerialize]
|
||||||
public bool HasAnyModification => _patches.Count > 0;
|
public bool HasAnyModification => _patches.Count > 0;
|
||||||
|
|
||||||
@@ -98,6 +89,27 @@ namespace FlaxEditor.Tools.Terrain.Undo
|
|||||||
var heightmapSize = chunkSize * FlaxEngine.Terrain.PatchEdgeChunksCount + 1;
|
var heightmapSize = chunkSize * FlaxEngine.Terrain.PatchEdgeChunksCount + 1;
|
||||||
_heightmapLength = heightmapSize * heightmapSize;
|
_heightmapLength = heightmapSize * heightmapSize;
|
||||||
_heightmapDataSize = _heightmapLength * stride;
|
_heightmapDataSize = _heightmapLength * stride;
|
||||||
|
|
||||||
|
// Auto NavMesh rebuild
|
||||||
|
var editorOptions = Editor.Instance.Options.Options;
|
||||||
|
bool isPlayMode = Editor.Instance.StateMachine.IsPlayMode;
|
||||||
|
if (!isPlayMode && editorOptions.General.AutoRebuildNavMesh)
|
||||||
|
{
|
||||||
|
if (terrain.Scene && terrain.HasStaticFlag(StaticFlags.Navigation))
|
||||||
|
{
|
||||||
|
_navmeshBoundsModifications = new List<BoundingBox>();
|
||||||
|
_dirtyNavMeshTimeoutMs = editorOptions.General.AutoRebuildNavMeshTimeoutMs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds modified bounds to the undo actor modifications list.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bounds">The world-space bounds.</param>
|
||||||
|
public void AddDirtyBounds(ref BoundingBox bounds)
|
||||||
|
{
|
||||||
|
_navmeshBoundsModifications?.Add(bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -155,7 +167,15 @@ namespace FlaxEditor.Tools.Terrain.Undo
|
|||||||
_patches[i] = patch;
|
_patches[i] = patch;
|
||||||
}
|
}
|
||||||
|
|
||||||
Editor.Instance.Scene.MarkSceneEdited(Terrain.Scene);
|
// Update navmesh
|
||||||
|
var scene = Terrain.Scene;
|
||||||
|
if (_navmeshBoundsModifications != null)
|
||||||
|
{
|
||||||
|
foreach (var bounds in _navmeshBoundsModifications)
|
||||||
|
Navigation.BuildNavMesh(scene, bounds, _dirtyNavMeshTimeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor.Instance.Scene.MarkSceneEdited(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -183,10 +203,12 @@ namespace FlaxEditor.Tools.Terrain.Undo
|
|||||||
Marshal.FreeHGlobal(_patches[i].After);
|
Marshal.FreeHGlobal(_patches[i].After);
|
||||||
}
|
}
|
||||||
_patches.Clear();
|
_patches.Clear();
|
||||||
|
_navmeshBoundsModifications?.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Set(Func<PatchData, IntPtr> dataGetter)
|
private void Set(Func<PatchData, IntPtr> dataGetter)
|
||||||
{
|
{
|
||||||
|
// Update patches
|
||||||
for (int i = 0; i < _patches.Count; i++)
|
for (int i = 0; i < _patches.Count; i++)
|
||||||
{
|
{
|
||||||
var patch = _patches[i];
|
var patch = _patches[i];
|
||||||
@@ -194,6 +216,14 @@ namespace FlaxEditor.Tools.Terrain.Undo
|
|||||||
SetData(ref patch.PatchCoord, data, patch.Tag);
|
SetData(ref patch.PatchCoord, data, patch.Tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update navmesh
|
||||||
|
var scene = Terrain.Scene;
|
||||||
|
if (_navmeshBoundsModifications != null)
|
||||||
|
{
|
||||||
|
foreach (var bounds in _navmeshBoundsModifications)
|
||||||
|
Navigation.BuildNavMesh(scene, bounds, _dirtyNavMeshTimeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
Editor.Instance.Scene.MarkSceneEdited(Terrain.Scene);
|
Editor.Instance.Scene.MarkSceneEdited(Terrain.Scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ namespace FlaxEditor.Windows
|
|||||||
var scriptType = new ScriptType(typeof(Script));
|
var scriptType = new ScriptType(typeof(Script));
|
||||||
foreach (var type in Editor.CodeEditing.All.Get())
|
foreach (var type in Editor.CodeEditing.All.Get())
|
||||||
{
|
{
|
||||||
if (type.IsAbstract)
|
if (type.IsAbstract || type.Type == null)
|
||||||
continue;
|
continue;
|
||||||
if (actorType.IsAssignableFrom(type) || scriptType.IsAssignableFrom(type))
|
if (actorType.IsAssignableFrom(type) || scriptType.IsAssignableFrom(type))
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -4,15 +4,16 @@
|
|||||||
#include "Cache/AssetsCache.h"
|
#include "Cache/AssetsCache.h"
|
||||||
#include "Storage/ContentStorageManager.h"
|
#include "Storage/ContentStorageManager.h"
|
||||||
#include "Loading/Tasks/LoadAssetDataTask.h"
|
#include "Loading/Tasks/LoadAssetDataTask.h"
|
||||||
|
#include "Factories/BinaryAssetFactory.h"
|
||||||
#include "Engine/ContentImporters/AssetsImportingManager.h"
|
#include "Engine/ContentImporters/AssetsImportingManager.h"
|
||||||
#include "Engine/Content/Content.h"
|
#include "Engine/Content/Content.h"
|
||||||
#include "Engine/Serialization/JsonTools.h"
|
#include "Engine/Serialization/JsonTools.h"
|
||||||
#include "Engine/Debug/Exceptions/JsonParseException.h"
|
#include "Engine/Debug/Exceptions/JsonParseException.h"
|
||||||
#include "Factories/BinaryAssetFactory.h"
|
|
||||||
#include "Engine/Threading/ThreadPoolTask.h"
|
#include "Engine/Threading/ThreadPoolTask.h"
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
#include "Engine/Platform/FileSystem.h"
|
#include "Engine/Platform/FileSystem.h"
|
||||||
#include "Engine/Threading/Threading.h"
|
#include "Engine/Threading/Threading.h"
|
||||||
|
#include "Engine/Engine/Globals.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
REGISTER_BINARY_ASSET_ABSTRACT(BinaryAsset, "FlaxEngine.BinaryAsset");
|
REGISTER_BINARY_ASSET_ABSTRACT(BinaryAsset, "FlaxEngine.BinaryAsset");
|
||||||
@@ -123,6 +124,12 @@ void BinaryAsset::GetImportMetadata(String& path, String& username) const
|
|||||||
{
|
{
|
||||||
path = JsonTools::GetString(document, "ImportPath");
|
path = JsonTools::GetString(document, "ImportPath");
|
||||||
username = JsonTools::GetString(document, "ImportUsername");
|
username = JsonTools::GetString(document, "ImportUsername");
|
||||||
|
if (path.HasChars() && FileSystem::IsRelative(path))
|
||||||
|
{
|
||||||
|
// Convert path back to thr absolute (eg. if stored in relative format)
|
||||||
|
path = Globals::ProjectFolder / path;
|
||||||
|
StringUtils::PathRemoveRelativeParts(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "Content.h"
|
#include "Content.h"
|
||||||
#include "JsonAsset.h"
|
#include "JsonAsset.h"
|
||||||
|
#include "SceneReference.h"
|
||||||
|
#include "Engine/Serialization/Serialization.h"
|
||||||
#include "Cache/AssetsCache.h"
|
#include "Cache/AssetsCache.h"
|
||||||
#include "Storage/ContentStorageManager.h"
|
#include "Storage/ContentStorageManager.h"
|
||||||
#include "Storage/JsonStorageProxy.h"
|
#include "Storage/JsonStorageProxy.h"
|
||||||
@@ -39,6 +41,16 @@ String AssetInfo::ToString() const
|
|||||||
return String::Format(TEXT("ID: {0}, TypeName: {1}, Path: \'{2}\'"), ID, TypeName, Path);
|
return String::Format(TEXT("ID: {0}, TypeName: {1}, Path: \'{2}\'"), ID, TypeName, Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FLAXENGINE_API Serialization::Serialize(ISerializable::SerializeStream& stream, const SceneReference& v, const void* otherObj)
|
||||||
|
{
|
||||||
|
Serialize(stream, v.ID, otherObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FLAXENGINE_API Serialization::Deserialize(ISerializable::DeserializeStream& stream, SceneReference& v, ISerializeModifier* modifier)
|
||||||
|
{
|
||||||
|
Deserialize(stream, v.ID, modifier);
|
||||||
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// Assets
|
// Assets
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Engine/Core/Types/Guid.h"
|
#include "Engine/Core/Types/Guid.h"
|
||||||
|
#include "Engine/Core/ISerializable.h"
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the reference to the scene asset. Stores the unique ID of the scene to reference. Can be used to load the selected scene.
|
/// Represents the reference to the scene asset. Stores the unique ID of the scene to reference. Can be used to load the selected scene.
|
||||||
@@ -15,4 +16,37 @@ API_STRUCT(NoDefault) struct FLAXENGINE_API SceneReference
|
|||||||
/// The identifier of the scene asset (and the scene object).
|
/// The identifier of the scene asset (and the scene object).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD() Guid ID;
|
API_FIELD() Guid ID;
|
||||||
|
|
||||||
|
FORCE_INLINE bool operator==(const SceneReference& other) const
|
||||||
|
{
|
||||||
|
return ID == other.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE bool operator!=(const SceneReference& other) const
|
||||||
|
{
|
||||||
|
return ID != other.ID;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct TIsPODType<SceneReference>
|
||||||
|
{
|
||||||
|
enum { Value = true };
|
||||||
|
};
|
||||||
|
|
||||||
|
inline uint32 GetHash(const SceneReference& key)
|
||||||
|
{
|
||||||
|
return GetHash(key.ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
namespace Serialization
|
||||||
|
{
|
||||||
|
inline bool ShouldSerialize(const SceneReference& v, const void* otherObj)
|
||||||
|
{
|
||||||
|
return !otherObj || v != *(SceneReference*)otherObj;
|
||||||
|
}
|
||||||
|
void FLAXENGINE_API Serialize(ISerializable::SerializeStream& stream, const SceneReference& v, const void* otherObj);
|
||||||
|
void FLAXENGINE_API Deserialize(ISerializable::DeserializeStream& stream, SceneReference& v, ISerializeModifier* modifier);
|
||||||
|
}
|
||||||
|
// @formatter:on
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#if COMPILE_WITH_ASSETS_IMPORTER
|
#if COMPILE_WITH_ASSETS_IMPORTER
|
||||||
|
|
||||||
#include "AssetsImportingManager.h"
|
#include "AssetsImportingManager.h"
|
||||||
|
#include "Engine/Core/Log.h"
|
||||||
#include "Engine/Core/Utilities.h"
|
#include "Engine/Core/Utilities.h"
|
||||||
#include "Engine/Serialization/JsonWriters.h"
|
#include "Engine/Serialization/JsonWriters.h"
|
||||||
#include "Engine/Threading/MainThreadTask.h"
|
#include "Engine/Threading/MainThreadTask.h"
|
||||||
@@ -10,9 +11,9 @@
|
|||||||
#include "Engine/Content/Content.h"
|
#include "Engine/Content/Content.h"
|
||||||
#include "Engine/Content/Cache/AssetsCache.h"
|
#include "Engine/Content/Cache/AssetsCache.h"
|
||||||
#include "Engine/Engine/EngineService.h"
|
#include "Engine/Engine/EngineService.h"
|
||||||
#include "Engine/Core/Log.h"
|
|
||||||
#include "Engine/Platform/FileSystem.h"
|
#include "Engine/Platform/FileSystem.h"
|
||||||
#include "Engine/Platform/Platform.h"
|
#include "Engine/Platform/Platform.h"
|
||||||
|
#include "Engine/Engine/Globals.h"
|
||||||
#include "ImportTexture.h"
|
#include "ImportTexture.h"
|
||||||
#include "ImportModelFile.h"
|
#include "ImportModelFile.h"
|
||||||
#include "ImportAudio.h"
|
#include "ImportAudio.h"
|
||||||
@@ -71,6 +72,7 @@ AssetsImportingManagerService AssetsImportingManagerServiceInstance;
|
|||||||
|
|
||||||
Array<AssetImporter> AssetsImportingManager::Importers;
|
Array<AssetImporter> AssetsImportingManager::Importers;
|
||||||
Array<AssetCreator> AssetsImportingManager::Creators;
|
Array<AssetCreator> AssetsImportingManager::Creators;
|
||||||
|
bool AssetsImportingManager::UseImportPathRelative = false;
|
||||||
|
|
||||||
CreateAssetContext::CreateAssetContext(const StringView& inputPath, const StringView& outputPath, const Guid& id, void* arg)
|
CreateAssetContext::CreateAssetContext(const StringView& inputPath, const StringView& outputPath, const Guid& id, void* arg)
|
||||||
{
|
{
|
||||||
@@ -161,7 +163,15 @@ bool CreateAssetContext::AllocateChunk(int32 index)
|
|||||||
void CreateAssetContext::AddMeta(JsonWriter& writer) const
|
void CreateAssetContext::AddMeta(JsonWriter& writer) const
|
||||||
{
|
{
|
||||||
writer.JKEY("ImportPath");
|
writer.JKEY("ImportPath");
|
||||||
writer.String(InputPath);
|
if (AssetsImportingManager::UseImportPathRelative && !FileSystem::IsRelative(InputPath))
|
||||||
|
{
|
||||||
|
const String relativePath = FileSystem::ConvertAbsolutePathToRelative(Globals::ProjectFolder, InputPath);
|
||||||
|
writer.String(relativePath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.String(InputPath);
|
||||||
|
}
|
||||||
writer.JKEY("ImportUsername");
|
writer.JKEY("ImportUsername");
|
||||||
writer.String(Platform::GetUserName());
|
writer.String(Platform::GetUserName());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
static Array<AssetCreator> Creators;
|
static Array<AssetCreator> Creators;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true store asset import path relative to the current workspace, otherwise will store absolute path.
|
||||||
|
/// </summary>
|
||||||
|
static bool UseImportPathRelative;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The create texture tag (using internal import pipeline to crate texture asset from custom image source).
|
/// The create texture tag (using internal import pipeline to crate texture asset from custom image source).
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ FLAXENGINE_API String* TagsListDebug = nullptr;
|
|||||||
|
|
||||||
const String& Tag::ToString() const
|
const String& Tag::ToString() const
|
||||||
{
|
{
|
||||||
return Index >= 0 && Index < Tags::List.Count() ? Tags::List.Get()[Index] : String::Empty;
|
const int32 index = (int32)Index - 1;
|
||||||
|
return index >= 0 && index < Tags::List.Count() ? Tags::List.Get()[index] : String::Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tag::operator==(const StringView& other) const
|
bool Tag::operator==(const StringView& other) const
|
||||||
@@ -27,7 +28,7 @@ bool Tag::operator!=(const StringView& other) const
|
|||||||
|
|
||||||
void FLAXENGINE_API Serialization::Serialize(ISerializable::SerializeStream& stream, const Tag& v, const void* otherObj)
|
void FLAXENGINE_API Serialization::Serialize(ISerializable::SerializeStream& stream, const Tag& v, const void* otherObj)
|
||||||
{
|
{
|
||||||
if (v.Index != -1)
|
if (v.Index != 0)
|
||||||
stream.String(v.ToString());
|
stream.String(v.ToString());
|
||||||
else
|
else
|
||||||
stream.String("", 0);
|
stream.String("", 0);
|
||||||
@@ -42,11 +43,11 @@ Tag Tags::Get(const StringView& tagName)
|
|||||||
{
|
{
|
||||||
if (tagName.IsEmpty())
|
if (tagName.IsEmpty())
|
||||||
return Tag();
|
return Tag();
|
||||||
Tag tag = List.Find(tagName);
|
Tag tag(List.Find(tagName) + 1);
|
||||||
if (tag.Index == -1 && tagName.HasChars())
|
if (tag.Index == 0 && tagName.HasChars())
|
||||||
{
|
{
|
||||||
tag.Index = List.Count();
|
|
||||||
List.AddOne() = tagName;
|
List.AddOne() = tagName;
|
||||||
|
tag.Index = List.Count();
|
||||||
#if !BUILD_RELEASE
|
#if !BUILD_RELEASE
|
||||||
TagsListDebug = List.Get();
|
TagsListDebug = List.Get();
|
||||||
#endif
|
#endif
|
||||||
@@ -56,7 +57,7 @@ Tag Tags::Get(const StringView& tagName)
|
|||||||
|
|
||||||
bool Tags::HasTag(const Array<Tag>& list, const Tag& tag)
|
bool Tags::HasTag(const Array<Tag>& list, const Tag& tag)
|
||||||
{
|
{
|
||||||
if (tag.Index == -1)
|
if (tag.Index == 0)
|
||||||
return false;
|
return false;
|
||||||
const String& tagName = tag.ToString();
|
const String& tagName = tag.ToString();
|
||||||
for (const Tag& e : list)
|
for (const Tag& e : list)
|
||||||
@@ -70,7 +71,7 @@ bool Tags::HasTag(const Array<Tag>& list, const Tag& tag)
|
|||||||
|
|
||||||
bool Tags::HasTagExact(const Array<Tag>& list, const Tag& tag)
|
bool Tags::HasTagExact(const Array<Tag>& list, const Tag& tag)
|
||||||
{
|
{
|
||||||
if (tag.Index == -1)
|
if (tag.Index == 0)
|
||||||
return false;
|
return false;
|
||||||
return list.Contains(tag);
|
return list.Contains(tag);
|
||||||
}
|
}
|
||||||
@@ -119,7 +120,7 @@ bool Tags::HasAllExact(const Array<Tag>& list, const Array<Tag>& tags)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const String& Tags::GetTagName(int32 tag)
|
const String& Tags::GetTagName(uint32 tag)
|
||||||
{
|
{
|
||||||
return Tag(tag).ToString();
|
return Tag(tag).ToString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,29 @@
|
|||||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Globalization;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace FlaxEngine
|
namespace FlaxEngine
|
||||||
{
|
{
|
||||||
|
[TypeConverter(typeof(TypeConverters.TagConverter))]
|
||||||
partial struct Tag : IEquatable<Tag>, IEquatable<string>, IComparable, IComparable<Tag>, IComparable<string>
|
partial struct Tag : IEquatable<Tag>, IEquatable<string>, IComparable, IComparable<Tag>, IComparable<string>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default <see cref="Tag"/>.
|
/// The default <see cref="Tag"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Tag Default => new Tag(-1);
|
public static Tag Default => new Tag(0);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Tag" /> struct.
|
/// Initializes a new instance of the <see cref="Tag" /> struct.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">The tag index.</param>
|
/// <param name="index">The tag index.</param>
|
||||||
public Tag(int index)
|
public Tag(uint index)
|
||||||
{
|
{
|
||||||
Index = index;
|
Index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.Runtime.Serialization.OnDeserializing]
|
|
||||||
internal void OnDeserializing(System.Runtime.Serialization.StreamingContext context)
|
|
||||||
{
|
|
||||||
// Initialize structure with default values to replicate C++ deserialization behavior
|
|
||||||
Index = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares two tags.
|
/// Compares two tags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -50,6 +46,28 @@ namespace FlaxEngine
|
|||||||
return left.Index == right.Index;
|
return left.Index == right.Index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares two tags.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">The lft tag.</param>
|
||||||
|
/// <param name="right">The right tag name.</param>
|
||||||
|
/// <returns>True if both values are equal, otherwise false.</returns>
|
||||||
|
public static bool operator ==(Tag left, string right)
|
||||||
|
{
|
||||||
|
return string.Equals(left.ToString(), right, StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares two tags.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">The lft tag.</param>
|
||||||
|
/// <param name="right">The right tag name.</param>
|
||||||
|
/// <returns>True if both values are not equal, otherwise false.</returns>
|
||||||
|
public static bool operator !=(Tag left, string right)
|
||||||
|
{
|
||||||
|
return !string.Equals(left.ToString(), right, StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if tag is valid.
|
/// Checks if tag is valid.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -58,7 +76,7 @@ namespace FlaxEngine
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static implicit operator bool(Tag tag)
|
public static implicit operator bool(Tag tag)
|
||||||
{
|
{
|
||||||
return tag.Index != -1;
|
return tag.Index != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -104,7 +122,7 @@ namespace FlaxEngine
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return Index;
|
return (int)Index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -124,7 +142,7 @@ namespace FlaxEngine
|
|||||||
/// <returns>True if given tag is contained by the list of tags. Returns false for empty list.</returns>
|
/// <returns>True if given tag is contained by the list of tags. Returns false for empty list.</returns>
|
||||||
public static bool HasTag(this Tag[] list, Tag tag)
|
public static bool HasTag(this Tag[] list, Tag tag)
|
||||||
{
|
{
|
||||||
if (tag.Index == -1)
|
if (tag.Index == 0)
|
||||||
return false;
|
return false;
|
||||||
string tagName = tag.ToString();
|
string tagName = tag.ToString();
|
||||||
foreach (Tag e in list)
|
foreach (Tag e in list)
|
||||||
@@ -144,7 +162,7 @@ namespace FlaxEngine
|
|||||||
/// <returns>True if given tag is contained by the list of tags. Returns false for empty list.</returns>
|
/// <returns>True if given tag is contained by the list of tags. Returns false for empty list.</returns>
|
||||||
public static bool HasTagExact(this Tag[] list, Tag tag)
|
public static bool HasTagExact(this Tag[] list, Tag tag)
|
||||||
{
|
{
|
||||||
if (tag.Index == -1)
|
if (tag.Index == 0)
|
||||||
return false;
|
return false;
|
||||||
if (list == null)
|
if (list == null)
|
||||||
return false;
|
return false;
|
||||||
@@ -233,3 +251,40 @@ namespace FlaxEngine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace FlaxEngine.TypeConverters
|
||||||
|
{
|
||||||
|
internal class TagConverter : TypeConverter
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||||
|
{
|
||||||
|
if (sourceType == typeof(string))
|
||||||
|
return true;
|
||||||
|
return base.CanConvertFrom(context, sourceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
|
{
|
||||||
|
if (value is string str)
|
||||||
|
{
|
||||||
|
if (str.Length == 0)
|
||||||
|
return Tag.Default;
|
||||||
|
return Tags.Get(str);
|
||||||
|
}
|
||||||
|
return base.ConvertFrom(context, culture, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
||||||
|
{
|
||||||
|
if (destinationType == typeof(string))
|
||||||
|
{
|
||||||
|
var v = (Tag)value;
|
||||||
|
return v.ToString();
|
||||||
|
}
|
||||||
|
return base.ConvertTo(context, culture, value, destinationType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ API_STRUCT(NoDefault) struct FLAXENGINE_API Tag
|
|||||||
DECLARE_SCRIPTING_TYPE_MINIMAL(Tag);
|
DECLARE_SCRIPTING_TYPE_MINIMAL(Tag);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Index of the tag (in global Level.Tags list).
|
/// Index of the tag (in global Level.Tags list). Index 0 is invalid. 1 is the first index.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD() int32 Index = -1;
|
API_FIELD() uint32 Index = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the tag name.
|
/// Gets the tag name.
|
||||||
@@ -26,14 +26,14 @@ API_STRUCT(NoDefault) struct FLAXENGINE_API Tag
|
|||||||
public:
|
public:
|
||||||
Tag() = default;
|
Tag() = default;
|
||||||
|
|
||||||
FORCE_INLINE Tag(int32 index)
|
FORCE_INLINE explicit Tag(uint32 index)
|
||||||
: Index(index)
|
: Index(index)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE operator bool() const
|
FORCE_INLINE operator bool() const
|
||||||
{
|
{
|
||||||
return Index != -1;
|
return Index != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE bool operator==(const Tag& other) const
|
FORCE_INLINE bool operator==(const Tag& other) const
|
||||||
@@ -142,7 +142,7 @@ public:
|
|||||||
static bool HasAllExact(const Array<Tag>& list, const Array<Tag>& tags);
|
static bool HasAllExact(const Array<Tag>& list, const Array<Tag>& tags);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
API_FUNCTION(NoProxy) static const String& GetTagName(int32 tag);
|
API_FUNCTION(NoProxy) static const String& GetTagName(uint32 tag);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if !BUILD_RELEASE
|
#if !BUILD_RELEASE
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
#include "Engine/Core/ISerializable.h"
|
#include "Engine/Core/ISerializable.h"
|
||||||
|
#include "Engine/Level/Tags.h"
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Physical materials are used to define the response of a physical object when interacting dynamically with the world.
|
/// Physical materials are used to define the response of a physical object when interacting dynamically with the world.
|
||||||
@@ -69,6 +70,12 @@ public:
|
|||||||
API_FIELD(Attributes="EditorOrder(10), EditorDisplay(\"Physical Material\")")
|
API_FIELD(Attributes="EditorOrder(10), EditorDisplay(\"Physical Material\")")
|
||||||
float Density = 1000.0f;
|
float Density = 1000.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Physical material tag used to identify it (eg. `Surface.Wood`). Can be used to play proper footstep sounds when walking over object with that material.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes="EditorOrder(100), EditorDisplay(\"Physical Material\")")
|
||||||
|
Tag Tag;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the PhysX material.
|
/// Gets the PhysX material.
|
||||||
|
|||||||
@@ -119,6 +119,11 @@ public:
|
|||||||
|
|
||||||
// Tries to cast native interface object to scripting object instance. Returns null if fails.
|
// Tries to cast native interface object to scripting object instance. Returns null if fails.
|
||||||
static ScriptingObject* FromInterface(void* interfaceObj, const ScriptingTypeHandle& interfaceType);
|
static ScriptingObject* FromInterface(void* interfaceObj, const ScriptingTypeHandle& interfaceType);
|
||||||
|
template<typename T>
|
||||||
|
static ScriptingObject* FromInterface(T* interfaceObj)
|
||||||
|
{
|
||||||
|
return FromInterface(interfaceObj, T::TypeInitializer);
|
||||||
|
}
|
||||||
static void* ToInterface(ScriptingObject* obj, const ScriptingTypeHandle& interfaceType);
|
static void* ToInterface(ScriptingObject* obj, const ScriptingTypeHandle& interfaceType);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static T* ToInterface(ScriptingObject* obj)
|
static T* ToInterface(ScriptingObject* obj)
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ TEST_CASE("Scripting")
|
|||||||
CHECK(object->Is<TestClassNative>());
|
CHECK(object->Is<TestClassNative>());
|
||||||
TestClassNative* testClass = (TestClassNative*)object;
|
TestClassNative* testClass = (TestClassNative*)object;
|
||||||
CHECK(testClass->SimpleField == 1);
|
CHECK(testClass->SimpleField == 1);
|
||||||
int32 methodResult = testClass->Test(TEXT("123"));
|
CHECK(testClass->SimpleStruct.Object == nullptr);
|
||||||
|
CHECK(testClass->SimpleStruct.Vector == Float3::One);
|
||||||
|
int32 methodResult = testClass->TestMethod(TEXT("123"));
|
||||||
CHECK(methodResult == 3);
|
CHECK(methodResult == 3);
|
||||||
|
|
||||||
// Test managed class
|
// Test managed class
|
||||||
@@ -34,7 +36,80 @@ TEST_CASE("Scripting")
|
|||||||
MObject* managed = testClass->GetOrCreateManagedInstance(); // Ensure to create C# object and run it's ctor
|
MObject* managed = testClass->GetOrCreateManagedInstance(); // Ensure to create C# object and run it's ctor
|
||||||
CHECK(managed);
|
CHECK(managed);
|
||||||
CHECK(testClass->SimpleField == 2);
|
CHECK(testClass->SimpleField == 2);
|
||||||
methodResult = testClass->Test(TEXT("123"));
|
CHECK(testClass->SimpleStruct.Object == testClass);
|
||||||
|
CHECK(testClass->SimpleStruct.Vector == Float3::UnitX);
|
||||||
|
methodResult = testClass->TestMethod(TEXT("123"));
|
||||||
CHECK(methodResult == 6);
|
CHECK(methodResult == 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Test Event")
|
||||||
|
{
|
||||||
|
ScriptingTypeHandle type = Scripting::FindScriptingType("FlaxEngine.TestClassManaged");
|
||||||
|
CHECK(type);
|
||||||
|
ScriptingObject* object = Scripting::NewObject(type.GetType().ManagedClass);
|
||||||
|
CHECK(object);
|
||||||
|
MObject* managed = object->GetOrCreateManagedInstance(); // Ensure to create C# object and run it's ctor
|
||||||
|
CHECK(managed);
|
||||||
|
TestClassNative* testClass = (TestClassNative*)object;
|
||||||
|
CHECK(testClass->SimpleField == 2);
|
||||||
|
String str1 = TEXT("1");
|
||||||
|
String str2 = TEXT("2");
|
||||||
|
Array<TestStruct> arr1 = { testClass->SimpleStruct };
|
||||||
|
Array<TestStruct> arr2 = { testClass->SimpleStruct };
|
||||||
|
testClass->SimpleEvent(1, Float3::One, str1, str2, arr1, arr2);
|
||||||
|
CHECK(testClass->SimpleField == 4);
|
||||||
|
CHECK(str2 == TEXT("4"));
|
||||||
|
CHECK(arr2.Count() == 2);
|
||||||
|
CHECK(arr2[0].Vector == Float3::Half);
|
||||||
|
CHECK(arr2[0].Object == nullptr);
|
||||||
|
CHECK(arr2[1].Vector == testClass->SimpleStruct.Vector);
|
||||||
|
CHECK(arr2[1].Object == testClass);
|
||||||
|
}
|
||||||
|
SECTION("Test Interface")
|
||||||
|
{
|
||||||
|
// Test native interface implementation
|
||||||
|
ScriptingTypeHandle type = Scripting::FindScriptingType("FlaxEngine.TestClassNative");
|
||||||
|
CHECK(type);
|
||||||
|
ScriptingObject* object = Scripting::NewObject(type.GetType().ManagedClass);
|
||||||
|
CHECK(object);
|
||||||
|
TestClassNative* testClass = (TestClassNative*)object;
|
||||||
|
int32 methodResult = testClass->TestInterfaceMethod(TEXT("123"));
|
||||||
|
CHECK(methodResult == 3);
|
||||||
|
ITestInterface* interface = ScriptingObject::ToInterface<ITestInterface>(object);
|
||||||
|
CHECK(interface);
|
||||||
|
methodResult = interface->TestInterfaceMethod(TEXT("1234"));
|
||||||
|
CHECK(methodResult == 4);
|
||||||
|
ScriptingObject* interfaceObject = ScriptingObject::FromInterface<ITestInterface>(interface);
|
||||||
|
CHECK(interfaceObject);
|
||||||
|
CHECK(interfaceObject == object);
|
||||||
|
|
||||||
|
// Test managed interface override
|
||||||
|
type = Scripting::FindScriptingType("FlaxEngine.TestClassManaged");
|
||||||
|
CHECK(type);
|
||||||
|
object = Scripting::NewObject(type.GetType().ManagedClass);
|
||||||
|
CHECK(object);
|
||||||
|
testClass = (TestClassNative*)object;
|
||||||
|
methodResult = testClass->TestInterfaceMethod(TEXT("123"));
|
||||||
|
CHECK(methodResult == 6);
|
||||||
|
interface = ScriptingObject::ToInterface<ITestInterface>(object);
|
||||||
|
CHECK(interface);
|
||||||
|
methodResult = interface->TestInterfaceMethod(TEXT("1234"));
|
||||||
|
CHECK(methodResult == 8);
|
||||||
|
interfaceObject = ScriptingObject::FromInterface<ITestInterface>(interface);
|
||||||
|
CHECK(interfaceObject);
|
||||||
|
CHECK(interfaceObject == object);
|
||||||
|
|
||||||
|
// Test managed interface implementation
|
||||||
|
type = Scripting::FindScriptingType("FlaxEngine.TestInterfaceManaged");
|
||||||
|
CHECK(type);
|
||||||
|
object = Scripting::NewObject(type.GetType().ManagedClass);
|
||||||
|
CHECK(object);
|
||||||
|
interface = ScriptingObject::ToInterface<ITestInterface>(object);
|
||||||
|
CHECK(interface);
|
||||||
|
methodResult = interface->TestInterfaceMethod(TEXT("1234"));
|
||||||
|
CHECK(methodResult == 4);
|
||||||
|
interfaceObject = ScriptingObject::FromInterface<ITestInterface>(interface);
|
||||||
|
CHECK(interfaceObject);
|
||||||
|
CHECK(interfaceObject == object);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,48 @@
|
|||||||
#if FLAX_TESTS
|
#if FLAX_TESTS
|
||||||
namespace FlaxEngine
|
namespace FlaxEngine
|
||||||
{
|
{
|
||||||
|
partial struct TestStruct : System.IEquatable<TestStruct>
|
||||||
|
{
|
||||||
|
/// <summary></summary>
|
||||||
|
public static bool operator ==(TestStruct left, TestStruct right)
|
||||||
|
{
|
||||||
|
return left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary></summary>
|
||||||
|
public static bool operator !=(TestStruct left, TestStruct right)
|
||||||
|
{
|
||||||
|
return !left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool Equals(TestStruct other)
|
||||||
|
{
|
||||||
|
return Vector.Equals(other.Vector) && Equals(Object, other.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is TestStruct other && Equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
return (Vector.GetHashCode() * 397) ^ (Object != null ? Object.GetHashCode() : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"Vector={Vector}, Object={Object?.ToString() ?? "null"}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Test class.
|
/// Test class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -10,13 +52,65 @@ namespace FlaxEngine
|
|||||||
{
|
{
|
||||||
TestClassManaged()
|
TestClassManaged()
|
||||||
{
|
{
|
||||||
|
// Test setting C++ values from C#
|
||||||
SimpleField = 2;
|
SimpleField = 2;
|
||||||
|
SimpleStruct = new TestStruct
|
||||||
|
{
|
||||||
|
Vector = Float3.UnitX,
|
||||||
|
Object = this,
|
||||||
|
};
|
||||||
|
SimpleEvent += OnSimpleEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override int Test(string str)
|
public override int TestMethod(string str)
|
||||||
{
|
{
|
||||||
return str.Length + base.Test(str);
|
// Test C++ base method invocation
|
||||||
|
return str.Length + base.TestMethod(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int TestInterfaceMethod(string str)
|
||||||
|
{
|
||||||
|
// Test C++ base method invocation
|
||||||
|
return str.Length + base.TestInterfaceMethod(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSimpleEvent(int arg1, Float3 arg2, string arg3, ref string arg4, TestStruct[] arg5, ref TestStruct[] arg6)
|
||||||
|
{
|
||||||
|
// Verify that C++ passed proper data to C# via event bindings
|
||||||
|
if (arg1 == 1 &&
|
||||||
|
arg2 == Float3.One &&
|
||||||
|
arg3 == "1" &&
|
||||||
|
arg4 == "2" &&
|
||||||
|
arg5 != null && arg5.Length == 1 && arg5[0] == SimpleStruct &&
|
||||||
|
arg6 != null && arg6.Length == 1 && arg6[0] == SimpleStruct)
|
||||||
|
{
|
||||||
|
// Test passing data back from C# to C++
|
||||||
|
SimpleField = 4;
|
||||||
|
arg4 = "4";
|
||||||
|
arg6 = new TestStruct[2]
|
||||||
|
{
|
||||||
|
new TestStruct
|
||||||
|
{
|
||||||
|
Vector = Float3.Half,
|
||||||
|
Object = null,
|
||||||
|
},
|
||||||
|
SimpleStruct,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test interface in C#.
|
||||||
|
/// </summary>
|
||||||
|
public class TestInterfaceManaged : Object, ITestInterface
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public int TestInterfaceMethod(string str)
|
||||||
|
{
|
||||||
|
return str.Length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,34 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Engine/Core/ISerializable.h"
|
#include "Engine/Core/ISerializable.h"
|
||||||
|
#include "Engine/Core/Math/Vector3.h"
|
||||||
|
#include "Engine/Core/Collections/Array.h"
|
||||||
#include "Engine/Scripting/ScriptingObject.h"
|
#include "Engine/Scripting/ScriptingObject.h"
|
||||||
|
|
||||||
|
// Test structure.
|
||||||
|
API_STRUCT(NoDefault) struct TestStruct : public ISerializable
|
||||||
|
{
|
||||||
|
API_AUTO_SERIALIZATION();
|
||||||
|
DECLARE_SCRIPTING_TYPE_MINIMAL(TestStruct);
|
||||||
|
|
||||||
|
// Var
|
||||||
|
API_FIELD() Float3 Vector = Float3::One;
|
||||||
|
// Ref
|
||||||
|
API_FIELD() ScriptingObject* Object = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test interface.
|
||||||
|
API_INTERFACE() class ITestInterface
|
||||||
|
{
|
||||||
|
DECLARE_SCRIPTING_TYPE_MINIMAL(ITestInterface);
|
||||||
|
~ITestInterface() = default;
|
||||||
|
|
||||||
|
// Test abstract method
|
||||||
|
API_FUNCTION() virtual int32 TestInterfaceMethod(const String& str) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// Test class.
|
// Test class.
|
||||||
API_CLASS() class TestClassNative : public ScriptingObject, public ISerializable
|
API_CLASS() class TestClassNative : public ScriptingObject, public ISerializable, public ITestInterface
|
||||||
{
|
{
|
||||||
API_AUTO_SERIALIZATION();
|
API_AUTO_SERIALIZATION();
|
||||||
DECLARE_SCRIPTING_TYPE(TestClassNative);
|
DECLARE_SCRIPTING_TYPE(TestClassNative);
|
||||||
@@ -15,8 +39,19 @@ public:
|
|||||||
// Test value
|
// Test value
|
||||||
API_FIELD() int32 SimpleField = 1;
|
API_FIELD() int32 SimpleField = 1;
|
||||||
|
|
||||||
|
// Test struct
|
||||||
|
API_FIELD() TestStruct SimpleStruct;
|
||||||
|
|
||||||
|
// Test event
|
||||||
|
API_EVENT() Delegate<int32, Float3, const String&, String&, const Array<TestStruct>&, Array<TestStruct>&> SimpleEvent;
|
||||||
|
|
||||||
// Test virtual method
|
// Test virtual method
|
||||||
API_FUNCTION() virtual int32 Test(const String& str)
|
API_FUNCTION() virtual int32 TestMethod(const String& str)
|
||||||
|
{
|
||||||
|
return str.Length();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 TestInterfaceMethod(const String& str) override
|
||||||
{
|
{
|
||||||
return str.Length();
|
return str.Length();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,14 +99,15 @@ namespace Flax.Build.Bindings
|
|||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GenerateCppWrapperNativeToManagedParam(BuildData buildData, StringBuilder contents, TypeInfo paramType, string paramName, ApiTypeInfo caller, bool isOut)
|
private static string GenerateCppWrapperNativeToManagedParam(BuildData buildData, StringBuilder contents, TypeInfo paramType, string paramName, ApiTypeInfo caller, bool isOut, out bool useLocalVar)
|
||||||
{
|
{
|
||||||
|
useLocalVar = false;
|
||||||
var nativeToManaged = GenerateCppWrapperNativeToManaged(buildData, paramType, caller, out var managedTypeAsNative, null);
|
var nativeToManaged = GenerateCppWrapperNativeToManaged(buildData, paramType, caller, out var managedTypeAsNative, null);
|
||||||
string result;
|
string result;
|
||||||
if (!string.IsNullOrEmpty(nativeToManaged))
|
if (!string.IsNullOrEmpty(nativeToManaged))
|
||||||
{
|
{
|
||||||
result = string.Format(nativeToManaged, paramName);
|
result = string.Format(nativeToManaged, paramName);
|
||||||
if (managedTypeAsNative[managedTypeAsNative.Length - 1] == '*')
|
if (managedTypeAsNative[managedTypeAsNative.Length - 1] == '*' && !isOut)
|
||||||
{
|
{
|
||||||
// Pass pointer value
|
// Pass pointer value
|
||||||
}
|
}
|
||||||
@@ -117,6 +118,7 @@ namespace Flax.Build.Bindings
|
|||||||
result = string.Format(nativeToManaged, '*' + paramName);
|
result = string.Format(nativeToManaged, '*' + paramName);
|
||||||
contents.Append($" auto __param_{paramName} = {result};").AppendLine();
|
contents.Append($" auto __param_{paramName} = {result};").AppendLine();
|
||||||
result = $"&__param_{paramName}";
|
result = $"&__param_{paramName}";
|
||||||
|
useLocalVar = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -588,12 +590,12 @@ namespace Flax.Build.Bindings
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GenerateCppWrapperManagedToNative(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller, out string type, FunctionInfo functionInfo, out bool needLocalVariable)
|
private static string GenerateCppWrapperManagedToNative(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller, out string type, out ApiTypeInfo apiType, FunctionInfo functionInfo, out bool needLocalVariable)
|
||||||
{
|
{
|
||||||
needLocalVariable = false;
|
needLocalVariable = false;
|
||||||
|
|
||||||
// Register any API types usage
|
// Register any API types usage
|
||||||
var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
|
apiType = FindApiTypeInfo(buildData, typeInfo, caller);
|
||||||
CppReferencesFiles.Add(apiType?.File);
|
CppReferencesFiles.Add(apiType?.File);
|
||||||
if (typeInfo.GenericArgs != null)
|
if (typeInfo.GenericArgs != null)
|
||||||
{
|
{
|
||||||
@@ -608,7 +610,7 @@ namespace Flax.Build.Bindings
|
|||||||
if (typeInfo.IsArray)
|
if (typeInfo.IsArray)
|
||||||
{
|
{
|
||||||
var arrayType = new TypeInfo { Type = "Array", GenericArgs = new List<TypeInfo> { new TypeInfo(typeInfo) { IsArray = false } } };
|
var arrayType = new TypeInfo { Type = "Array", GenericArgs = new List<TypeInfo> { new TypeInfo(typeInfo) { IsArray = false } } };
|
||||||
var result = GenerateCppWrapperManagedToNative(buildData, arrayType, caller, out type, functionInfo, out needLocalVariable);
|
var result = GenerateCppWrapperManagedToNative(buildData, arrayType, caller, out type, out _, functionInfo, out needLocalVariable);
|
||||||
return result + ".Get()";
|
return result + ".Get()";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -967,7 +969,7 @@ namespace Flax.Build.Bindings
|
|||||||
separator = true;
|
separator = true;
|
||||||
|
|
||||||
CppParamsThatNeedConversion[i] = false;
|
CppParamsThatNeedConversion[i] = false;
|
||||||
CppParamsWrappersCache[i] = GenerateCppWrapperManagedToNative(buildData, parameterInfo.Type, caller, out var managedType, functionInfo, out CppParamsThatNeedLocalVariable[i]);
|
CppParamsWrappersCache[i] = GenerateCppWrapperManagedToNative(buildData, parameterInfo.Type, caller, out var managedType, out var apiType, functionInfo, out CppParamsThatNeedLocalVariable[i]);
|
||||||
|
|
||||||
// Out parameters that need additional converting will be converted at the native side (eg. object reference)
|
// Out parameters that need additional converting will be converted at the native side (eg. object reference)
|
||||||
var isOutWithManagedConverter = parameterInfo.IsOut && !string.IsNullOrEmpty(GenerateCSharpManagedToNativeConverter(buildData, parameterInfo.Type, caller));
|
var isOutWithManagedConverter = parameterInfo.IsOut && !string.IsNullOrEmpty(GenerateCSharpManagedToNativeConverter(buildData, parameterInfo.Type, caller));
|
||||||
@@ -985,7 +987,6 @@ namespace Flax.Build.Bindings
|
|||||||
if (parameterInfo.IsOut || isRefOut)
|
if (parameterInfo.IsOut || isRefOut)
|
||||||
{
|
{
|
||||||
bool convertOutputParameter = false;
|
bool convertOutputParameter = false;
|
||||||
var apiType = FindApiTypeInfo(buildData, parameterInfo.Type, caller);
|
|
||||||
if (apiType != null)
|
if (apiType != null)
|
||||||
{
|
{
|
||||||
// Non-POD structure passed as value (eg. it contains string or array inside)
|
// Non-POD structure passed as value (eg. it contains string or array inside)
|
||||||
@@ -1038,7 +1039,7 @@ namespace Flax.Build.Bindings
|
|||||||
contents.Append(", ");
|
contents.Append(", ");
|
||||||
separator = true;
|
separator = true;
|
||||||
|
|
||||||
GenerateCppWrapperManagedToNative(buildData, parameterInfo.Type, caller, out var managedType, functionInfo, out _);
|
GenerateCppWrapperManagedToNative(buildData, parameterInfo.Type, caller, out var managedType, out _, functionInfo, out _);
|
||||||
contents.Append(managedType);
|
contents.Append(managedType);
|
||||||
if (parameterInfo.IsRef || parameterInfo.IsOut || UsePassByReference(buildData, parameterInfo.Type, caller))
|
if (parameterInfo.IsRef || parameterInfo.IsOut || UsePassByReference(buildData, parameterInfo.Type, caller))
|
||||||
contents.Append('*');
|
contents.Append('*');
|
||||||
@@ -1336,7 +1337,7 @@ namespace Flax.Build.Bindings
|
|||||||
for (var i = 0; i < functionInfo.Parameters.Count; i++)
|
for (var i = 0; i < functionInfo.Parameters.Count; i++)
|
||||||
{
|
{
|
||||||
var parameterInfo = functionInfo.Parameters[i];
|
var parameterInfo = functionInfo.Parameters[i];
|
||||||
var paramValue = GenerateCppWrapperNativeToManagedParam(buildData, contents, parameterInfo.Type, parameterInfo.Name, classInfo, parameterInfo.IsOut);
|
var paramValue = GenerateCppWrapperNativeToManagedParam(buildData, contents, parameterInfo.Type, parameterInfo.Name, classInfo, parameterInfo.IsOut, out _);
|
||||||
contents.Append($" params[{i}] = {paramValue};").AppendLine();
|
contents.Append($" params[{i}] = {paramValue};").AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1728,7 +1729,8 @@ namespace Flax.Build.Bindings
|
|||||||
{
|
{
|
||||||
var paramType = eventInfo.Type.GenericArgs[i];
|
var paramType = eventInfo.Type.GenericArgs[i];
|
||||||
var paramName = "arg" + i;
|
var paramName = "arg" + i;
|
||||||
var paramValue = GenerateCppWrapperNativeToManagedParam(buildData, contents, paramType, paramName, classInfo, false);
|
var paramIsOut = paramType.IsRef && !paramType.IsConst;
|
||||||
|
var paramValue = GenerateCppWrapperNativeToManagedParam(buildData, contents, paramType, paramName, classInfo, paramIsOut, out CppParamsThatNeedConversion[i]);
|
||||||
contents.Append($" params[{i}] = {paramValue};").AppendLine();
|
contents.Append($" params[{i}] = {paramValue};").AppendLine();
|
||||||
}
|
}
|
||||||
if (eventInfo.IsStatic)
|
if (eventInfo.IsStatic)
|
||||||
@@ -1741,13 +1743,15 @@ namespace Flax.Build.Bindings
|
|||||||
for (var i = 0; i < paramsCount; i++)
|
for (var i = 0; i < paramsCount; i++)
|
||||||
{
|
{
|
||||||
var paramType = eventInfo.Type.GenericArgs[i];
|
var paramType = eventInfo.Type.GenericArgs[i];
|
||||||
if (paramType.IsRef && !paramType.IsConst)
|
var paramIsOut = paramType.IsRef && !paramType.IsConst;
|
||||||
|
if (paramIsOut)
|
||||||
{
|
{
|
||||||
// Convert value back from managed to native (could be modified there)
|
// Convert value back from managed to native (could be modified there)
|
||||||
paramType.IsRef = false;
|
paramType.IsRef = false;
|
||||||
var managedToNative = GenerateCppWrapperManagedToNative(buildData, paramType, classInfo, out var managedType, null, out _);
|
var managedToNative = GenerateCppWrapperManagedToNative(buildData, paramType, classInfo, out var managedType, out var apiType, null, out _);
|
||||||
var passAsParamPtr = managedType.EndsWith("*");
|
var passAsParamPtr = managedType.EndsWith("*");
|
||||||
var paramValue = $"({managedType}{(passAsParamPtr ? "" : "*")})params[{i}]";
|
var useLocalVarPointer = CppParamsThatNeedConversion[i] && !apiType.IsValueType;
|
||||||
|
var paramValue = useLocalVarPointer ? $"*({managedType}{(passAsParamPtr ? "" : "*")}*)params[{i}]" : $"({managedType}{(passAsParamPtr ? "" : "*")})params[{i}]";
|
||||||
if (!string.IsNullOrEmpty(managedToNative))
|
if (!string.IsNullOrEmpty(managedToNative))
|
||||||
{
|
{
|
||||||
if (!passAsParamPtr)
|
if (!passAsParamPtr)
|
||||||
@@ -2468,7 +2472,7 @@ namespace Flax.Build.Bindings
|
|||||||
if (typeInfo.IsArray)
|
if (typeInfo.IsArray)
|
||||||
{
|
{
|
||||||
typeInfo.IsArray = false;
|
typeInfo.IsArray = false;
|
||||||
header.Append($"{GenerateCppWrapperNativeToVariantMethodName(typeInfo)}Array(const {typeInfo}* v, const int32 length)").AppendLine();
|
header.Append($"{GenerateCppWrapperNativeToVariantMethodName(typeInfo)}Array({(typeInfo.IsConst ? "const " : "")}{typeInfo}* v, const int32 length)").AppendLine();
|
||||||
header.Append('{').AppendLine();
|
header.Append('{').AppendLine();
|
||||||
header.Append(" Variant result;").AppendLine();
|
header.Append(" Variant result;").AppendLine();
|
||||||
header.Append(" result.SetType(VariantType(VariantType::Array));").AppendLine();
|
header.Append(" result.SetType(VariantType(VariantType::Array));").AppendLine();
|
||||||
@@ -2481,7 +2485,7 @@ namespace Flax.Build.Bindings
|
|||||||
else if (typeInfo.Type == "Array" && typeInfo.GenericArgs != null)
|
else if (typeInfo.Type == "Array" && typeInfo.GenericArgs != null)
|
||||||
{
|
{
|
||||||
var valueType = typeInfo.GenericArgs[0];
|
var valueType = typeInfo.GenericArgs[0];
|
||||||
header.Append($"{GenerateCppWrapperNativeToVariantMethodName(valueType)}Array(const {valueType}* v, const int32 length)").AppendLine();
|
header.Append($"{GenerateCppWrapperNativeToVariantMethodName(valueType)}Array({(typeInfo.IsConst ? "const " : "")}{valueType}* v, const int32 length)").AppendLine();
|
||||||
header.Append('{').AppendLine();
|
header.Append('{').AppendLine();
|
||||||
header.Append(" Variant result;").AppendLine();
|
header.Append(" Variant result;").AppendLine();
|
||||||
header.Append(" result.SetType(VariantType(VariantType::Array));").AppendLine();
|
header.Append(" result.SetType(VariantType(VariantType::Array));").AppendLine();
|
||||||
@@ -2646,7 +2650,7 @@ namespace Flax.Build.Bindings
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
CppNonPodTypesConvertingGeneration = true;
|
CppNonPodTypesConvertingGeneration = true;
|
||||||
var wrapper = GenerateCppWrapperManagedToNative(buildData, fieldInfo.Type, apiType, out _, null, out _);
|
var wrapper = GenerateCppWrapperManagedToNative(buildData, fieldInfo.Type, apiType, out _, out _, null, out _);
|
||||||
CppNonPodTypesConvertingGeneration = false;
|
CppNonPodTypesConvertingGeneration = false;
|
||||||
|
|
||||||
if (fieldInfo.Type.IsArray)
|
if (fieldInfo.Type.IsArray)
|
||||||
@@ -2730,7 +2734,7 @@ namespace Flax.Build.Bindings
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
CppNonPodTypesConvertingGeneration = true;
|
CppNonPodTypesConvertingGeneration = true;
|
||||||
var wrapper = GenerateCppWrapperManagedToNative(buildData, fieldInfo.Type, apiType, out _, null, out _);
|
var wrapper = GenerateCppWrapperManagedToNative(buildData, fieldInfo.Type, apiType, out _, out _, null, out _);
|
||||||
CppNonPodTypesConvertingGeneration = false;
|
CppNonPodTypesConvertingGeneration = false;
|
||||||
|
|
||||||
if (fieldInfo.Type.IsArray)
|
if (fieldInfo.Type.IsArray)
|
||||||
|
|||||||
Reference in New Issue
Block a user