Merge remote-tracking branch 'origin/master' into 1.13
# Conflicts: # Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp # Source/Engine/Renderer/Utils/GlobalSignDistanceFieldPass.cpp # Source/Engine/Scripting/Internal/InternalCalls.h # Source/Engine/Scripting/Internal/ManagedDictionary.cpp # Source/Engine/Scripting/Internal/ManagedDictionary.h # Source/Engine/Scripting/ScriptingObject.cpp # Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
This commit is contained in:
@@ -52,7 +52,7 @@ namespace FlaxEditor.Content
|
||||
/// <inheritdoc />
|
||||
public override bool CanDrawThumbnail(ThumbnailRequest request)
|
||||
{
|
||||
return _preview.HasLoadedAssets && ThumbnailsModule.HasMinimumQuality((CubeTexture)request.Asset);
|
||||
return _preview.HasContentLoaded && ThumbnailsModule.HasMinimumQuality((CubeTexture)request.Asset);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace FlaxEditor.Content
|
||||
/// <inheritdoc />
|
||||
public override bool CanDrawThumbnail(ThumbnailRequest request)
|
||||
{
|
||||
return _preview.HasLoadedAssets && ThumbnailsModule.HasMinimumQuality((MaterialInstance)request.Asset);
|
||||
return _preview.HasContentLoaded && ThumbnailsModule.HasMinimumQuality((MaterialInstance)request.Asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace FlaxEditor.Content
|
||||
/// <inheritdoc />
|
||||
public override bool CanDrawThumbnail(ThumbnailRequest request)
|
||||
{
|
||||
return _preview.HasLoadedAssets && ThumbnailsModule.HasMinimumQuality((Material)request.Asset);
|
||||
return _preview.HasContentLoaded && ThumbnailsModule.HasMinimumQuality((Material)request.Asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace FlaxEditor.Content
|
||||
/// <inheritdoc />
|
||||
public override bool CanDrawThumbnail(ThumbnailRequest request)
|
||||
{
|
||||
return _preview.HasLoadedAssets && ThumbnailsModule.HasMinimumQuality((Model)request.Asset);
|
||||
return _preview.HasContentLoaded && ThumbnailsModule.HasMinimumQuality((Model)request.Asset);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace FlaxEditor.Content
|
||||
return false;
|
||||
|
||||
// Ensure assets are ready to be used
|
||||
if (!_preview.HasLoadedAssets)
|
||||
if (!_preview.HasContentLoaded)
|
||||
return false;
|
||||
var asset = (ParticleEmitter)request.Asset;
|
||||
if (!asset.IsLoaded)
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace FlaxEditor.Content
|
||||
return false;
|
||||
|
||||
// Ensure assets are ready to be used
|
||||
if (!_preview.HasLoadedAssets)
|
||||
if (!_preview.HasContentLoaded)
|
||||
return false;
|
||||
var asset = (ParticleSystem)request.Asset;
|
||||
if (!asset.IsLoaded)
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace FlaxEditor.Content
|
||||
/// <inheritdoc />
|
||||
public override bool CanDrawThumbnail(ThumbnailRequest request)
|
||||
{
|
||||
if (!_preview.HasLoadedAssets)
|
||||
if (!_preview.HasContentLoaded)
|
||||
return false;
|
||||
|
||||
// Check if asset is streamed enough
|
||||
@@ -140,7 +140,7 @@ namespace FlaxEditor.Content
|
||||
actor is SpriteRender ||
|
||||
actor is TextRender)
|
||||
{
|
||||
actorBounds = actor.EditorBox;
|
||||
actorBounds = actor.EditorBoundingBox;
|
||||
}
|
||||
if (actorBounds != BoundingBox.Empty)
|
||||
{
|
||||
@@ -182,7 +182,7 @@ namespace FlaxEditor.Content
|
||||
// Update some actors data (some actor types update bounds/data later but its required to be done before rendering)
|
||||
var bounds = BoundingBox.Empty;
|
||||
Prepare(_preview.Instance, ref bounds);
|
||||
//bounds = _preview.Instance.EditorBoxChildren;
|
||||
//bounds = _preview.Instance.EditorBoundingBoxWithChildren;
|
||||
|
||||
// Auto fit actor to camera
|
||||
if (bounds != BoundingBox.Empty)
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace FlaxEditor.Content
|
||||
/// <inheritdoc />
|
||||
public override bool CanDrawThumbnail(ThumbnailRequest request)
|
||||
{
|
||||
return _preview.HasLoadedAssets && ThumbnailsModule.HasMinimumQuality((SkinnedModel)request.Asset);
|
||||
return _preview.HasContentLoaded && ThumbnailsModule.HasMinimumQuality((SkinnedModel)request.Asset);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -802,7 +802,9 @@ int32 GameCookerImpl::ThreadFunction()
|
||||
Build();
|
||||
}
|
||||
|
||||
mutex.Lock();
|
||||
ThreadCond.Wait(mutex);
|
||||
mutex.Unlock();
|
||||
}
|
||||
|
||||
IsThreadRunning = false;
|
||||
|
||||
@@ -58,9 +58,9 @@ namespace FlaxEditor.CustomEditors
|
||||
if (targetType.Type == typeof(object) && values.Count > 0 && values[0] != null && !values.HasDifferentTypes)
|
||||
return CreateEditor(TypeUtils.GetObjectType(values[0]), canUseRefPicker);
|
||||
|
||||
// Special case if property is interface but the value is implemented as Scripting Object that should use reference picker
|
||||
if (targetType.IsInterface && canUseRefPicker && values.Count > 0 && values[0] is FlaxEngine.Object)
|
||||
return new DummyEditor();
|
||||
// Special case if property is interface but the value is implemented as Scripting Object that should use reference picker (or all interface impl are by Scripting Objects)
|
||||
if (canUseRefPicker && targetType.IsInterface && values.Count > 0 && values[0] is FlaxEngine.Object)
|
||||
return new FlaxObjectRefEditor();
|
||||
|
||||
// Use editor for the property type
|
||||
return CreateEditor(targetType, canUseRefPicker);
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
{
|
||||
if (value is NavMeshBoundsVolume volume)
|
||||
{
|
||||
Navigation.BuildNavMesh(volume.Box, volume.Scene);
|
||||
Navigation.BuildNavMesh(volume.BoundingBox, volume.Scene);
|
||||
Editor.Instance.Scene.MarkSceneEdited(volume.Scene);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
var patchesCount = terrain.PatchesCount;
|
||||
var chunkSize = terrain.ChunkSize;
|
||||
var resolution = terrain.Scale;
|
||||
var totalSize = terrain.Box.Size;
|
||||
var totalSize = terrain.BoundingBox.Size;
|
||||
string text = string.Format("Patches: {0}\nTotal Chunks: {1}\nChunk Size: {2}\nResolution: {3}m x {4}m\nTotal size: {5}km x {6}km",
|
||||
patchesCount,
|
||||
patchesCount * 16,
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
var overrideEditor = overrideEditorType != null ? (CustomEditor)Activator.CreateInstance(overrideEditorType) : null;
|
||||
var property = panel.AddPropertyItem(new DictionaryItemLabel(this, key));
|
||||
var itemLayout = useSharedLayout ? (LayoutElementsContainer)property : property.VerticalPanel();
|
||||
itemLayout.Object(new DictionaryValueContainer(valuesType, key, Values), overrideEditor);
|
||||
itemLayout.Object(new DictionaryValueContainer(valuesType, key, Values, attributes), overrideEditor);
|
||||
if (_readOnly && itemLayout.Children.Count > 0)
|
||||
GenericEditor.OnReadOnlyProperty(itemLayout);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEditor.CustomEditors.Elements;
|
||||
using FlaxEditor.GUI;
|
||||
@@ -48,7 +49,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
public IPresenterOwner PresenterContext;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the allowed objects type (given type and all subclasses). Must be <see cref="Object"/> type of any subclass.
|
||||
/// Gets or sets the allowed objects type (given type and all subclasses). Must be <see cref="Object"/> type of any subclass or a scripting interface.
|
||||
/// </summary>
|
||||
public ScriptType Type
|
||||
{
|
||||
@@ -57,11 +58,12 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
{
|
||||
if (_type == value)
|
||||
return;
|
||||
if (value == ScriptType.Null || (value.Type != typeof(Object) && !value.IsSubclassOf(ScriptType.Object)))
|
||||
if (value == ScriptType.Null || (!value.IsInterface && value.Type != typeof(Object) && !value.IsSubclassOf(ScriptType.Object)))
|
||||
throw new ArgumentException(string.Format("Invalid type for FlaxObjectRefEditor. Input type: {0}", value != ScriptType.Null ? value.TypeName : "null"));
|
||||
|
||||
_type = value;
|
||||
_supportsPickDropDown = new ScriptType(typeof(Actor)).IsAssignableFrom(value) ||
|
||||
_supportsPickDropDown = value.IsInterface ||
|
||||
new ScriptType(typeof(Actor)).IsAssignableFrom(value) ||
|
||||
new ScriptType(typeof(Script)).IsAssignableFrom(value);
|
||||
|
||||
// Deselect value if it's not valid now
|
||||
@@ -149,41 +151,38 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
protected virtual bool IsValid(Object obj)
|
||||
{
|
||||
var type = TypeUtils.GetObjectType(obj);
|
||||
return obj == null || _type.IsAssignableFrom(type) && (CheckValid == null || CheckValid(obj, type));
|
||||
return obj == null || (!_type.IsInterface || obj is SceneObject) && _type.IsAssignableFrom(type) && (CheckValid == null || CheckValid(obj, type));
|
||||
}
|
||||
|
||||
private void ShowDropDownMenu()
|
||||
{
|
||||
Focus();
|
||||
if (new ScriptType(typeof(Actor)).IsAssignableFrom(_type))
|
||||
var pos = new Float2(0, Height);
|
||||
if (_type.IsInterface)
|
||||
{
|
||||
ActorSearchPopup.Show(this, new Float2(0, Height), IsValid, actor =>
|
||||
{
|
||||
Value = actor;
|
||||
RootWindow.Focus();
|
||||
Focus();
|
||||
}, PresenterContext);
|
||||
SceneObjectSearchPopup.Show(this, pos, IsValid, SetDropDownResult, PresenterContext);
|
||||
}
|
||||
else if (new ScriptType(typeof(Actor)).IsAssignableFrom(_type))
|
||||
{
|
||||
ActorSearchPopup.Show(this, pos, IsValid, SetDropDownResult, PresenterContext);
|
||||
}
|
||||
else if (new ScriptType(typeof(Control)).IsAssignableFrom(_type))
|
||||
{
|
||||
ActorSearchPopup.Show(this, new Float2(0, Height), IsValid, actor =>
|
||||
{
|
||||
Value = actor as UIControl;
|
||||
RootWindow.Focus();
|
||||
Focus();
|
||||
}, PresenterContext);
|
||||
ActorSearchPopup.Show(this, pos, IsValid, actor => { SetDropDownResult(actor as UIControl); }, PresenterContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptSearchPopup.Show(this, new Float2(0, Height), IsValid, script =>
|
||||
{
|
||||
Value = script;
|
||||
RootWindow.Focus();
|
||||
Focus();
|
||||
}, PresenterContext);
|
||||
ScriptSearchPopup.Show(this, pos, IsValid, SetDropDownResult, PresenterContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetDropDownResult(Object value)
|
||||
{
|
||||
Value = value;
|
||||
RootWindow.Focus();
|
||||
Focus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when value gets changed.
|
||||
/// </summary>
|
||||
@@ -218,7 +217,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
{
|
||||
// Draw info
|
||||
Render2D.PushClip(nameRect);
|
||||
Render2D.DrawText(style.FontMedium, Type != null ? $"Multiple Values ({Utilities.Utils.GetPropertyNameUI(Type.ToString())})" : "-", nameRect, isEnabled ? style.ForegroundGrey : style.ForegroundGrey.AlphaMultiplied(0.75f), TextAlignment.Near, TextAlignment.Center);
|
||||
Render2D.DrawText(style.FontMedium, Type != null ? $"Multiple Values ({Utilities.Utils.GetTypeNameUI(_type)})" : "-", nameRect, isEnabled ? style.ForegroundGrey : style.ForegroundGrey.AlphaMultiplied(0.75f), TextAlignment.Near, TextAlignment.Center);
|
||||
Render2D.PopClip();
|
||||
}
|
||||
else if (isSelected)
|
||||
@@ -235,7 +234,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
{
|
||||
// Draw info
|
||||
Render2D.PushClip(nameRect);
|
||||
Render2D.DrawText(style.FontMedium, Type != null ? $"None ({Utilities.Utils.GetPropertyNameUI(Type.ToString())})" : "-", nameRect, isEnabled ? style.ForegroundGrey : style.ForegroundGrey.AlphaMultiplied(0.75f), TextAlignment.Near, TextAlignment.Center);
|
||||
Render2D.DrawText(style.FontMedium, Type != null ? $"None ({Utilities.Utils.GetTypeNameUI(_type)})" : "-", nameRect, isEnabled ? style.ForegroundGrey : style.ForegroundGrey.AlphaMultiplied(0.75f), TextAlignment.Near, TextAlignment.Center);
|
||||
Render2D.PopClip();
|
||||
}
|
||||
|
||||
@@ -662,4 +661,58 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default implementation of the inspector used to edit reference to the <see cref="ScriptingObjectInterfaceReference{T}"/>.
|
||||
/// </summary>
|
||||
internal sealed class ScriptingObjectInterfaceReferenceEditor : CustomEditor
|
||||
{
|
||||
private CustomElement<FlaxObjectRefPickerControl> _element;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DisplayStyle Style => DisplayStyle.Inline;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Initialize(LayoutElementsContainer layout)
|
||||
{
|
||||
if (!HasDifferentTypes)
|
||||
{
|
||||
_element = layout.Custom<FlaxObjectRefPickerControl>();
|
||||
_element.CustomControl.PresenterContext = Presenter.Owner;
|
||||
_element.CustomControl.Type = new ScriptType(Values.Type.GetGenericArguments()[0]);
|
||||
_element.CustomControl.ValueChanged += OnValueChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnValueChanged()
|
||||
{
|
||||
// Set value
|
||||
var obj = _element.CustomControl.Value;
|
||||
var v = Values.Type.CreateInstance();
|
||||
var objectField = v.GetType().GetField("_object", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
objectField.SetValue(v, obj);
|
||||
SetValue(v);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
|
||||
var differentValues = HasDifferentValues;
|
||||
_element.CustomControl.DifferentValues = differentValues;
|
||||
if (!differentValues)
|
||||
{
|
||||
// Get value
|
||||
var v = Values[0];
|
||||
var obj = v as Object;
|
||||
if (v != null && obj == null)
|
||||
{
|
||||
var objectField = v.GetType().GetField("_object", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
obj = objectField.GetValue(v) as Object;
|
||||
}
|
||||
_element.CustomControl.Value = obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -716,19 +716,18 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
if (value == null)
|
||||
{
|
||||
// Check if it's an object type that can be created in editor
|
||||
if (type != ScriptMemberInfo.Null)
|
||||
if (type != ScriptMemberInfo.Null && CanEditValue)
|
||||
{
|
||||
ScriptType[] types = null;
|
||||
if (type.IsAbstract || type.IsInterface)
|
||||
{
|
||||
// Show picker with all types that implement specific class/interface but are not abstract
|
||||
types = Editor.Instance.CodeEditing.All.Get().Where(x => !x.IsAbstract && x.CanCreateInstance && type.IsAssignableFrom(x)).ToArray();
|
||||
types = Editor.Instance.CodeEditing.All.Get().Where(x => !x.IsAbstract && !x.IsScriptingObject && x.CanCreateInstance && type.IsAssignableFrom(x)).ToArray();
|
||||
}
|
||||
else if (type.CanCreateInstance)
|
||||
{
|
||||
types = [type];
|
||||
}
|
||||
|
||||
if (types != null && types.Length != 0)
|
||||
{
|
||||
layout = layout.Space(20);
|
||||
@@ -759,7 +758,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
layout.Label("<null>");
|
||||
return;
|
||||
}
|
||||
if (!type.IsArray && !type.IsStructure && !type.IsScriptingObject && (type.IsAbstract || type.IsInterface) && value.GetType() != type.Type && layout is GroupElement group)
|
||||
if (!type.IsArray && !type.IsStructure && !type.IsScriptingObject && (type.IsAbstract || type.IsInterface) && value.GetType() != type.Type && layout is GroupElement group && CanEditValue)
|
||||
{
|
||||
// Add button to unset the value to null (eg. to edit it to different type)
|
||||
var button = group.AddHeaderButton("Reset value to null", 0, FlaxEngine.GUI.Style.Current.Cross);
|
||||
|
||||
@@ -14,6 +14,8 @@ namespace FlaxEditor.CustomEditors
|
||||
[HideInEditor]
|
||||
public class DictionaryValueContainer : ValueContainer
|
||||
{
|
||||
private readonly object[] _attributes;
|
||||
|
||||
/// <summary>
|
||||
/// The key in the collection.
|
||||
/// </summary>
|
||||
@@ -24,9 +26,11 @@ namespace FlaxEditor.CustomEditors
|
||||
/// </summary>
|
||||
/// <param name="elementType">Type of the collection elements.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
public DictionaryValueContainer(ScriptType elementType, object key)
|
||||
/// <param name="attributes">The dictionary property attributes to inherit.</param>
|
||||
public DictionaryValueContainer(ScriptType elementType, object key, object[] attributes = null)
|
||||
: base(ScriptMemberInfo.Null, elementType)
|
||||
{
|
||||
_attributes = attributes;
|
||||
Key = key;
|
||||
}
|
||||
|
||||
@@ -36,8 +40,9 @@ namespace FlaxEditor.CustomEditors
|
||||
/// <param name="elementType">Type of the collection elements.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="values">The collection values.</param>
|
||||
public DictionaryValueContainer(ScriptType elementType, object key, ValueContainer values)
|
||||
: this(elementType, key)
|
||||
/// <param name="attributes">The dictionary property attributes to inherit.</param>
|
||||
public DictionaryValueContainer(ScriptType elementType, object key, ValueContainer values, object[] attributes = null)
|
||||
: this(elementType, key, attributes)
|
||||
{
|
||||
Capacity = values.Count;
|
||||
for (int i = 0; i < values.Count; i++)
|
||||
@@ -123,5 +128,11 @@ namespace FlaxEditor.CustomEditors
|
||||
_hasReferenceValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object[] GetAttributes()
|
||||
{
|
||||
return _attributes ?? base.GetAttributes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,6 +297,11 @@ namespace FlaxEditor.CustomEditors
|
||||
else if (Type.Type == typeof(long))
|
||||
_defaultValue = Convert.ToInt64(_defaultValue);
|
||||
}
|
||||
else if (_defaultValue == null && Type.IsValueType)
|
||||
{
|
||||
// Use zero value for value-types that have null as default value for some reason
|
||||
_defaultValue = Type.CreateInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (instanceValues._hasReferenceValue)
|
||||
|
||||
@@ -501,8 +501,10 @@ namespace FlaxEditor.GUI.Docking
|
||||
{
|
||||
scrPanel.GetChild(i).Parent = splitterParent;
|
||||
}
|
||||
Assert.IsTrue(scrPanel.ChildrenCount == 0);
|
||||
Assert.IsTrue(splitterParent.ChildrenCount == srcPanelChildrenCount);
|
||||
if (scrPanel.ChildrenCount != 0 || splitterParent.ChildrenCount == srcPanelChildrenCount)
|
||||
{
|
||||
Editor.LogError("Broken dock panel layout!");
|
||||
}
|
||||
|
||||
// Delete
|
||||
splitter.Dispose();
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace FlaxEditor.GUI
|
||||
public float SortScore;
|
||||
|
||||
/// <summary>
|
||||
/// Wether the query highlights should be draw.
|
||||
/// Whether the query highlights should be drawn.
|
||||
/// </summary>
|
||||
public bool DrawHighlights = true;
|
||||
|
||||
@@ -261,6 +261,11 @@ namespace FlaxEditor.GUI
|
||||
/// </summary>
|
||||
public readonly VerticalPanel ItemsPanel;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of panels with item categories.
|
||||
/// </summary>
|
||||
public IEnumerable<DropPanel> CategoryPanels => (IEnumerable<DropPanel>)_categoryPanels ?? Array.Empty<DropPanel>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemsListContextMenu"/> class.
|
||||
/// </summary>
|
||||
@@ -504,6 +509,12 @@ namespace FlaxEditor.GUI
|
||||
category.Visible = true;
|
||||
category.Close(false);
|
||||
}
|
||||
|
||||
if (_categoryPanels.Count == 1 && items.Count == 1)
|
||||
{
|
||||
// Expand the only category if there are no items outside of it
|
||||
_categoryPanels[0].Open(false);
|
||||
}
|
||||
}
|
||||
|
||||
_searchBox?.Clear();
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using FlaxEditor.Windows;
|
||||
using FlaxEditor.Windows.Assets;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
using FlaxEngine.Utilities;
|
||||
|
||||
namespace FlaxEditor.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Popup that shows the list of scene objects to pick. Supports searching and basic type filtering.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.GUI.ItemsListContextMenu" />
|
||||
public class SceneObjectSearchPopup : ItemsListContextMenu
|
||||
{
|
||||
/// <summary>
|
||||
/// The scene object item.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.GUI.ItemsListContextMenu.Item" />
|
||||
public class SceneObjectItemView : Item
|
||||
{
|
||||
private SceneObject _object;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the scene object.
|
||||
/// </summary>
|
||||
public SceneObject Object => _object;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SceneObjectItemView"/> class.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object.</param>
|
||||
public SceneObjectItemView(SceneObject obj)
|
||||
{
|
||||
_object = obj;
|
||||
Category = obj is Actor ? "Actors" : "Scripts";
|
||||
if (obj is Script script)
|
||||
{
|
||||
var type = TypeUtils.GetObjectType(script);
|
||||
Name = script.Actor ? $"{type.Name} ({script.Actor.Name})" : type.Name;
|
||||
}
|
||||
else if (obj is Actor actor)
|
||||
{
|
||||
Name = actor.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
Name = obj.ToString();
|
||||
}
|
||||
TooltipText = Utilities.Utils.GetTooltip(obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
_object = null;
|
||||
base.OnDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates if the given scene object item can be used to pick it.
|
||||
/// </summary>
|
||||
/// <param name="obj">The scene object.</param>
|
||||
/// <returns>True if is valid.</returns>
|
||||
public delegate bool IsValidDelegate(SceneObject obj);
|
||||
|
||||
private IsValidDelegate _isValid;
|
||||
private Action<SceneObject> _selected;
|
||||
|
||||
private SceneObjectSearchPopup(IsValidDelegate isValid, Action<SceneObject> selected, CustomEditors.IPresenterOwner context)
|
||||
{
|
||||
_isValid = isValid;
|
||||
_selected = selected;
|
||||
|
||||
ItemClicked += OnItemClicked;
|
||||
|
||||
if (context is PropertiesWindow || context == null)
|
||||
{
|
||||
// TODO: use async thread to search scenes
|
||||
for (int i = 0; i < Level.ScenesCount; i++)
|
||||
{
|
||||
Find(Level.GetScene(i));
|
||||
}
|
||||
}
|
||||
else if (context is PrefabWindow prefabWindow)
|
||||
{
|
||||
Find(prefabWindow.Graph.MainActor);
|
||||
}
|
||||
|
||||
SortItems();
|
||||
}
|
||||
|
||||
private void OnItemClicked(Item item)
|
||||
{
|
||||
_selected(((SceneObjectItemView)item).Object);
|
||||
}
|
||||
|
||||
private void Find(Actor actor)
|
||||
{
|
||||
if (!actor)
|
||||
return;
|
||||
|
||||
if (_isValid(actor))
|
||||
AddItem(new SceneObjectItemView(actor));
|
||||
|
||||
for (int i = 0; i < actor.ScriptsCount; i++)
|
||||
{
|
||||
var script = actor.GetScript(i);
|
||||
if (_isValid(script))
|
||||
AddItem(new SceneObjectItemView(script));
|
||||
}
|
||||
|
||||
for (int i = 0; i < actor.ChildrenCount; i++)
|
||||
{
|
||||
Find(actor.GetChild(i));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the popup.
|
||||
/// </summary>
|
||||
/// <param name="showTarget">The show target.</param>
|
||||
/// <param name="showTargetLocation">The show target location.</param>
|
||||
/// <param name="isValid">Event called to check if a given scene object item is valid to be used.</param>
|
||||
/// <param name="selected">Event called on scene object item pick.</param>
|
||||
/// <param name="context">The presenter owner context (i.e. PrefabWindow, PropertiesWindow).</param>
|
||||
/// <returns>The dialog.</returns>
|
||||
public static SceneObjectSearchPopup Show(Control showTarget, Float2 showTargetLocation, IsValidDelegate isValid, Action<SceneObject> selected, CustomEditors.IPresenterOwner context)
|
||||
{
|
||||
var popup = new SceneObjectSearchPopup(isValid, selected, context);
|
||||
popup.Show(showTarget, showTargetLocation);
|
||||
return popup;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
_isValid = null;
|
||||
_selected = null;
|
||||
base.OnDestroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,7 +128,7 @@ namespace FlaxEditor.Gizmo
|
||||
{
|
||||
if (_selectionParents[i] is ActorNode actorNode)
|
||||
{
|
||||
var b = actorNode.Actor.EditorBoxChildren;
|
||||
var b = actorNode.Actor.EditorBoundingBoxWithChildren;
|
||||
BoundingBox.Merge(ref editorBounds, ref b, out editorBounds);
|
||||
bottomToCenter = Mathf.Min(bottomToCenter, actorNode.Actor.Position.Y - editorBounds.Minimum.Y);
|
||||
}
|
||||
@@ -299,7 +299,7 @@ namespace FlaxEditor.Gizmo
|
||||
{
|
||||
if (_selectionParents[i] is ActorNode actorNode)
|
||||
{
|
||||
bounds = BoundingBox.Merge(bounds, actorNode.Actor.BoxWithChildren);
|
||||
bounds = BoundingBox.Merge(bounds, actorNode.Actor.BoundingBoxWithChildren);
|
||||
navigationDirty |= actorNode.AffectsNavigationWithChildren;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace FlaxEngine.Gizmo;
|
||||
/// </summary>
|
||||
public sealed class ViewportRubberBandSelector
|
||||
{
|
||||
private bool _isMosueCaptured;
|
||||
private bool _isMouseCaptured;
|
||||
private bool _isRubberBandSpanning;
|
||||
private bool _tryStartRubberBand;
|
||||
private Float2 _cachedStartingMousePosition;
|
||||
@@ -53,9 +53,9 @@ public sealed class ViewportRubberBandSelector
|
||||
/// <returns>Returns true if rubber band is currently spanning</returns>
|
||||
public bool ReleaseRubberBandSelection()
|
||||
{
|
||||
if (_isMosueCaptured)
|
||||
if (_isMouseCaptured)
|
||||
{
|
||||
_isMosueCaptured = false;
|
||||
_isMouseCaptured = false;
|
||||
_owner.Viewport.EndMouseCapture();
|
||||
}
|
||||
if (_tryStartRubberBand)
|
||||
@@ -99,9 +99,9 @@ public sealed class ViewportRubberBandSelector
|
||||
_rubberBandRect.Height = mousePosition.Y - _cachedStartingMousePosition.Y;
|
||||
if (_lastRubberBandRect != _rubberBandRect)
|
||||
{
|
||||
if (!_isMosueCaptured)
|
||||
if (!_isMouseCaptured)
|
||||
{
|
||||
_isMosueCaptured = true;
|
||||
_isMouseCaptured = true;
|
||||
_owner.Viewport.StartMouseCapture();
|
||||
}
|
||||
UpdateRubberBand();
|
||||
@@ -182,7 +182,7 @@ public sealed class ViewportRubberBandSelector
|
||||
var a = node.Actor;
|
||||
|
||||
// Skip actor if outside of view frustum
|
||||
var actorBox = a.EditorBox;
|
||||
var actorBox = a.EditorBoundingBox;
|
||||
if (projection.FrustumCull(ref actorBox) == ContainmentType.Disjoint)
|
||||
continue;
|
||||
|
||||
@@ -263,9 +263,9 @@ public sealed class ViewportRubberBandSelector
|
||||
/// <returns>True if rubber band was active before stopping.</returns>
|
||||
public bool StopRubberBand()
|
||||
{
|
||||
if (_isMosueCaptured)
|
||||
if (_isMouseCaptured)
|
||||
{
|
||||
_isMosueCaptured = false;
|
||||
_isMouseCaptured = false;
|
||||
_owner.Viewport.EndMouseCapture();
|
||||
}
|
||||
var result = _tryStartRubberBand;
|
||||
|
||||
@@ -333,7 +333,7 @@ DEFINE_INTERNAL_CALL(void) EditorInternal_GetCollisionWires(CollisionData* colli
|
||||
DEFINE_INTERNAL_CALL(void) EditorInternal_GetEditorBoxWithChildren(Actor* obj, BoundingBox* result)
|
||||
{
|
||||
INTERNAL_CALL_CHECK(obj);
|
||||
*result = obj->GetEditorBoxChildren();
|
||||
*result = obj->GetEditorBoundingBoxWithChildren();
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void) EditorInternal_SetOptions(ManagedEditor::InternalOptions* options)
|
||||
|
||||
@@ -244,7 +244,7 @@ namespace FlaxEditor.Modules
|
||||
// Auto NavMesh rebuild
|
||||
if (!isPlayMode && options.General.AutoRebuildNavMesh && actor.Scene && node.AffectsNavigationWithChildren)
|
||||
{
|
||||
var bounds = actor.BoxWithChildren;
|
||||
var bounds = actor.BoundingBoxWithChildren;
|
||||
Navigation.BuildNavMesh(bounds, options.General.AutoRebuildNavMeshTimeoutMs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,10 @@ namespace FlaxEditor.Options
|
||||
[EditorDisplay("Common"), EditorOrder(200)]
|
||||
public InputBinding LockFocusSelection = new InputBinding(KeyboardKeys.F, KeyboardKeys.Shift);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Ctrl+Alpha0")]
|
||||
[EditorDisplay("Common"), EditorOrder(201)]
|
||||
public InputBinding ShowEditorContents = new InputBinding(KeyboardKeys.Alpha0, KeyboardKeys.Control);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Ctrl+F")]
|
||||
[EditorDisplay("Common"), EditorOrder(210)]
|
||||
public InputBinding Search = new InputBinding(KeyboardKeys.F, KeyboardKeys.Control);
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace FlaxEditor.SceneGraph
|
||||
/// <returns>The points to use if the actor can be selected.</returns>
|
||||
public virtual Vector3[] GetActorSelectionPoints()
|
||||
{
|
||||
return Actor.EditorBox.GetCorners();
|
||||
return Actor.EditorBoundingBox.GetCorners();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -555,7 +555,7 @@ namespace FlaxEditor.SceneGraph.Actors
|
||||
var options = Editor.Instance.Options.Options.General;
|
||||
if (options.AutoRebuildNavMesh)
|
||||
{
|
||||
Navigation.BuildNavMesh(collider.Box, options.AutoRebuildNavMeshTimeoutMs);
|
||||
Navigation.BuildNavMesh(collider.BoundingBox, options.AutoRebuildNavMeshTimeoutMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -572,7 +572,7 @@ namespace FlaxEditor.SceneGraph.Actors
|
||||
var viewBounds = sceneContext.Viewport.ViewFrustum;
|
||||
foreach (var s in splines)
|
||||
{
|
||||
var contains = viewBounds.Contains(s.EditorBox);
|
||||
var contains = viewBounds.Contains(s.EditorBoundingBox);
|
||||
if (contains == ContainmentType.Contains || contains == ContainmentType.Intersects)
|
||||
result.Add(s);
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ namespace FlaxEditor.SceneGraph.Actors
|
||||
|
||||
private void CreateSphere(StaticModel actor, Spawner spawner, bool singleNode)
|
||||
{
|
||||
var bounds = actor.Sphere;
|
||||
var bounds = actor.BoundingSphere;
|
||||
var collider = new SphereCollider
|
||||
{
|
||||
Transform = actor.Transform,
|
||||
@@ -336,10 +336,10 @@ namespace FlaxEditor.SceneGraph.Actors
|
||||
var collider = new CapsuleCollider
|
||||
{
|
||||
Transform = actor.Transform,
|
||||
Position = actor.Box.Center,
|
||||
Position = actor.BoundingBox.Center,
|
||||
|
||||
// Size the capsule to best fit the actor
|
||||
Radius = (float)actor.Sphere.Radius / Mathf.Max((float)actor.Scale.MaxValue, 0.0001f) * 0.707f,
|
||||
Radius = (float)actor.BoundingSphere.Radius / Mathf.Max((float)actor.Scale.MaxValue, 0.0001f) * 0.707f,
|
||||
Height = 100f,
|
||||
};
|
||||
spawner(collider);
|
||||
|
||||
@@ -1,15 +1,62 @@
|
||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.TypeConverters;
|
||||
using FlaxEngine.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.Design.Serialization;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.Utilities;
|
||||
|
||||
namespace FlaxEngine.TypeConverters
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal ITypeDescriptorContext used to pass some context for custom TypeConvert implementations.
|
||||
/// Allows passing CurrentType to TypeConverter.ConvertFrom method to support custom type conversion for FlaxEngine types (simpler than PropertyDescriptor.PropertyType).
|
||||
/// </summary>
|
||||
internal sealed class DummyTypeDescriptorContext : ITypeDescriptorContext
|
||||
{
|
||||
private static DummyTypeDescriptorContext _cached;
|
||||
|
||||
public Type CurrentType;
|
||||
|
||||
public static object ConvertFrom(TypeConverter converter, object value, Type type)
|
||||
{
|
||||
if (_cached == null)
|
||||
_cached = new DummyTypeDescriptorContext();
|
||||
_cached.CurrentType = type;
|
||||
var result = converter.ConvertFrom(_cached, CultureInfo.CurrentUICulture, value);
|
||||
_cached.CurrentType = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
public object GetService(Type serviceType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void OnComponentChanged()
|
||||
{
|
||||
}
|
||||
|
||||
public bool OnComponentChanging()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public IContainer Container => null;
|
||||
|
||||
public object Instance => null;
|
||||
|
||||
public PropertyDescriptor PropertyDescriptor => null;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FlaxEditor.Scripting
|
||||
{
|
||||
@@ -681,7 +728,7 @@ namespace FlaxEditor.Scripting
|
||||
if (converter.CanConvertTo(type))
|
||||
value = converter.ConvertTo(value, type);
|
||||
else if (converter.CanConvertFrom(valueType))
|
||||
value = converter.ConvertFrom(null, null, value);
|
||||
value = DummyTypeDescriptorContext.ConvertFrom(converter, value, type);
|
||||
}
|
||||
|
||||
if (_managed is PropertyInfo propertyInfo)
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace FlaxEditor.Surface
|
||||
color = Colors.Enum;
|
||||
else if (type.IsValueType)
|
||||
color = Colors.Structures;
|
||||
else if (type.IsScriptingObject || type.IsInterface)
|
||||
else if (type.IsScriptingObject || type.IsInterface || type.Name.StartsWith("ScriptingObjectInterfaceReference"))
|
||||
color = Colors.Object;
|
||||
else if (hint == ConnectionsHint.Vector)
|
||||
color = Colors.Vector;
|
||||
|
||||
@@ -589,7 +589,7 @@ namespace FlaxEditor.Surface
|
||||
redoButton = toolStrip.AddButton(editor.Icons.Redo64, undo.PerformRedo).LinkTooltip("Redo.", ref inputOptions.Redo);
|
||||
toolStrip.AddSeparator();
|
||||
toolStrip.AddButton(editor.Icons.Search64, showSearch).LinkTooltip("Open content search tool.", ref inputOptions.Search);
|
||||
toolStrip.AddButton(editor.Icons.CenterView64, surface.ShowWholeGraph).LinkTooltip("Show whole graph.");
|
||||
toolStrip.AddButton(editor.Icons.CenterView64, surface.ShowWholeGraph).LinkTooltip("Show whole graph.", ref inputOptions.ShowEditorContents);
|
||||
var gridSnapButton = toolStrip.AddButton(editor.Icons.Grid32, surface.ToggleGridSnapping);
|
||||
gridSnapButton.LinkTooltip("Toggle grid snapping for nodes.");
|
||||
gridSnapButton.AutoCheck = true;
|
||||
@@ -600,6 +600,7 @@ namespace FlaxEditor.Surface
|
||||
window.InputActions.Add(options => options.Undo, undo.PerformUndo);
|
||||
window.InputActions.Add(options => options.Redo, undo.PerformRedo);
|
||||
window.InputActions.Add(options => options.Search, showSearch);
|
||||
window.InputActions.Add(options => options.ShowEditorContents, surface.ShowWholeGraph);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ namespace FlaxEngine.Tools
|
||||
|
||||
public override bool IsControllingMouse => IsPainting;
|
||||
|
||||
public override BoundingSphere FocusBounds => _cloth?.Sphere ?? base.FocusBounds;
|
||||
public override BoundingSphere FocusBounds => _cloth?.BoundingSphere ?? base.FocusBounds;
|
||||
|
||||
public override void Update(float dt)
|
||||
{
|
||||
|
||||
@@ -67,7 +67,7 @@ struct GeometryLookup
|
||||
static bool Search(Actor* actor, GeometryLookup& lookup)
|
||||
{
|
||||
// Early out if object is not intersecting with the foliage brush bounds
|
||||
if (!actor->GetIsActive() || !actor->GetBox().Intersects(lookup.Brush))
|
||||
if (!actor->GetIsActive() || !actor->GetBoundingBox().Intersects(lookup.Brush))
|
||||
return true;
|
||||
|
||||
const auto brush = lookup.Brush;
|
||||
|
||||
@@ -487,7 +487,7 @@ namespace FlaxEditor.Tools
|
||||
public override bool IsControllingMouse => IsPainting;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override BoundingSphere FocusBounds => _selectedModel != null ? _selectedModel.Sphere : base.FocusBounds;
|
||||
public override BoundingSphere FocusBounds => _selectedModel != null ? _selectedModel.BoundingSphere : base.FocusBounds;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(float dt)
|
||||
@@ -598,7 +598,7 @@ namespace FlaxEditor.Tools
|
||||
var vertexScale = Mathf.Lerp(0.005f, 0.01f, Mathf.Saturate(distanceScale));
|
||||
var modelScaleMatrix = Matrix.Scaling(_gizmoMode.PreviewVertexSize * vertexScale);
|
||||
var brushSphere = new BoundingSphere(_hitLocation, _gizmoMode.BrushSize * 0.5f);
|
||||
var lodIndex = _gizmoMode.ModelLOD == -1 ? RenderTools.ComputeModelLOD(_selectedModel.Model, ref renderContext.View.Position, (float)_selectedModel.Sphere.Radius, ref renderContext) : _gizmoMode.ModelLOD;
|
||||
var lodIndex = _gizmoMode.ModelLOD == -1 ? RenderTools.ComputeModelLOD(_selectedModel.Model, ref renderContext.View.Position, (float)_selectedModel.BoundingSphere.Radius, ref renderContext) : _gizmoMode.ModelLOD;
|
||||
lodIndex = Mathf.Clamp(lodIndex, 0, meshDatas.Length - 1);
|
||||
var lodData = meshDatas[lodIndex];
|
||||
if (lodData != null)
|
||||
|
||||
@@ -302,7 +302,7 @@ namespace FlaxEditor.Actions
|
||||
{
|
||||
if (_nodeParents[i] is ActorNode node && node.Actor && node.Actor.Scene && node.AffectsNavigationWithChildren)
|
||||
{
|
||||
var bounds = node.Actor.BoxWithChildren;
|
||||
var bounds = node.Actor.BoundingBoxWithChildren;
|
||||
Navigation.BuildNavMesh(bounds, options.General.AutoRebuildNavMeshTimeoutMs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,7 +387,7 @@ namespace FlaxEditor.Utilities
|
||||
transforms[i] = nodes[i].Transform;
|
||||
if (nodes[i] is ActorNode actorNode)
|
||||
{
|
||||
bounds = BoundingBox.Merge(bounds, actorNode.Actor.BoxWithChildren);
|
||||
bounds = BoundingBox.Merge(bounds, actorNode.Actor.BoundingBoxWithChildren);
|
||||
}
|
||||
}
|
||||
return transforms;
|
||||
@@ -833,6 +833,24 @@ namespace FlaxEditor.Utilities
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type name for UI. Removes unnecessary characters and filters text. Makes it more user-friendly.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>The result.</returns>
|
||||
public static string GetTypeNameUI(Scripting.ScriptType type)
|
||||
{
|
||||
var name = type.ToString();
|
||||
|
||||
// Don't format interfaces to maintain code-name (eg. prefix 'I')
|
||||
if (type.IsInterface)
|
||||
return name;
|
||||
if (type.IsGenericType && name.StartsWith("ScriptingObjectInterfaceReference", StringComparison.Ordinal))
|
||||
return type.GetGenericArguments()[0].GetTypeDisplayName();
|
||||
|
||||
return GetPropertyNameUI(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property name for UI. Removes unnecessary characters and filters text. Makes it more user-friendly.
|
||||
/// </summary>
|
||||
|
||||
@@ -423,7 +423,7 @@ namespace FlaxEditor.Viewport
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this viewport has loaded dependant assets.
|
||||
/// </summary>
|
||||
public virtual bool HasLoadedAssets => true;
|
||||
public virtual bool HasContentLoaded => true;
|
||||
|
||||
/// <summary>
|
||||
/// The 'View' widget button context menu.
|
||||
@@ -1565,8 +1565,9 @@ namespace FlaxEditor.Viewport
|
||||
var center = Float2.Round(size * 0.5f);
|
||||
if (Mathf.Abs(_viewMousePos.X - center.X) > center.X * 0.8f || Mathf.Abs(_viewMousePos.Y - center.Y) > center.Y * 0.8f)
|
||||
{
|
||||
_viewMousePos = center;
|
||||
win.MousePosition = PointToWindow(_viewMousePos);
|
||||
var windowPosition = SnapMousePositionToDevicePixels(PointToWindow(center), win.DpiScale);
|
||||
_viewMousePos = PointFromWindow(windowPosition);
|
||||
win.MousePosition = windowPosition * win.DpiScale;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1583,6 +1584,11 @@ namespace FlaxEditor.Viewport
|
||||
win.MouseMoveRelative -= OnMouseMoveRelative;
|
||||
}
|
||||
|
||||
internal static Float2 SnapMousePositionToDevicePixels(Float2 position, float dpiScale)
|
||||
{
|
||||
return Float2.Round(position * dpiScale) / dpiScale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when left mouse button goes down (on press).
|
||||
/// </summary>
|
||||
@@ -1863,8 +1869,9 @@ namespace FlaxEditor.Viewport
|
||||
// Move mouse back to the root position
|
||||
if (centerMouse && (_input.IsMouseRightDown || _input.IsMouseLeftDown || _input.IsMouseMiddleDown || _isVirtualMouseRightDown))
|
||||
{
|
||||
var center = PointToWindow(_startPos);
|
||||
win.MousePosition = center;
|
||||
var windowPosition = SnapMousePositionToDevicePixels(PointToWindow(_startPos), win.Window.DpiScale);
|
||||
_startPos = PointFromWindow(windowPosition);
|
||||
win.MousePosition = windowPosition;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -396,6 +396,22 @@ namespace FlaxEditor.Viewport
|
||||
ViewportCamera.ShowActors(TransformGizmo.SelectedParents, ref orient);
|
||||
}
|
||||
|
||||
private static bool ActorHasContentLoaded(Actor a)
|
||||
{
|
||||
if (!a.HasContentLoaded)
|
||||
return false;
|
||||
var children = a.ChildrenCount;
|
||||
for (int i = 0; i < children; i++)
|
||||
{
|
||||
if (!ActorHasContentLoaded(a.GetChild(i)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool HasContentLoaded => base.HasContentLoaded && (Instance == null || ActorHasContentLoaded(Instance));
|
||||
|
||||
/// <inheritdoc />
|
||||
public EditorViewport Viewport => this;
|
||||
|
||||
|
||||
@@ -361,7 +361,7 @@ namespace FlaxEditor.Viewport.Previews
|
||||
if (_showNodes)
|
||||
{
|
||||
// Draw bounding box at the node locations
|
||||
var boxSize = Mathf.Min(1.0f, _previewModel.Sphere.Radius / 100.0f);
|
||||
var boxSize = Mathf.Min(1.0f, _previewModel.BoundingSphere.Radius / 100.0f);
|
||||
var localBox = new OrientedBoundingBox(new Vector3(-boxSize), new Vector3(boxSize));
|
||||
for (int nodeIndex = 0; nodeIndex < pose.Length; nodeIndex++)
|
||||
{
|
||||
@@ -405,7 +405,7 @@ namespace FlaxEditor.Viewport.Previews
|
||||
// Draw bounds
|
||||
if (_showBounds)
|
||||
{
|
||||
DebugDrawBounds(_previewModel.Box);
|
||||
DebugDrawBounds(_previewModel.BoundingBox);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ namespace FlaxEditor.Viewport.Previews
|
||||
/// </summary>
|
||||
public void ResetCamera()
|
||||
{
|
||||
ViewportCamera.SetArcBallView(_previewModel.Box);
|
||||
ViewportCamera.SetArcBallView(_previewModel.BoundingBox);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -245,7 +245,7 @@ namespace FlaxEditor.Viewport.Previews
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool HasLoadedAssets => base.HasLoadedAssets && Sky.HasContentLoaded && EnvProbe.HasContentLoaded && PostFxVolume.HasContentLoaded;
|
||||
public override bool HasContentLoaded => base.HasContentLoaded && Sky.HasContentLoaded && EnvProbe.HasContentLoaded && PostFxVolume.HasContentLoaded;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace FlaxEditor.Viewport.Previews
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool HasLoadedAssets => base.HasLoadedAssets && _previewMaterial.IsLoaded && _previewMaterial.BaseMaterial.IsLoaded;
|
||||
public override bool HasContentLoaded => base.HasContentLoaded && _previewMaterial.IsLoaded && _previewMaterial.BaseMaterial.IsLoaded;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
|
||||
@@ -175,11 +175,11 @@ namespace FlaxEditor.Viewport.Previews
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool HasLoadedAssets
|
||||
public override bool HasContentLoaded
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!base.HasLoadedAssets)
|
||||
if (!base.HasContentLoaded)
|
||||
return false;
|
||||
UpdateMaterial();
|
||||
return true;
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace FlaxEditor.Viewport.Previews
|
||||
/// </summary>
|
||||
public void ResetCamera()
|
||||
{
|
||||
ViewportCamera.SetArcBallView(StaticModel.Model != null ? StaticModel.Box : AnimatedModel.Box);
|
||||
ViewportCamera.SetArcBallView(StaticModel.Model != null ? StaticModel.BoundingBox : AnimatedModel.BoundingBox);
|
||||
}
|
||||
|
||||
private void OnBegin(RenderTask task, GPUContext context)
|
||||
|
||||
@@ -302,7 +302,7 @@ namespace FlaxEditor.Viewport.Previews
|
||||
// Draw bounds
|
||||
if (_showBounds)
|
||||
{
|
||||
DebugDrawBounds(_previewModel.Box);
|
||||
DebugDrawBounds(_previewModel.BoundingBox);
|
||||
}
|
||||
|
||||
// Draw normals
|
||||
@@ -395,7 +395,7 @@ namespace FlaxEditor.Viewport.Previews
|
||||
// Based on RenderTools::ComputeModelLOD
|
||||
CreateProjectionMatrix(out var projectionMatrix);
|
||||
float screenMultiple = 0.5f * Mathf.Max(projectionMatrix.M11, projectionMatrix.M22);
|
||||
var sphere = PreviewActor.Sphere;
|
||||
var sphere = PreviewActor.BoundingSphere;
|
||||
var viewOrigin = ViewPosition;
|
||||
var distSqr = Vector3.DistanceSquared(ref sphere.Center, ref viewOrigin);
|
||||
var screenRadiusSquared = Mathf.Square(screenMultiple * sphere.Radius) / Mathf.Max(1.0f, distSqr);
|
||||
@@ -461,11 +461,11 @@ namespace FlaxEditor.Viewport.Previews
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the camera to focus on a object.
|
||||
/// Resets the camera to focus on an object.
|
||||
/// </summary>
|
||||
public void ResetCamera()
|
||||
{
|
||||
ViewportCamera.SetArcBallView(_previewModel.Box);
|
||||
ViewportCamera.SetArcBallView(_previewModel.BoundingBox);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace FlaxEditor.Viewport.Previews
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool HasLoadedAssets => (_emitter == null || _emitter.IsLoaded) && base.HasLoadedAssets;
|
||||
public override bool HasContentLoaded => (_emitter == null || _emitter.IsLoaded) && base.HasContentLoaded;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
|
||||
@@ -207,7 +207,7 @@ namespace FlaxEditor.Viewport.Previews
|
||||
|
||||
private void UpdateBoundsModel()
|
||||
{
|
||||
var bounds = _previewEffect.Box;
|
||||
var bounds = _previewEffect.BoundingBox;
|
||||
Transform t = Transform.Identity;
|
||||
t.Translation = bounds.Center;
|
||||
t.Scale = bounds.Size;
|
||||
@@ -221,12 +221,12 @@ namespace FlaxEditor.Viewport.Previews
|
||||
public void FitIntoView(float targetSize = 300.0f)
|
||||
{
|
||||
_previewEffect.Scale = Float3.One;
|
||||
float maxSize = Mathf.Max(0.001f, (float)_previewEffect.Box.Size.MaxValue);
|
||||
float maxSize = Mathf.Max(0.001f, (float)_previewEffect.BoundingBox.Size.MaxValue);
|
||||
_previewEffect.Scale = new Float3(targetSize / maxSize);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool HasLoadedAssets => _previewEffect.HasContentLoaded && base.HasLoadedAssets;
|
||||
public override bool HasContentLoaded => _previewEffect.HasContentLoaded && base.HasContentLoaded;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(float deltaTime)
|
||||
@@ -278,7 +278,7 @@ namespace FlaxEditor.Viewport.Previews
|
||||
switch (key)
|
||||
{
|
||||
case KeyboardKeys.F:
|
||||
ViewportCamera.SetArcBallView(_previewEffect.Box);
|
||||
ViewportCamera.SetArcBallView(_previewEffect.BoundingBox);
|
||||
return true;
|
||||
case KeyboardKeys.Spacebar:
|
||||
PlaySimulation = !PlaySimulation;
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace FlaxEditor.Viewport.Previews
|
||||
// Based on RenderTools::ComputeModelLOD
|
||||
CreateProjectionMatrix(out var projectionMatrix);
|
||||
float screenMultiple = 0.5f * Mathf.Max(projectionMatrix.M11, projectionMatrix.M22);
|
||||
var sphere = PreviewActor.Sphere;
|
||||
var sphere = PreviewActor.BoundingSphere;
|
||||
var viewOrigin = ViewPosition;
|
||||
var distSqr = Vector3.DistanceSquared(ref sphere.Center, ref viewOrigin);
|
||||
var screenRadiusSquared = Mathf.Square(screenMultiple * sphere.Radius) / Mathf.Max(1.0f, distSqr);
|
||||
|
||||
@@ -192,7 +192,7 @@ namespace FlaxEditor.Viewport
|
||||
|
||||
// Place the object
|
||||
//var location = hitLocation - (box.Size.Length * 0.5f) * ViewDirection;
|
||||
var editorBounds = actor.EditorBoxChildren;
|
||||
var editorBounds = actor.EditorBoundingBoxWithChildren;
|
||||
var bottomToCenter = actor.Position.Y - editorBounds.Minimum.Y;
|
||||
var location = hitLocation + new Vector3(0, bottomToCenter, 0);
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace FlaxEditor
|
||||
if (model == null)
|
||||
continue;
|
||||
staticModel.Transform.GetWorld(out world);
|
||||
var bounds = BoundingSphere.FromBox(staticModel.Box);
|
||||
var bounds = BoundingSphere.FromBox(staticModel.BoundingBox);
|
||||
|
||||
// Pick a proper LOD
|
||||
Float3 center = bounds.Center - renderContext.View.Origin;
|
||||
@@ -149,7 +149,7 @@ namespace FlaxEditor
|
||||
if (model == null)
|
||||
continue;
|
||||
animatedModel.Transform.GetWorld(out world);
|
||||
var bounds = BoundingSphere.FromBox(animatedModel.Box);
|
||||
var bounds = BoundingSphere.FromBox(animatedModel.BoundingBox);
|
||||
var bones = animatedModel.SkinnedMeshBones;
|
||||
|
||||
// Pick a proper LOD
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
{
|
||||
// Focus model
|
||||
value.WaitForLoaded(500);
|
||||
Window._preview.ViewportCamera.SetArcBallView(Window._preview.PreviewActor.Sphere);
|
||||
Window._preview.ViewportCamera.SetArcBallView(Window._preview.PreviewActor.BoundingSphere);
|
||||
}
|
||||
|
||||
if (EnablePreviewModelCache)
|
||||
|
||||
@@ -117,9 +117,12 @@ namespace FlaxEditor.Windows.Assets
|
||||
|
||||
public override void OnClean()
|
||||
{
|
||||
Window._isolateIndex = -1;
|
||||
Window._highlightIndex = -1;
|
||||
Window._meshProxy = null;
|
||||
if (Window != null)
|
||||
{
|
||||
Window._isolateIndex = -1;
|
||||
Window._highlightIndex = -1;
|
||||
Window._meshProxy = null;
|
||||
}
|
||||
|
||||
base.OnClean();
|
||||
}
|
||||
|
||||
@@ -536,7 +536,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
}
|
||||
|
||||
// Auto fit
|
||||
if (_focusCamera && _viewport.Task.FrameCount > 1)
|
||||
if (_focusCamera && _viewport.Task.FrameCount > 1 && _viewport.HasContentLoaded)
|
||||
{
|
||||
_focusCamera = false;
|
||||
Editor.GetActorEditorSphere(_viewport.Instance, out BoundingSphere bounds);
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
};
|
||||
|
||||
// Toolstrip
|
||||
_toolstrip.AddButton(editor.Icons.CenterView64, _preview.CenterView).LinkTooltip("Center view");
|
||||
_toolstrip.AddButton(editor.Icons.CenterView64, _preview.CenterView).LinkTooltip("Center view", ref editor.Options.Options.Input.ShowEditorContents);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -326,7 +326,9 @@ namespace FlaxEditor.Windows.Assets
|
||||
_propertiesEditor.BuildLayout();
|
||||
}).LinkTooltip("Add a new sprite");
|
||||
_toolstrip.AddSeparator();
|
||||
_toolstrip.AddButton(editor.Icons.CenterView64, _preview.CenterView).LinkTooltip("Center view");
|
||||
_toolstrip.AddButton(editor.Icons.CenterView64, _preview.CenterView).LinkTooltip("Center view", ref editor.Options.Options.Input.ShowEditorContents);
|
||||
|
||||
InputActions.Add(options => options.ShowEditorContents, _preview.CenterView);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -262,9 +262,11 @@ namespace FlaxEditor.Windows.Assets
|
||||
_saveButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Save64, Save).LinkTooltip("Save", ref inputOptions.Save);
|
||||
_toolstrip.AddButton(Editor.Icons.Import64, () => Editor.ContentImporting.Reimport((BinaryAssetItem)Item)).LinkTooltip("Reimport");
|
||||
_toolstrip.AddSeparator();
|
||||
_toolstrip.AddButton(Editor.Icons.CenterView64, _preview.CenterView).LinkTooltip("Center view");
|
||||
_toolstrip.AddButton(Editor.Icons.CenterView64, _preview.CenterView).LinkTooltip("Center view", ref editor.Options.Options.Input.ShowEditorContents);
|
||||
_toolstrip.AddSeparator();
|
||||
_toolstrip.AddButton(editor.Icons.Docs64, () => Platform.OpenUrl(Utilities.Constants.DocsUrl + "manual/graphics/textures/index.html")).LinkTooltip("See documentation to learn more");
|
||||
|
||||
InputActions.Add(options => options.ShowEditorContents, _preview.CenterView);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -229,6 +229,17 @@ namespace FlaxEditor.Windows
|
||||
_navigationBar.IsLayoutLocked = wasLayoutLocked;
|
||||
_navigationBar.PerformLayout();
|
||||
UpdateNavigationBarBounds();
|
||||
|
||||
ScrollNavigationBarToCurrentFolder();
|
||||
}
|
||||
|
||||
private void ScrollNavigationBarToCurrentFolder()
|
||||
{
|
||||
if (_navigationBar != null && _navigationBar.ChildrenCount != 0 && _navigationBar.HScrollBar.Visible)
|
||||
{
|
||||
_navigationBar.HScrollBar.TargetValue = _navigationBar.HScrollBar.Maximum;
|
||||
_navigationBar.HScrollBar.FastScroll();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -561,7 +561,7 @@ namespace FlaxEditor.Windows
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables vertical and horizontal scrolling on the content tree panel
|
||||
/// Enables or disables vertical and horizontal scrolling on the content tree panel
|
||||
/// </summary>
|
||||
/// <param name="enabled">The state to set scrolling to</param>
|
||||
public void ScrollingOnTreeView(bool enabled)
|
||||
@@ -573,7 +573,7 @@ namespace FlaxEditor.Windows
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables vertical and horizontal scrolling on the content view panel
|
||||
/// Enables or disables vertical and horizontal scrolling on the content view panel
|
||||
/// </summary>
|
||||
/// <param name="enabled">The state to set scrolling to</param>
|
||||
public void ScrollingOnContentView(bool enabled)
|
||||
@@ -1570,6 +1570,7 @@ namespace FlaxEditor.Windows
|
||||
PerformLayout();
|
||||
}
|
||||
UpdateViewDropdownBounds();
|
||||
ScrollNavigationBarToCurrentFolder();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1850,6 +1851,14 @@ namespace FlaxEditor.Windows
|
||||
return base.OnMouseUp(location, button);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnSizeChanged()
|
||||
{
|
||||
base.OnSizeChanged();
|
||||
|
||||
ScrollNavigationBarToCurrentFolder();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void PerformLayoutAfterChildren()
|
||||
{
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace FlaxEditor.Windows
|
||||
|
||||
_pilotActor = actor;
|
||||
_pilotStart = actor.Transform;
|
||||
_pilotBounds = actor.BoxWithChildren;
|
||||
_pilotBounds = actor.BoundingBoxWithChildren;
|
||||
Viewport.ViewTransform = _pilotStart;
|
||||
if (_pilotWidget == null)
|
||||
{
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace FlaxEngine
|
||||
/// </summary>
|
||||
/// <param name="knowledge">The knowledge container to access.</param>
|
||||
/// <param name="value">The value to set.</param>
|
||||
/// <returns>True if set value value, otherwise false.</returns>
|
||||
/// <returns>True if set value, otherwise false.</returns>
|
||||
public bool Set(BehaviorKnowledge knowledge, T value)
|
||||
{
|
||||
return knowledge != null && knowledge.Set(Path, value);
|
||||
|
||||
@@ -394,8 +394,8 @@ void BehaviorTreeMoveToNode::GetAgentSize(Actor* agent, float& outRadius, float&
|
||||
}
|
||||
|
||||
// Estimate actor bounds to extract capsule information
|
||||
const BoundingBox box = agent->GetBox();
|
||||
const BoundingSphere sphere = agent->GetSphere();
|
||||
const BoundingBox box = agent->GetBoundingBox();
|
||||
const BoundingSphere sphere = agent->GetBoundingSphere();
|
||||
outRadius = (float)sphere.Radius;
|
||||
outHeight = (float)box.GetSize().Y;
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ public:
|
||||
void Serialize(SerializeStream& stream, const void* otherObj) override;
|
||||
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
|
||||
#if USE_EDITOR
|
||||
BoundingBox GetEditorBox() const override
|
||||
BoundingBox GetEditorBoundingBox() const override
|
||||
{
|
||||
const Vector3 size(50);
|
||||
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
|
||||
|
||||
@@ -30,7 +30,7 @@ private:
|
||||
public:
|
||||
// [Actor]
|
||||
#if USE_EDITOR
|
||||
BoundingBox GetEditorBox() const override
|
||||
BoundingBox GetEditorBoundingBox() const override
|
||||
{
|
||||
const Vector3 size(50);
|
||||
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
|
||||
|
||||
@@ -318,7 +318,7 @@ private:
|
||||
public:
|
||||
// [Actor]
|
||||
#if USE_EDITOR
|
||||
BoundingBox GetEditorBox() const override
|
||||
BoundingBox GetEditorBoundingBox() const override
|
||||
{
|
||||
const Vector3 size(50);
|
||||
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
|
||||
|
||||
@@ -794,7 +794,9 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, const M
|
||||
// Setup node in hierarchy
|
||||
nodeToActor.Add(nodeIndex, nodeActor);
|
||||
nodeActor->SetName(node.Name);
|
||||
nodeActor->SetLocalTransform(node.LocalTransform);
|
||||
|
||||
#if 0
|
||||
// When use local origin is checked, it shifts everything over the same amount, including the root. This tries to work around that.
|
||||
if (!(nodeIndex == 0 && options.UseLocalOrigin))
|
||||
{
|
||||
@@ -829,6 +831,7 @@ CreateAssetResult ImportModel::CreatePrefab(CreateAssetContext& context, const M
|
||||
|
||||
nodeActor->SetLocalTransform(positionOffset);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (nodeIndex == 0)
|
||||
{
|
||||
|
||||
@@ -263,12 +263,36 @@ namespace FlaxEngine.Interop
|
||||
/// <returns>The output array.</returns>
|
||||
public static TDst[] ConvertArray<TSrc, TDst>(this TSrc[] src, Func<TSrc, TDst> convertFunc)
|
||||
{
|
||||
TDst[] dst = new TDst[src.Length];
|
||||
if (src == null)
|
||||
return null;
|
||||
var dst = new TDst[src.Length];
|
||||
for (int i = 0; i < src.Length; i++)
|
||||
dst[i] = convertFunc(src[i]);
|
||||
return dst;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts dictionary with a custom converter function for each pair of keys and values.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSrcKey">Input dictionary key type.</typeparam>
|
||||
/// <typeparam name="TSrcValue">Input dictionary value type.</typeparam>
|
||||
/// <typeparam name="TDstKey">Output dictionary key type.</typeparam>
|
||||
/// <typeparam name="TDstValue">Output dictionary value type.</typeparam>
|
||||
/// <param name="src">The input dictionary.</param>
|
||||
/// <param name="convertFuncKey">Converter callback for keys.</param>
|
||||
/// <param name="convertFuncValue">Converter callback for values.</param>
|
||||
/// <returns>The output dictionary.</returns>
|
||||
public static Dictionary<TDstKey, TDstValue> ConvertDictionary<TSrcKey, TSrcValue, TDstKey, TDstValue>(this Dictionary<TSrcKey, TSrcValue> src, Func<TSrcKey, TDstKey> convertFuncKey, Func<TSrcValue, TDstValue> convertFuncValue)
|
||||
{
|
||||
if (src == null)
|
||||
return null;
|
||||
var dst = new Dictionary<TDstKey, TDstValue>();
|
||||
dst.EnsureCapacity(src.Count);
|
||||
foreach (var e in src)
|
||||
dst.Add(convertFuncKey(e.Key), convertFuncValue(e.Value));
|
||||
return dst;
|
||||
}
|
||||
|
||||
/// <summary>Find <paramref name="assemblyName"/> among the scripting assemblies.</summary>
|
||||
/// <param name="assemblyName">The name to find</param>
|
||||
/// <param name="allowPartial">If true, partial names should be allowed to be resolved.</param>
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace FlaxEngine
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
public void UpdateMesh(Float3[] vertices, int[] triangles, Float3[] normals = null, Float3[] tangents = null, Float2[] uv = null, Color32[] colors = null)
|
||||
@@ -153,7 +153,7 @@ namespace FlaxEngine
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
public void UpdateMesh(List<Float3> vertices, List<int> triangles, List<Float3> normals = null, List<Float3> tangents = null, List<Float2> uv = null, List<Color32> colors = null)
|
||||
@@ -189,7 +189,7 @@ namespace FlaxEngine
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
public void UpdateMesh(Float3[] vertices, uint[] triangles, Float3[] normals = null, Float3[] tangents = null, Float2[] uv = null, Color32[] colors = null)
|
||||
@@ -225,7 +225,7 @@ namespace FlaxEngine
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
public void UpdateMesh(List<Float3> vertices, List<uint> triangles, List<Float3> normals = null, List<Float3> tangents = null, List<Float2> uv = null, List<Color32> colors = null)
|
||||
@@ -261,7 +261,7 @@ namespace FlaxEngine
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 16-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
public void UpdateMesh(Float3[] vertices, ushort[] triangles, Float3[] normals = null, Float3[] tangents = null, Float2[] uv = null, Color32[] colors = null)
|
||||
@@ -297,7 +297,7 @@ namespace FlaxEngine
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 16-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
public void UpdateMesh(List<Float3> vertices, List<ushort> triangles, List<Float3> normals = null, List<Float3> tangents = null, List<Float2> uv = null, List<Color32> colors = null)
|
||||
@@ -334,7 +334,7 @@ namespace FlaxEngine
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
[Obsolete("Use UpdateMesh with Float3 and Float2 parameters instead")]
|
||||
@@ -352,7 +352,7 @@ namespace FlaxEngine
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
[Obsolete("Use UpdateMesh with Float3 and Float2 parameters instead")]
|
||||
@@ -388,7 +388,7 @@ namespace FlaxEngine
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
[Obsolete("Use UpdateMesh with Float3 and Float2 parameters instead")]
|
||||
@@ -406,7 +406,7 @@ namespace FlaxEngine
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 16-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
[Obsolete("Use UpdateMesh with Float3 and Float2 parameters instead")]
|
||||
@@ -424,7 +424,7 @@ namespace FlaxEngine
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 16-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
[Obsolete("Use UpdateMesh with Float3 and Float2 parameters instead")]
|
||||
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uvs">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uvs">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace FlaxEngine
|
||||
/// <param name="blendIndices">The skinned mesh blend indices buffer. Contains indices of the skeleton bones (up to 4 bones per vertex) to use for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="blendWeights">The skinned mesh blend weights buffer (normalized). Contains weights per blend bone (up to 4 bones per vertex) of the skeleton bones to mix for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
public void UpdateMesh(Float3[] vertices, int[] triangles, Int4[] blendIndices, Float4[] blendWeights, Float3[] normals = null, Float3[] tangents = null, Float2[] uv = null, Color32[] colors = null)
|
||||
@@ -140,7 +140,7 @@ namespace FlaxEngine
|
||||
/// <param name="blendIndices">The skinned mesh blend indices buffer. Contains indices of the skeleton bones (up to 4 bones per vertex) to use for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="blendWeights">The skinned mesh blend weights buffer (normalized). Contains weights per blend bone (up to 4 bones per vertex) of the skeleton bones to mix for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
public void UpdateMesh(Float3[] vertices, uint[] triangles, Int4[] blendIndices, Float4[] blendWeights, Float3[] normals = null, Float3[] tangents = null, Float2[] uv = null, Color32[] colors = null)
|
||||
@@ -178,7 +178,7 @@ namespace FlaxEngine
|
||||
/// <param name="blendIndices">The skinned mesh blend indices buffer. Contains indices of the skeleton bones (up to 4 bones per vertex) to use for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="blendWeights">The skinned mesh blend weights buffer (normalized). Contains weights per blend bone (up to 4 bones per vertex) of the skeleton bones to mix for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
public void UpdateMesh(Float3[] vertices, ushort[] triangles, Int4[] blendIndices, Float4[] blendWeights, Float3[] normals = null, Float3[] tangents = null, Float2[] uv = null, Color32[] colors = null)
|
||||
@@ -217,7 +217,7 @@ namespace FlaxEngine
|
||||
/// <param name="blendIndices">The skinned mesh blend indices buffer. Contains indices of the skeleton bones (up to 4 bones per vertex) to use for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="blendWeights">The skinned mesh blend weights buffer (normalized). Contains weights per blend bone (up to 4 bones per vertex) of the skeleton bones to mix for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
[Obsolete("Use UpdateMesh with Float3 and Float2 parameters instead")]
|
||||
public void UpdateMesh(Vector3[] vertices, int[] triangles, Int4[] blendIndices, Vector4[] blendWeights, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null)
|
||||
@@ -236,7 +236,7 @@ namespace FlaxEngine
|
||||
/// <param name="blendIndices">The skinned mesh blend indices buffer. Contains indices of the skeleton bones (up to 4 bones per vertex) to use for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="blendWeights">The skinned mesh blend weights buffer (normalized). Contains weights per blend bone (up to 4 bones per vertex) of the skeleton bones to mix for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
[Obsolete("Use UpdateMesh with Float3 and Float2 parameters instead")]
|
||||
public void UpdateMesh(Vector3[] vertices, uint[] triangles, Int4[] blendIndices, Vector4[] blendWeights, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null)
|
||||
@@ -255,7 +255,7 @@ namespace FlaxEngine
|
||||
/// <param name="blendIndices">The skinned mesh blend indices buffer. Contains indices of the skeleton bones (up to 4 bones per vertex) to use for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="blendWeights">The skinned mesh blend weights buffer (normalized). Contains weights per blend bone (up to 4 bones per vertex) of the skeleton bones to mix for vertex position blending. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uv">The texture coordinates (per vertex).</param>
|
||||
[Obsolete("Use UpdateMesh with Float3 and Float2 parameters instead")]
|
||||
public void UpdateMesh(Vector3[] vertices, ushort[] triangles, Int4[] blendIndices, Vector4[] blendWeights, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null)
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
/// <param name="blendIndices">The skeletal bones indices to use for skinning.</param>
|
||||
/// <param name="blendWeights">The skeletal bones weights to use for skinning (matches blendIndices).</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uvs">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
@@ -137,7 +137,7 @@ public:
|
||||
/// <param name="blendIndices">The skeletal bones indices to use for skinning.</param>
|
||||
/// <param name="blendWeights">The skeletal bones weights to use for skinning (matches blendIndices).</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="tangents">The tangent vectors (per vertex).</param>
|
||||
/// <param name="uvs">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
|
||||
@@ -417,7 +417,7 @@ GeometryDrawState* RenderBuffers::GetGeometryDrawState(SceneRendering* scene, in
|
||||
|
||||
bool RenderBuffers::TestOcclusionCulling(const Actor* actor, uint32& cullingId) const
|
||||
{
|
||||
return TestOcclusionCulling(actor->GetSceneRendering(), actor, actor->GetBox(), cullingId);
|
||||
return TestOcclusionCulling(actor->GetSceneRendering(), actor, actor->GetBoundingBox(), cullingId);
|
||||
}
|
||||
|
||||
bool RenderBuffers::TestOcclusionCulling(SceneRendering* scene, const Actor* actor, const BoundingBox& objectBounds, uint32& cullingId, const void* object) const
|
||||
|
||||
@@ -137,6 +137,7 @@ GPUTextureView* GPUSwapChainVulkan::GetBackBufferView()
|
||||
PROFILE_CPU();
|
||||
auto context = _device->MainContext;
|
||||
auto cmdBufferManager = context->GetCmdBufferManager();
|
||||
|
||||
// Keep commands recorded before acquire independent from the image-acquired semaphore wait below.
|
||||
if (cmdBufferManager->HasPendingActiveCmdBuffer())
|
||||
context->Flush();
|
||||
@@ -154,7 +155,6 @@ GPUTextureView* GPUSwapChainVulkan::GetBackBufferView()
|
||||
acquiredBackBuffer.WaitForSubmit();
|
||||
|
||||
const auto backBuffer = &_backBuffers[_acquiredImageIndex].Handle;
|
||||
|
||||
auto cmdBuffer = cmdBufferManager->GetCmdBuffer();
|
||||
|
||||
// Transition to render target (typical usage in most cases when calling backbuffer getter)
|
||||
@@ -174,6 +174,17 @@ void GPUSwapChainVulkan::Begin(RenderTask* task)
|
||||
{
|
||||
GPUSwapChain::Begin(task);
|
||||
|
||||
// Wait for the backbuffer to be available
|
||||
if (_currentImageIndex != -1)
|
||||
{
|
||||
auto& backBuffer = _backBuffers[_currentImageIndex];
|
||||
if (backBuffer.SubmitCmdBuffer)
|
||||
{
|
||||
backBuffer.SubmitCmdBuffer->Wait();
|
||||
backBuffer.SubmitCmdBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild swapchain if need to
|
||||
if (_vsyncPending != _vsyncCurrent)
|
||||
{
|
||||
|
||||
@@ -1428,9 +1428,14 @@ void Actor::OnLayerChanged()
|
||||
|
||||
BoundingBox Actor::GetBoxWithChildren() const
|
||||
{
|
||||
BoundingBox result = GetBox();
|
||||
return GetBoundingBoxWithChildren();
|
||||
}
|
||||
|
||||
BoundingBox Actor::GetBoundingBoxWithChildren() const
|
||||
{
|
||||
BoundingBox result = GetBoundingBox();
|
||||
for (int32 i = 0; i < Children.Count(); i++)
|
||||
BoundingBox::Merge(result, Children.Get()[i]->GetBoxWithChildren(), result);
|
||||
BoundingBox::Merge(result, Children.Get()[i]->GetBoundingBoxWithChildren(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1438,14 +1443,24 @@ BoundingBox Actor::GetBoxWithChildren() const
|
||||
|
||||
BoundingBox Actor::GetEditorBox() const
|
||||
{
|
||||
return GetBox();
|
||||
return GetEditorBoundingBox();
|
||||
}
|
||||
|
||||
BoundingBox Actor::GetEditorBoundingBox() const
|
||||
{
|
||||
return GetBoundingBox();
|
||||
}
|
||||
|
||||
BoundingBox Actor::GetEditorBoxChildren() const
|
||||
{
|
||||
BoundingBox result = GetEditorBox();
|
||||
return GetEditorBoundingBoxWithChildren();
|
||||
}
|
||||
|
||||
BoundingBox Actor::GetEditorBoundingBoxWithChildren() const
|
||||
{
|
||||
BoundingBox result = GetEditorBoundingBox();
|
||||
for (int32 i = 0; i < Children.Count(); i++)
|
||||
BoundingBox::Merge(result, Children.Get()[i]->GetEditorBoxChildren(), result);
|
||||
BoundingBox::Merge(result, Children.Get()[i]->GetEditorBoundingBoxWithChildren(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -690,35 +690,71 @@ public:
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets actor bounding sphere that defines 3D space intersecting with the actor (for determination of the visibility for actor).
|
||||
/// [Deprecated in 1.13]
|
||||
/// </summary>
|
||||
API_PROPERTY() FORCE_INLINE const BoundingSphere& GetSphere() const
|
||||
API_PROPERTY() DEPRECATED("Use GetBoundingSphere instead.") FORCE_INLINE const BoundingSphere& GetSphere() const
|
||||
{
|
||||
return _sphere;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets actor bounding sphere that defines 3D space intersecting with the actor (for determination of the visibility for actor).
|
||||
/// </summary>
|
||||
API_PROPERTY() FORCE_INLINE const BoundingSphere& GetBoundingSphere() const
|
||||
{
|
||||
return _sphere;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets actor bounding box that defines 3D space intersecting with the actor (for determination of the visibility for actor).
|
||||
/// [Deprecated in 1.13]
|
||||
/// </summary>
|
||||
API_PROPERTY() FORCE_INLINE const BoundingBox& GetBox() const
|
||||
API_PROPERTY() DEPRECATED("Use GetBoundingBox instead.") FORCE_INLINE const BoundingBox& GetBox() const
|
||||
{
|
||||
return _box;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets actor bounding box that defines 3D space intersecting with the actor (for determination of the visibility for actor).
|
||||
/// </summary>
|
||||
API_PROPERTY() FORCE_INLINE const BoundingBox& GetBoundingBox() const
|
||||
{
|
||||
return _box;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets actor bounding box of the actor including all child actors (children included in recursive way)
|
||||
/// [Deprecated in 1.13]
|
||||
/// </summary>
|
||||
API_PROPERTY() BoundingBox GetBoxWithChildren() const;
|
||||
API_PROPERTY() DEPRECATED("Use GetBoundingBoxWithChildren instead.") BoundingBox GetBoxWithChildren() const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets actor bounding box of the actor including all child actors (children included in recursive way)
|
||||
/// </summary>
|
||||
API_PROPERTY() BoundingBox GetBoundingBoxWithChildren() const;
|
||||
|
||||
#if USE_EDITOR
|
||||
/// <summary>
|
||||
/// Gets actor bounding box (single actor, no children included) for editor tools.
|
||||
/// [Deprecated in 1.13]
|
||||
/// </summary>
|
||||
API_PROPERTY() virtual BoundingBox GetEditorBox() const;
|
||||
API_PROPERTY() DEPRECATED("Use GetEditorBoundingBox instead.") virtual BoundingBox GetEditorBox() const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets actor bounding box (single actor, no children included) for editor tools.
|
||||
/// </summary>
|
||||
API_PROPERTY() virtual BoundingBox GetEditorBoundingBox() const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets actor bounding box of the actor including all child actors for editor tools.
|
||||
/// [Deprecated in 1.13]
|
||||
/// </summary>
|
||||
API_PROPERTY() BoundingBox GetEditorBoxChildren() const;
|
||||
API_PROPERTY() DEPRECATED("Use GetEditorBoundingBoxWithChildren instead.") BoundingBox GetEditorBoxChildren() const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets actor bounding box of the actor including all child actors for editor tools.
|
||||
/// </summary>
|
||||
API_PROPERTY() BoundingBox GetEditorBoundingBoxWithChildren() const;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1378,7 +1378,7 @@ void AnimatedModel::OnDebugDraw()
|
||||
ModelInstanceActor::OnDebugDraw();
|
||||
}
|
||||
|
||||
BoundingBox AnimatedModel::GetEditorBox() const
|
||||
BoundingBox AnimatedModel::GetEditorBoundingBox() const
|
||||
{
|
||||
if (SkinnedModel)
|
||||
SkinnedModel->WaitForLoaded(100);
|
||||
|
||||
@@ -498,7 +498,7 @@ public:
|
||||
#if USE_EDITOR
|
||||
void OnDebugDrawSelected() override;
|
||||
void OnDebugDraw() override;
|
||||
BoundingBox GetEditorBox() const override;
|
||||
BoundingBox GetEditorBoundingBox() const override;
|
||||
#endif
|
||||
bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override;
|
||||
void Serialize(SerializeStream& stream, const void* otherObj) override;
|
||||
|
||||
@@ -338,7 +338,7 @@ void Camera::BeginPlay(SceneBeginData* data)
|
||||
Actor::BeginPlay(data);
|
||||
}
|
||||
|
||||
BoundingBox Camera::GetEditorBox() const
|
||||
BoundingBox Camera::GetEditorBoundingBox() const
|
||||
{
|
||||
const Vector3 size(100);
|
||||
const Vector3 pos = _transform.Translation + _transform.Orientation * Vector3::Forward * 30.0f;
|
||||
|
||||
@@ -264,7 +264,7 @@ private:
|
||||
public:
|
||||
// [Actor]
|
||||
#if USE_EDITOR
|
||||
BoundingBox GetEditorBox() const override;
|
||||
BoundingBox GetEditorBoundingBox() const override;
|
||||
bool HasContentLoaded() const override;
|
||||
void Draw(RenderContextBatch& renderContextBatch) override;
|
||||
void OnDebugDrawSelected() override;
|
||||
|
||||
@@ -53,7 +53,7 @@ void Decal::OnDebugDrawSelected()
|
||||
Actor::OnDebugDrawSelected();
|
||||
}
|
||||
|
||||
BoundingBox Decal::GetEditorBox() const
|
||||
BoundingBox Decal::GetEditorBoundingBox() const
|
||||
{
|
||||
const Vector3 size(10.0f);
|
||||
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
// [Actor]
|
||||
#if USE_EDITOR
|
||||
void OnDebugDrawSelected() override;
|
||||
BoundingBox GetEditorBox() const override;
|
||||
BoundingBox GetEditorBoundingBox() const override;
|
||||
#endif
|
||||
void OnLayerChanged() override;
|
||||
void Draw(RenderContextBatch& renderContextBatch) override;
|
||||
|
||||
@@ -9,7 +9,7 @@ EmptyActor::EmptyActor(const SpawnParams& params)
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
BoundingBox EmptyActor::GetEditorBox() const
|
||||
BoundingBox EmptyActor::GetEditorBoundingBox() const
|
||||
{
|
||||
const Vector3 size(50);
|
||||
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
|
||||
|
||||
@@ -14,7 +14,7 @@ class FLAXENGINE_API EmptyActor : public Actor
|
||||
public:
|
||||
// [Actor]
|
||||
#if USE_EDITOR
|
||||
BoundingBox GetEditorBox() const override;
|
||||
BoundingBox GetEditorBoundingBox() const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
@@ -152,7 +152,7 @@ private:
|
||||
public:
|
||||
// [Actor]
|
||||
#if USE_EDITOR
|
||||
BoundingBox GetEditorBox() const override
|
||||
BoundingBox GetEditorBoundingBox() const override
|
||||
{
|
||||
const Vector3 size(50);
|
||||
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
|
||||
|
||||
@@ -141,7 +141,7 @@ private:
|
||||
public:
|
||||
// [Actor]
|
||||
#if USE_EDITOR
|
||||
BoundingBox GetEditorBox() const override
|
||||
BoundingBox GetEditorBoundingBox() const override
|
||||
{
|
||||
const Vector3 size(50);
|
||||
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
void OnEnable() override;
|
||||
void OnDisable() override;
|
||||
#if USE_EDITOR
|
||||
BoundingBox GetEditorBox() const override
|
||||
BoundingBox GetEditorBoundingBox() const override
|
||||
{
|
||||
const Vector3 size(50);
|
||||
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
|
||||
|
||||
@@ -63,7 +63,7 @@ private:
|
||||
public:
|
||||
// [Actor]
|
||||
#if USE_EDITOR
|
||||
BoundingBox GetEditorBox() const override
|
||||
BoundingBox GetEditorBoundingBox() const override
|
||||
{
|
||||
const Vector3 size(50);
|
||||
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
|
||||
|
||||
@@ -57,7 +57,7 @@ private:
|
||||
public:
|
||||
// [Actor]
|
||||
#if USE_EDITOR
|
||||
BoundingBox GetEditorBox() const override
|
||||
BoundingBox GetEditorBoundingBox() const override
|
||||
{
|
||||
const Vector3 size(50);
|
||||
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
|
||||
|
||||
@@ -44,9 +44,9 @@ BoundingBox SceneNavigation::GetNavigationBounds()
|
||||
if (Volumes.IsEmpty())
|
||||
return BoundingBox::Empty;
|
||||
PROFILE_CPU_NAMED("GetNavigationBounds");
|
||||
auto box = Volumes[0]->GetBox();
|
||||
auto box = Volumes[0]->GetBoundingBox();
|
||||
for (int32 i = 1; i < Volumes.Count(); i++)
|
||||
BoundingBox::Merge(box, Volumes[i]->GetBox(), box);
|
||||
BoundingBox::Merge(box, Volumes[i]->GetBoundingBox(), box);
|
||||
return box;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ NavMeshBoundsVolume* SceneNavigation::FindNavigationBoundsOverlap(const Bounding
|
||||
NavMeshBoundsVolume* result = nullptr;
|
||||
for (int32 i = 0; i < Volumes.Count(); i++)
|
||||
{
|
||||
if (Volumes[i]->GetBox().Intersects(bounds))
|
||||
if (Volumes[i]->GetBoundingBox().Intersects(bounds))
|
||||
{
|
||||
result = Volumes[i];
|
||||
break;
|
||||
|
||||
@@ -191,7 +191,7 @@ void SceneRendering::AddActor(Actor* a, int32& key)
|
||||
auto& e = list[key];
|
||||
e.Actor = a;
|
||||
e.LayerMask = a->GetLayerMask();
|
||||
e.Bounds = a->GetSphere();
|
||||
e.Bounds = a->GetBoundingSphere();
|
||||
e.NoCulling = a->_drawNoCulling;
|
||||
for (auto* listener : _listeners)
|
||||
listener->OnSceneRenderingAddActor(this, key, a);
|
||||
@@ -214,7 +214,7 @@ void SceneRendering::UpdateActor(Actor* a, int32& key, ISceneRenderingListener::
|
||||
if (flags & ISceneRenderingListener::Layer)
|
||||
e.LayerMask = a->GetLayerMask();
|
||||
if (flags & ISceneRenderingListener::Bounds)
|
||||
e.Bounds = a->GetSphere();
|
||||
e.Bounds = a->GetBoundingSphere();
|
||||
}
|
||||
}
|
||||
if (lock)
|
||||
|
||||
@@ -251,7 +251,7 @@ struct NavSceneRasterizer
|
||||
return;
|
||||
PROFILE_CPU_NAMED("SphereCollider");
|
||||
|
||||
const BoundingSphere sphere = sphereCollider->GetSphere();
|
||||
const BoundingSphere sphere = sphereCollider->GetBoundingSphere();
|
||||
TriangulateSphere(VertexBuffer, IndexBuffer, sphere);
|
||||
RasterizeTriangles();
|
||||
}
|
||||
@@ -261,7 +261,7 @@ struct NavSceneRasterizer
|
||||
return;
|
||||
PROFILE_CPU_NAMED("CapsuleCollider");
|
||||
|
||||
const BoundingBox box = capsuleCollider->GetBox();
|
||||
const BoundingBox box = capsuleCollider->GetBoundingBox();
|
||||
TriangulateBox(VertexBuffer, IndexBuffer, box);
|
||||
RasterizeTriangles();
|
||||
}
|
||||
@@ -411,7 +411,7 @@ bool GenerateTile(NavMesh* navMesh, NavMeshRuntime* runtime, int32 x, int32 y, B
|
||||
for (Actor* actor : scene->Navigation.Actors)
|
||||
{
|
||||
BoundingBox actorBoxNavMesh;
|
||||
BoundingBox::Transform(actor->GetBox(), rasterizer.WorldToNavMesh, actorBoxNavMesh);
|
||||
BoundingBox::Transform(actor->GetBoundingBox(), rasterizer.WorldToNavMesh, actorBoxNavMesh);
|
||||
if (actorBoxNavMesh.Intersects(rasterizer.TileBoundsNavMesh) &&
|
||||
actor->IsActiveInHierarchy() &&
|
||||
EnumHasAllFlags(actor->GetStaticFlags(), StaticFlags::Navigation))
|
||||
@@ -963,10 +963,10 @@ void BuildDirtyBounds(Scene* scene, NavMesh* navMesh, const BoundingBox& dirtyBo
|
||||
for (const NavMeshBoundsVolume* volume : scene->Navigation.Volumes)
|
||||
{
|
||||
if (!volume->AgentsMask.IsNavMeshSupported(navMesh->Properties) ||
|
||||
!volume->GetBox().Intersects(dirtyBoundsNavMesh))
|
||||
!volume->GetBoundingBox().Intersects(dirtyBoundsNavMesh))
|
||||
continue;
|
||||
auto& bounds = volumes.AddOne();
|
||||
BoundingBox::Transform(volume->GetBox(), worldToNavMesh, bounds);
|
||||
BoundingBox::Transform(volume->GetBoundingBox(), worldToNavMesh, bounds);
|
||||
}
|
||||
|
||||
Array<TileId> unusedTiles;
|
||||
|
||||
@@ -423,7 +423,7 @@ public:
|
||||
void Serialize(SerializeStream& stream, const void* otherObj) override;
|
||||
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
|
||||
#if USE_EDITOR
|
||||
BoundingBox GetEditorBox() const override
|
||||
BoundingBox GetEditorBoundingBox() const override
|
||||
{
|
||||
const Vector3 size(50);
|
||||
return BoundingBox(_transform.Translation - size, _transform.Translation + size);
|
||||
|
||||
@@ -1144,7 +1144,7 @@ void Particles::DrawParticles(RenderContextBatch& renderContextBatch, ParticleEf
|
||||
|
||||
// Drawing assumes that all views within a batch have the same Origin
|
||||
const Vector3& viewOrigin = renderContextBatch.GetMainContext().View.Origin;
|
||||
BoundingSphere bounds = effect->GetSphere();
|
||||
BoundingSphere bounds = effect->GetBoundingSphere();
|
||||
bounds.Center -= viewOrigin;
|
||||
|
||||
// Cull particles against all views
|
||||
|
||||
@@ -34,13 +34,13 @@ void BoxCollider::AutoResize(bool globalOrientation = true)
|
||||
// Hacky way to get unrotated bounded box of parent
|
||||
const Quaternion parentOrientation = parent->GetOrientation();
|
||||
parent->SetOrientation(Quaternion::Identity);
|
||||
BoundingBox parentBox = parent->GetBox();
|
||||
BoundingBox parentBox = parent->GetBoundingBox();
|
||||
parent->SetOrientation(parentOrientation);
|
||||
|
||||
for (const Actor* sibling : parent->Children)
|
||||
{
|
||||
if (sibling != this)
|
||||
BoundingBox::Merge(parentBox, sibling->GetBoxWithChildren(), parentBox);
|
||||
BoundingBox::Merge(parentBox, sibling->GetBoundingBoxWithChildren(), parentBox);
|
||||
}
|
||||
const Vector3 parentSize = parentBox.GetSize();
|
||||
const Vector3 parentCenter = parentBox.GetCenter() - parent->GetPosition();
|
||||
|
||||
@@ -209,9 +209,9 @@ public:
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Moves the character with the given speed. Gravity is automatically applied. It will slide along colliders. Result collision flags is the summary of collisions that occurred during the Move.
|
||||
/// Moves the character with the given speed. Gravity is automatically applied. The speed is multipled by Time.DeltaTime internally. It will slide along colliders. Result collision flags is the summary of collisions that occurred during the Move.
|
||||
/// </summary>
|
||||
/// <param name="speed">The movement speed (in units/s).</param>
|
||||
/// <param name="speed">The movement speed (in units/s). The speed is multipled by Time.DeltaTime internally.</param>
|
||||
/// <returns>The collision flags. It can be used to trigger various character animations.</returns>
|
||||
API_FUNCTION() CollisionFlags SimpleMove(const Vector3& speed);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "MeshCollider.h"
|
||||
#include "Engine/Core/Math/Matrix.h"
|
||||
#include "Engine/Core/Math/Ray.h"
|
||||
#include "Engine/Core/ScopeExit.h"
|
||||
#include "Engine/Physics/Physics.h"
|
||||
#include "Engine/Physics/PhysicsScene.h"
|
||||
#if USE_EDITOR || !BUILD_RELEASE
|
||||
@@ -22,19 +23,29 @@ void MeshCollider::OnCollisionDataChanged()
|
||||
|
||||
if (CollisionData)
|
||||
{
|
||||
_isChangingCollisionData = true;
|
||||
SCOPE_EXIT { _isChangingCollisionData = false; };
|
||||
|
||||
// Ensure that collision asset is loaded (otherwise objects might fall though collider that is not yet loaded on play begin)
|
||||
CollisionData->WaitForLoaded();
|
||||
// OnSet sends Loaded after Changed returns, so let that notification update the collider once.
|
||||
if (!CollisionData->WaitForLoaded())
|
||||
return;
|
||||
}
|
||||
|
||||
// Clearing the reference or failing to load won't send Loaded, so clear the old geometry here.
|
||||
UpdateGeometry();
|
||||
UpdateBounds();
|
||||
}
|
||||
|
||||
void MeshCollider::OnCollisionDataLoaded()
|
||||
{
|
||||
// Not needed as OnCollisionDataChanged waits for it to be loaded
|
||||
//UpdateGeometry();
|
||||
//UpdateBounds();
|
||||
// WaitForLoaded can dispatch Loaded while Changed is still waiting. OnSet will send it again afterwards.
|
||||
if (_isChangingCollisionData)
|
||||
return;
|
||||
|
||||
// Virtual collision data can be recooked without changing the asset reference.
|
||||
UpdateGeometry();
|
||||
UpdateBounds();
|
||||
}
|
||||
|
||||
bool MeshCollider::CanAttach(RigidBody* rigidBody) const
|
||||
|
||||
@@ -23,6 +23,8 @@ public:
|
||||
AssetReference<CollisionData> CollisionData;
|
||||
|
||||
private:
|
||||
bool _isChangingCollisionData = false;
|
||||
|
||||
void OnCollisionDataChanged();
|
||||
void OnCollisionDataLoaded();
|
||||
|
||||
|
||||
@@ -216,8 +216,8 @@ struct ClothSettings
|
||||
clothTrans.LocalToWorld(c, c);
|
||||
|
||||
// Setup bounds
|
||||
BoundingBox::FromPoints(boundsCorners, 8, const_cast<BoundingBox&>(Actor->GetBox()));
|
||||
BoundingSphere::FromBox(Actor->GetBox(), const_cast<BoundingSphere&>(Actor->GetSphere()));
|
||||
BoundingBox::FromPoints(boundsCorners, 8, const_cast<BoundingBox&>(Actor->GetBoundingBox()));
|
||||
BoundingSphere::FromBox(Actor->GetBoundingBox(), const_cast<BoundingSphere&>(Actor->GetBoundingSphere()));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -458,7 +458,16 @@ bool ParseFloat(const C* str, T* ret)
|
||||
if (*str == 'e' || *str == 'E')
|
||||
{
|
||||
str++;
|
||||
T powerer = *str == '-' ? str++, (T)0.1 : (T)10;
|
||||
T powerer = (T)10;
|
||||
if (*str == '-')
|
||||
{
|
||||
powerer = (T)0.1;
|
||||
str++;
|
||||
}
|
||||
else if (*str == '+')
|
||||
{
|
||||
str++;
|
||||
}
|
||||
T power = 0;
|
||||
while (*str >= '0' && *str <= '9')
|
||||
{
|
||||
|
||||
@@ -39,6 +39,62 @@ inline bool IsWindowInvalid(Window* win)
|
||||
return !hasWindow || !win;
|
||||
}
|
||||
|
||||
inline Window* GetEngineWindow(NSWindow* nativeWindow)
|
||||
{
|
||||
WindowsManager::WindowsLocker.Lock();
|
||||
for (auto* window : WindowsManager::Windows)
|
||||
{
|
||||
if (window && window->GetNativePtr() == nativeWindow)
|
||||
{
|
||||
WindowsManager::WindowsLocker.Unlock();
|
||||
return window;
|
||||
}
|
||||
}
|
||||
WindowsManager::WindowsLocker.Unlock();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline bool ShouldAttachToParent(const CreateWindowSettings& settings)
|
||||
{
|
||||
// Cocoa child windows inherit parent z-order and minimize behavior.
|
||||
// Minimizable regular windows need independent top-level window semantics.
|
||||
return settings.Parent && (settings.Type != WindowType::Regular || !settings.AllowMinimize);
|
||||
}
|
||||
|
||||
inline bool CanMakeKeyWindow(NSWindow* window)
|
||||
{
|
||||
return window && [window isVisible] && ![window isMiniaturized] && [window canBecomeKeyWindow];
|
||||
}
|
||||
|
||||
inline bool IsRegularWindowWithParent(Window* window, Window* parent)
|
||||
{
|
||||
return window &&
|
||||
!window->IsClosed() &&
|
||||
window->GetSettings().Type == WindowType::Regular &&
|
||||
window->GetSettings().Parent == parent;
|
||||
}
|
||||
|
||||
inline void MakeNextParentedWindowKey(NSWindow* hiddenWindow, Window* fallbackParent)
|
||||
{
|
||||
if (!fallbackParent || IsWindowInvalid(fallbackParent))
|
||||
return;
|
||||
|
||||
for (NSWindow* candidate in [NSApp orderedWindows])
|
||||
{
|
||||
if (candidate == hiddenWindow || !CanMakeKeyWindow(candidate))
|
||||
continue;
|
||||
Window* candidateWindow = GetEngineWindow(candidate);
|
||||
if (!IsRegularWindowWithParent(candidateWindow, fallbackParent))
|
||||
continue;
|
||||
[candidate makeKeyAndOrderFront:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
NSWindow* parent = (NSWindow*)fallbackParent->GetNativePtr();
|
||||
if (parent != hiddenWindow && CanMakeKeyWindow(parent))
|
||||
[parent makeKeyAndOrderFront:nil];
|
||||
}
|
||||
|
||||
KeyboardKeys GetKey(NSEvent* event)
|
||||
{
|
||||
switch ([event keyCode])
|
||||
@@ -963,7 +1019,7 @@ void MacWindow::Show()
|
||||
|
||||
// Show
|
||||
NSWindow* window = (NSWindow*)_window;
|
||||
if (_settings.Parent)
|
||||
if (ShouldAttachToParent(_settings))
|
||||
{
|
||||
NSWindow* parent = (NSWindow*)_settings.Parent->GetNativePtr();
|
||||
[parent addChildWindow:window ordered:NSWindowAbove];
|
||||
@@ -989,18 +1045,17 @@ void MacWindow::Hide()
|
||||
|
||||
// Hide (order out doesn't work for miniaturized windows)
|
||||
NSWindow* window = (NSWindow*)_window;
|
||||
const BOOL wasKey = [window isKeyWindow];
|
||||
const BOOL wasKey = [window isKeyWindow] || [NSApp keyWindow] == window;
|
||||
if ([window isMiniaturized])
|
||||
[window close];
|
||||
else
|
||||
[window orderOut:nil];
|
||||
|
||||
// Transfer focus back to the parent when hiding popup
|
||||
if (_settings.Parent && wasKey && _settings.Type != WindowType::Popup && _settings.Type != WindowType::Tooltip)
|
||||
{
|
||||
NSWindow* parent = (NSWindow*)_settings.Parent->GetNativePtr();
|
||||
[parent makeKeyAndOrderFront:nil];
|
||||
}
|
||||
const bool shouldRestoreFocus = _settings.Parent &&
|
||||
_settings.Type == WindowType::Regular &&
|
||||
[NSApp isActive] &&
|
||||
(wasKey || [NSApp keyWindow] == nil);
|
||||
if (!IsClosed() && shouldRestoreFocus)
|
||||
MakeNextParentedWindowKey(window, _settings.Parent);
|
||||
|
||||
// Base
|
||||
WindowBase::Hide();
|
||||
@@ -1009,23 +1064,27 @@ void MacWindow::Hide()
|
||||
|
||||
void MacWindow::Close(ClosingReason reason)
|
||||
{
|
||||
const BOOL wasKey = _window && [(NSWindow*)_window isKeyWindow];
|
||||
NSWindow* window = (NSWindow*)_window;
|
||||
const BOOL shouldRestoreFocus = window &&
|
||||
_settings.Parent &&
|
||||
_settings.Type == WindowType::Regular &&
|
||||
[NSApp isActive] &&
|
||||
([window isKeyWindow] || [NSApp keyWindow] == window);
|
||||
|
||||
WindowBase::Close(reason);
|
||||
|
||||
// Closing can be cancelled by managed Window.Closing handlers.
|
||||
if (!IsClosed())
|
||||
return;
|
||||
|
||||
if (NSWindow* window = (NSWindow*)_window)
|
||||
{
|
||||
if (window)
|
||||
[window close];
|
||||
}
|
||||
|
||||
if (_settings.Parent && wasKey && _settings.Type != WindowType::Popup && _settings.Type != WindowType::Tooltip)
|
||||
{
|
||||
NSWindow* parent = (NSWindow*)_settings.Parent->GetNativePtr();
|
||||
[parent makeKeyAndOrderFront:nil];
|
||||
}
|
||||
const bool hasNoKeyWindow = _settings.Parent &&
|
||||
_settings.Type == WindowType::Regular &&
|
||||
[NSApp isActive] &&
|
||||
[NSApp keyWindow] == nil;
|
||||
if (shouldRestoreFocus || hasNoKeyWindow)
|
||||
MakeNextParentedWindowKey(window, _settings.Parent);
|
||||
}
|
||||
|
||||
void MacWindow::Minimize()
|
||||
|
||||
@@ -149,7 +149,7 @@ WindowsWindow::WindowsWindow(const CreateWindowSettings& settings)
|
||||
const HMODULE user32Dll = LoadLibraryW(L"user32.dll");
|
||||
if (user32Dll)
|
||||
{
|
||||
typedef UINT (STDAPICALLTYPE*GetDpiForWindowProc)(HWND hwnd);
|
||||
typedef UINT(STDAPICALLTYPE* GetDpiForWindowProc)(HWND hwnd);
|
||||
const GetDpiForWindowProc getDpiForWindowProc = (GetDpiForWindowProc)GetProcAddress(user32Dll, "GetDpiForWindow");
|
||||
if (getDpiForWindowProc)
|
||||
{
|
||||
@@ -848,7 +848,7 @@ void WindowsWindow::UpdateCursor()
|
||||
if (!_lastCursorHidden)
|
||||
{
|
||||
_lastCursorHidden = true;
|
||||
while(::ShowCursor(FALSE) >= 0)
|
||||
while (::ShowCursor(FALSE) >= 0)
|
||||
{
|
||||
if (_cursorHiddenSafetyCount >= 100)
|
||||
{
|
||||
|
||||
@@ -412,7 +412,7 @@ public:
|
||||
void OnSceneRenderingAddActor(SceneRendering* scene, int32 key, Actor* a) override
|
||||
{
|
||||
if (a->HasStaticFlag(StaticFlags::Shadow))
|
||||
DirtyStaticBounds(a->GetSphere());
|
||||
DirtyStaticBounds(a->GetBoundingSphere());
|
||||
}
|
||||
|
||||
void OnSceneRenderingUpdateActor(SceneRendering* scene, int32 key, Actor* a, const BoundingSphere& prevBounds, UpdateFlags flags) override
|
||||
@@ -421,7 +421,7 @@ public:
|
||||
if (a->HasStaticFlag(StaticFlags::Shadow))
|
||||
{
|
||||
// TODO: skip actors that don't cast shadows (eg. particles)
|
||||
BoundingSphere bounds = a->GetSphere();
|
||||
BoundingSphere bounds = a->GetBoundingSphere();
|
||||
if (bounds != prevBounds)
|
||||
{
|
||||
// Avoid dirtying twice when bounds are close to each other
|
||||
@@ -434,14 +434,14 @@ public:
|
||||
}
|
||||
else if (flags & StaticFlags)
|
||||
{
|
||||
DirtyStaticBounds(a->GetSphere());
|
||||
DirtyStaticBounds(a->GetBoundingSphere());
|
||||
}
|
||||
}
|
||||
|
||||
void OnSceneRenderingRemoveActor(SceneRendering* scene, int32 key, Actor* a) override
|
||||
{
|
||||
if (a->HasStaticFlag(StaticFlags::Shadow))
|
||||
DirtyStaticBounds(a->GetSphere());
|
||||
DirtyStaticBounds(a->GetBoundingSphere());
|
||||
}
|
||||
|
||||
void OnSceneRenderingClear(SceneRendering* scene) override
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user