Merge remote-tracking branch 'origin/master' into 1.9
# Conflicts: # Flax.flaxproj
This commit is contained in:
@@ -74,6 +74,7 @@
|
|||||||
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></s:String>
|
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION_005FMEMBER/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></s:String>
|
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION_005FMEMBER/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /></s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AI/@EntryIndexedValue">AI</s:String>
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AI/@EntryIndexedValue">AI</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ARGB/@EntryIndexedValue">ARGB</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LO/@EntryIndexedValue">LO</s:String>
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=LO/@EntryIndexedValue">LO</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RPC/@EntryIndexedValue">RPC</s:String>
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RPC/@EntryIndexedValue">RPC</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SDK/@EntryIndexedValue">SDK</s:String>
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SDK/@EntryIndexedValue">SDK</s:String>
|
||||||
|
|||||||
@@ -75,7 +75,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
|
|
||||||
// Selecting actor prefab asset
|
// Selecting actor prefab asset
|
||||||
var selectPrefab = panel.Button("Select Prefab");
|
var selectPrefab = panel.Button("Select Prefab");
|
||||||
selectPrefab.Button.Clicked += () => Editor.Instance.Windows.ContentWin.Select(prefab);
|
selectPrefab.Button.Clicked += () =>
|
||||||
|
{
|
||||||
|
Editor.Instance.Windows.ContentWin.ClearItemsSearch();
|
||||||
|
Editor.Instance.Windows.ContentWin.Select(prefab);
|
||||||
|
};
|
||||||
|
|
||||||
// Viewing changes applied to this actor
|
// Viewing changes applied to this actor
|
||||||
var viewChanges = panel.Button("View Changes");
|
var viewChanges = panel.Button("View Changes");
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
var collection = (CollectionAttribute)attributes?.FirstOrDefault(x => x is CollectionAttribute);
|
var collection = (CollectionAttribute)attributes?.FirstOrDefault(x => x is CollectionAttribute);
|
||||||
if (collection != null)
|
if (collection != null)
|
||||||
{
|
{
|
||||||
_canResize = !collection.ReadOnly;
|
_canResize = collection.CanResize;
|
||||||
_readOnly = collection.ReadOnly;
|
_readOnly = collection.ReadOnly;
|
||||||
_minCount = collection.MinCount;
|
_minCount = collection.MinCount;
|
||||||
_maxCount = collection.MaxCount;
|
_maxCount = collection.MaxCount;
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
var collection = (CollectionAttribute)attributes?.FirstOrDefault(x => x is CollectionAttribute);
|
var collection = (CollectionAttribute)attributes?.FirstOrDefault(x => x is CollectionAttribute);
|
||||||
if (collection != null)
|
if (collection != null)
|
||||||
{
|
{
|
||||||
|
_canEditKeys &= collection.CanReorderItems;
|
||||||
_readOnly = collection.ReadOnly;
|
_readOnly = collection.ReadOnly;
|
||||||
_notNullItems = collection.NotNullItems;
|
_notNullItems = collection.NotNullItems;
|
||||||
if (collection.BackgroundColor.HasValue)
|
if (collection.BackgroundColor.HasValue)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
if (watermarkAttribute is WatermarkAttribute watermark)
|
if (watermarkAttribute is WatermarkAttribute watermark)
|
||||||
{
|
{
|
||||||
_watermarkText = watermark.WatermarkText;
|
_watermarkText = watermark.WatermarkText;
|
||||||
var watermarkColor = watermark.WatermarkColor > 0 ? Color.FromRGBA(watermark.WatermarkColor) : FlaxEngine.GUI.Style.Current.ForegroundDisabled;
|
var watermarkColor = watermark.WatermarkColor > 0 ? Color.FromRGB(watermark.WatermarkColor) : FlaxEngine.GUI.Style.Current.ForegroundDisabled;
|
||||||
_watermarkColor = watermarkColor;
|
_watermarkColor = watermarkColor;
|
||||||
_element.TextBox.WatermarkText = watermark.WatermarkText;
|
_element.TextBox.WatermarkText = watermark.WatermarkText;
|
||||||
_element.TextBox.WatermarkTextColor = watermarkColor;
|
_element.TextBox.WatermarkTextColor = watermarkColor;
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ namespace FlaxEditor.CustomEditors
|
|||||||
if (header.FontSize > 0)
|
if (header.FontSize > 0)
|
||||||
element.Label.Font = new FontReference(element.Label.Font.Font, header.FontSize);
|
element.Label.Font = new FontReference(element.Label.Font.Font, header.FontSize);
|
||||||
if (header.Color > 0)
|
if (header.Color > 0)
|
||||||
element.Label.TextColor = Color.FromRGBA(header.Color);
|
element.Label.TextColor = Color.FromRGB(header.Color);
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
|
|||||||
/// The keyframes.
|
/// The keyframes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EditorDisplay("Keyframes", EditorDisplayAttribute.InlineStyle), ExpandGroups]
|
[EditorDisplay("Keyframes", EditorDisplayAttribute.InlineStyle), ExpandGroups]
|
||||||
[Collection(CanReorderItems = false, ReadOnly = true)]
|
[Collection(CanReorderItems = false, CanResize = true)]
|
||||||
public List<KeyValuePair<string, object>> Keyframes;
|
public List<KeyValuePair<string, object>> Keyframes;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks
|
|||||||
/// The parameters values.
|
/// The parameters values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EditorDisplay("Parameters", EditorDisplayAttribute.InlineStyle), ExpandGroups]
|
[EditorDisplay("Parameters", EditorDisplayAttribute.InlineStyle), ExpandGroups]
|
||||||
[Collection(CanReorderItems = false, ReadOnly = true)]
|
[Collection(CanReorderItems = false, CanResize = true)]
|
||||||
public object[] Parameters;
|
public object[] Parameters;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -253,7 +253,11 @@ namespace FlaxEditor
|
|||||||
{
|
{
|
||||||
// Select node (with additive mode)
|
// Select node (with additive mode)
|
||||||
var selection = new List<SceneGraphNode>();
|
var selection = new List<SceneGraphNode>();
|
||||||
if (Root.GetKey(KeyboardKeys.Control))
|
if (Root.GetKey(KeyboardKeys.Shift) && transformGizmo.Selection.Contains(uiControlNode))
|
||||||
|
{
|
||||||
|
// Move whole selection
|
||||||
|
}
|
||||||
|
else if (Root.GetKey(KeyboardKeys.Control))
|
||||||
{
|
{
|
||||||
// Add/remove from selection
|
// Add/remove from selection
|
||||||
selection.AddRange(transformGizmo.Selection);
|
selection.AddRange(transformGizmo.Selection);
|
||||||
@@ -261,13 +265,14 @@ namespace FlaxEditor
|
|||||||
selection.Remove(uiControlNode);
|
selection.Remove(uiControlNode);
|
||||||
else
|
else
|
||||||
selection.Add(uiControlNode);
|
selection.Add(uiControlNode);
|
||||||
|
owner.Select(selection);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Select
|
// Select
|
||||||
selection.Add(uiControlNode);
|
selection.Add(uiControlNode);
|
||||||
|
owner.Select(selection);
|
||||||
}
|
}
|
||||||
owner.Select(selection);
|
|
||||||
|
|
||||||
// Initialize control movement
|
// Initialize control movement
|
||||||
_mouseMovesControl = true;
|
_mouseMovesControl = true;
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ namespace FlaxEditor.Modules
|
|||||||
|
|
||||||
var prefabId = ((ActorNode)selection[0]).Actor.PrefabID;
|
var prefabId = ((ActorNode)selection[0]).Actor.PrefabID;
|
||||||
var prefab = FlaxEngine.Content.LoadAsync<Prefab>(prefabId);
|
var prefab = FlaxEngine.Content.LoadAsync<Prefab>(prefabId);
|
||||||
|
Editor.Windows.ContentWin.ClearItemsSearch();
|
||||||
Editor.Windows.ContentWin.Select(prefab);
|
Editor.Windows.ContentWin.Select(prefab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -565,6 +565,7 @@ namespace FlaxEditor.Modules
|
|||||||
if (item != null)
|
if (item != null)
|
||||||
Editor.ContentEditing.Open(item);
|
Editor.ContentEditing.Open(item);
|
||||||
});
|
});
|
||||||
|
cm.AddButton("Editor Options", () => Editor.Windows.EditorOptionsWin.Show());
|
||||||
|
|
||||||
// Scene
|
// Scene
|
||||||
MenuScene = MainMenu.AddButton("Scene");
|
MenuScene = MainMenu.AddButton("Scene");
|
||||||
@@ -619,7 +620,6 @@ namespace FlaxEditor.Modules
|
|||||||
_menuToolsTakeScreenshot = cm.AddButton("Take screenshot", inputOptions.TakeScreenshot, Editor.Windows.TakeScreenshot);
|
_menuToolsTakeScreenshot = cm.AddButton("Take screenshot", inputOptions.TakeScreenshot, Editor.Windows.TakeScreenshot);
|
||||||
cm.AddSeparator();
|
cm.AddSeparator();
|
||||||
cm.AddButton("Plugins", () => Editor.Windows.PluginsWin.Show());
|
cm.AddButton("Plugins", () => Editor.Windows.PluginsWin.Show());
|
||||||
cm.AddButton("Options", () => Editor.Windows.EditorOptionsWin.Show());
|
|
||||||
|
|
||||||
// Window
|
// Window
|
||||||
MenuWindow = MainMenu.AddButton("Window");
|
MenuWindow = MainMenu.AddButton("Window");
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace FlaxEditor.Tools.Foliage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[EditorOrder(20), EditorDisplay("Model"), Collection(ReadOnly = true), Tooltip("Model materials override collection. Can be used to change a specific material of the mesh to the custom one without editing the asset.")]
|
[EditorOrder(20), EditorDisplay("Model"), Collection(CanResize = true), Tooltip("Model materials override collection. Can be used to change a specific material of the mesh to the custom one without editing the asset.")]
|
||||||
public MaterialBase[] Materials
|
public MaterialBase[] Materials
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|||||||
@@ -155,8 +155,8 @@ namespace FlaxEditor.Utilities
|
|||||||
var scene = Level.LoadSceneFromBytes(data.Bytes);
|
var scene = Level.LoadSceneFromBytes(data.Bytes);
|
||||||
if (scene == null)
|
if (scene == null)
|
||||||
{
|
{
|
||||||
Profiler.EndEvent();
|
Editor.LogError("Failed to restore scene");
|
||||||
throw new Exception("Failed to deserialize scene");
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore `dirty` state
|
// Restore `dirty` state
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ namespace FlaxEditor.Windows
|
|||||||
public void ClearItemsSearch()
|
public void ClearItemsSearch()
|
||||||
{
|
{
|
||||||
// Skip if already cleared
|
// Skip if already cleared
|
||||||
if (_itemsSearchBox.TextLength == 0 && !_viewDropdown.HasSelection)
|
if (_itemsSearchBox.TextLength == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IsLayoutLocked = true;
|
IsLayoutLocked = true;
|
||||||
|
|||||||
@@ -860,7 +860,7 @@ namespace FlaxEditor.Windows
|
|||||||
{
|
{
|
||||||
var alpha = Mathf.Saturate(-animTime / fadeOutTime);
|
var alpha = Mathf.Saturate(-animTime / fadeOutTime);
|
||||||
var rect = new Rectangle(new Float2(6), Size - 12);
|
var rect = new Rectangle(new Float2(6), Size - 12);
|
||||||
var text = "Press Shift+F11 to unlock the mouse";
|
var text = $"Press {Editor.Options.Options.Input.DebuggerUnlockMouse} to unlock the mouse";
|
||||||
Render2D.DrawText(style.FontSmall, text, rect + new Float2(1.0f), style.Background * alpha, TextAlignment.Near, TextAlignment.Far);
|
Render2D.DrawText(style.FontSmall, text, rect + new Float2(1.0f), style.Background * alpha, TextAlignment.Near, TextAlignment.Far);
|
||||||
Render2D.DrawText(style.FontSmall, text, rect, style.Foreground * alpha, TextAlignment.Near, TextAlignment.Far);
|
Render2D.DrawText(style.FontSmall, text, rect, style.Foreground * alpha, TextAlignment.Near, TextAlignment.Far);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,10 @@ namespace Serialization
|
|||||||
{
|
{
|
||||||
const auto& keyframesArray = mKeyframes->value.GetArray();
|
const auto& keyframesArray = mKeyframes->value.GetArray();
|
||||||
auto& keyframes = v.GetKeyframes();
|
auto& keyframes = v.GetKeyframes();
|
||||||
|
const int32 newCount = keyframesArray.Size() - keyframes.Count();
|
||||||
keyframes.Resize(keyframesArray.Size());
|
keyframes.Resize(keyframesArray.Size());
|
||||||
|
for (int32 i = 0; i < newCount; i++)
|
||||||
|
keyframes[keyframes.Count() + i - newCount] = KeyFrame(0.0f, AnimationUtils::GetZero<T>());
|
||||||
for (rapidjson::SizeType i = 0; i < keyframesArray.Size(); i++)
|
for (rapidjson::SizeType i = 0; i < keyframesArray.Size(); i++)
|
||||||
Deserialize(keyframesArray[i], keyframes[i], modifier);
|
Deserialize(keyframesArray[i], keyframes[i], modifier);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ void InverseKinematics::SolveTwoBoneIK(Transform& rootTransform, Transform& midJ
|
|||||||
// Calculate new positions for joint and end effector
|
// Calculate new positions for joint and end effector
|
||||||
Vector3 newEndEffectorPos = targetPosition;
|
Vector3 newEndEffectorPos = targetPosition;
|
||||||
Vector3 newMidJointPos = midJointPos;
|
Vector3 newMidJointPos = midJointPos;
|
||||||
|
|
||||||
if (toTargetLength >= totalLimbLength)
|
if (toTargetLength >= totalLimbLength)
|
||||||
{
|
{
|
||||||
// Target is beyond the reach of the limb
|
// Target is beyond the reach of the limb
|
||||||
@@ -90,13 +89,9 @@ void InverseKinematics::SolveTwoBoneIK(Transform& rootTransform, Transform& midJ
|
|||||||
Vector3 rootToPole = (poleVector - rootTransform.Translation).GetNormalized();
|
Vector3 rootToPole = (poleVector - rootTransform.Translation).GetNormalized();
|
||||||
Vector3 slightBendDirection = Vector3::Cross(rootToEnd, rootToPole);
|
Vector3 slightBendDirection = Vector3::Cross(rootToEnd, rootToPole);
|
||||||
if (slightBendDirection.LengthSquared() < ZeroTolerance * ZeroTolerance)
|
if (slightBendDirection.LengthSquared() < ZeroTolerance * ZeroTolerance)
|
||||||
{
|
|
||||||
slightBendDirection = Vector3::Up;
|
slightBendDirection = Vector3::Up;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
slightBendDirection.Normalize();
|
slightBendDirection.Normalize();
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the direction from root to mid joint with a slight offset towards the pole vector
|
// Calculate the direction from root to mid joint with a slight offset towards the pole vector
|
||||||
Vector3 midJointDirection = Vector3::Cross(slightBendDirection, rootToEnd).GetNormalized();
|
Vector3 midJointDirection = Vector3::Cross(slightBendDirection, rootToEnd).GetNormalized();
|
||||||
@@ -117,9 +112,16 @@ void InverseKinematics::SolveTwoBoneIK(Transform& rootTransform, Transform& midJ
|
|||||||
projJointDist *= -1.0f;
|
projJointDist *= -1.0f;
|
||||||
newMidJointPos = rootTransform.Translation + projJointDist * toTargetDir + jointLineDist * bendDirection;
|
newMidJointPos = rootTransform.Translation + projJointDist * toTargetDir + jointLineDist * bendDirection;
|
||||||
}
|
}
|
||||||
|
// TODO: fix the new IK impl (https://github.com/FlaxEngine/FlaxEngine/pull/2421) to properly work for character from https://github.com/PrecisionRender/CharacterControllerPro
|
||||||
|
#define OLD 0
|
||||||
// Update root joint orientation
|
// Update root joint orientation
|
||||||
{
|
{
|
||||||
|
#if OLD
|
||||||
|
const Vector3 oldDir = (midJointPos - rootTransform.Translation).GetNormalized();
|
||||||
|
const Vector3 newDir = (newMidJointPos - rootTransform.Translation).GetNormalized();
|
||||||
|
const Quaternion deltaRotation = Quaternion::FindBetween(oldDir, newDir);
|
||||||
|
rootTransform.Orientation = deltaRotation * rootTransform.Orientation;
|
||||||
|
#else
|
||||||
// Vector from root joint to mid joint (local Y-axis direction)
|
// Vector from root joint to mid joint (local Y-axis direction)
|
||||||
Vector3 localY = (newMidJointPos - rootTransform.Translation).GetNormalized();
|
Vector3 localY = (newMidJointPos - rootTransform.Translation).GetNormalized();
|
||||||
|
|
||||||
@@ -136,20 +138,23 @@ void InverseKinematics::SolveTwoBoneIK(Transform& rootTransform, Transform& midJ
|
|||||||
localZ = Vector3::Cross(localX, localY).GetNormalized();
|
localZ = Vector3::Cross(localX, localY).GetNormalized();
|
||||||
|
|
||||||
// Construct a rotation from the orthogonal basis vectors
|
// Construct a rotation from the orthogonal basis vectors
|
||||||
Quaternion newRootJointOrientation = Quaternion::LookRotation(localZ, localY);
|
rootTransform.Orientation = Quaternion::LookRotation(localZ, localY);
|
||||||
|
#endif
|
||||||
// Apply the new rotation to the root joint
|
|
||||||
rootTransform.Orientation = newRootJointOrientation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update mid joint orientation to point Y-axis towards the end effector and Z-axis perpendicular to the IK plane
|
// Update mid joint orientation to point Y-axis towards the end effector and Z-axis perpendicular to the IK plane
|
||||||
{
|
{
|
||||||
|
#if OLD
|
||||||
|
const Vector3 oldDir = (endEffectorTransform.Translation - midJointPos).GetNormalized();
|
||||||
|
const Vector3 newDir = (newEndEffectorPos - newMidJointPos).GetNormalized();
|
||||||
|
const Quaternion deltaRotation = Quaternion::FindBetween(oldDir, newDir);
|
||||||
|
midJointTransform.Orientation = deltaRotation * midJointTransform.Orientation;
|
||||||
|
#else
|
||||||
// Vector from mid joint to end effector (local Y-axis direction after rotation)
|
// Vector from mid joint to end effector (local Y-axis direction after rotation)
|
||||||
Vector3 midToEnd = (newEndEffectorPos - newMidJointPos).GetNormalized();
|
Vector3 midToEnd = (newEndEffectorPos - newMidJointPos).GetNormalized();
|
||||||
|
|
||||||
// Calculate the plane normal using the root, mid joint, and end effector positions (will be the local Z-axis direction)
|
// Calculate the plane normal using the root, mid joint, and end effector positions (will be the local Z-axis direction)
|
||||||
Vector3 rootToMid = (newMidJointPos - rootTransform.Translation).GetNormalized();
|
Vector3 rootToMid = (newMidJointPos - rootTransform.Translation).GetNormalized();
|
||||||
Vector3 planeNormal = Vector3::Cross(rootToMid, midToEnd).GetNormalized();
|
|
||||||
|
|
||||||
// Vector from mid joint to end effector (local Y-axis direction)
|
// Vector from mid joint to end effector (local Y-axis direction)
|
||||||
Vector3 localY = (newEndEffectorPos - newMidJointPos).GetNormalized();
|
Vector3 localY = (newEndEffectorPos - newMidJointPos).GetNormalized();
|
||||||
@@ -157,21 +162,18 @@ void InverseKinematics::SolveTwoBoneIK(Transform& rootTransform, Transform& midJ
|
|||||||
// Calculate the plane normal using the root, mid joint, and end effector positions (local Z-axis direction)
|
// Calculate the plane normal using the root, mid joint, and end effector positions (local Z-axis direction)
|
||||||
Vector3 localZ = Vector3::Cross(rootToMid, localY).GetNormalized();
|
Vector3 localZ = Vector3::Cross(rootToMid, localY).GetNormalized();
|
||||||
|
|
||||||
//// Calculate the local X-axis direction, should be perpendicular to the Y and Z axes
|
// Calculate the local X-axis direction, should be perpendicular to the Y and Z axes
|
||||||
Vector3 localX = Vector3::Cross(localY, localZ).GetNormalized();
|
Vector3 localX = Vector3::Cross(localY, localZ).GetNormalized();
|
||||||
|
|
||||||
// Correct the local Z-axis direction based on the cross product of X and Y to ensure orthogonality
|
// Correct the local Z-axis direction based on the cross product of X and Y to ensure orthogonality
|
||||||
localZ = Vector3::Cross(localX, localY).GetNormalized();
|
localZ = Vector3::Cross(localX, localY).GetNormalized();
|
||||||
|
|
||||||
// Construct a rotation from the orthogonal basis vectors
|
// Construct a rotation from the orthogonal basis vectors
|
||||||
// The axes are used differently here than a standard LookRotation to align Z towards the end and Y perpendicular
|
midJointTransform.Orientation = Quaternion::LookRotation(localZ, localY);
|
||||||
Quaternion newMidJointOrientation = Quaternion::LookRotation(localZ, localY); // Assuming FromLookRotation creates a rotation with the first vector as forward and the second as up
|
#endif
|
||||||
|
|
||||||
// Apply the new rotation to the mid joint
|
|
||||||
midJointTransform.Orientation = newMidJointOrientation;
|
|
||||||
midJointTransform.Translation = newMidJointPos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update end effector transform
|
// Update mid and end locations
|
||||||
|
midJointTransform.Translation = newMidJointPos;
|
||||||
endEffectorTransform.Translation = newEndEffectorPos;
|
endEffectorTransform.Translation = newEndEffectorPos;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,6 +187,9 @@ Asset::LoadResult Material::load()
|
|||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
// Guard file with the lock during shader generation (prevents FlaxStorage::Tick from messing with the file)
|
||||||
|
auto lock = Storage->Lock();
|
||||||
|
|
||||||
// Prepare
|
// Prepare
|
||||||
MaterialGenerator generator;
|
MaterialGenerator generator;
|
||||||
generator.Error.Bind(&OnGeneratorError);
|
generator.Error.Bind(&OnGeneratorError);
|
||||||
|
|||||||
@@ -252,6 +252,7 @@ void ContentStorageSystem::Job(int32 index)
|
|||||||
{
|
{
|
||||||
PROFILE_CPU_NAMED("ContentStorage.Job");
|
PROFILE_CPU_NAMED("ContentStorage.Job");
|
||||||
|
|
||||||
|
const double time = Platform::GetTimeSeconds();
|
||||||
ScopeLock lock(Locker);
|
ScopeLock lock(Locker);
|
||||||
for (auto i = StorageMap.Begin(); i.IsNotEnd(); ++i)
|
for (auto i = StorageMap.Begin(); i.IsNotEnd(); ++i)
|
||||||
{
|
{
|
||||||
@@ -271,7 +272,7 @@ void ContentStorageSystem::Job(int32 index)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
storage->Tick();
|
storage->Tick(time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1337,9 +1337,6 @@ bool FlaxStorage::CloseFileHandles()
|
|||||||
{
|
{
|
||||||
if (Platform::AtomicRead(&_chunksLock) == 0 && Platform::AtomicRead(&_files) == 0)
|
if (Platform::AtomicRead(&_chunksLock) == 0 && Platform::AtomicRead(&_files) == 0)
|
||||||
{
|
{
|
||||||
Array<FileReadStream*, InlinedAllocation<8>> streams;
|
|
||||||
_file.GetValues(streams);
|
|
||||||
ASSERT(streams.Count() == 0);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PROFILE_CPU();
|
PROFILE_CPU();
|
||||||
@@ -1401,19 +1398,18 @@ void FlaxStorage::Dispose()
|
|||||||
_version = 0;
|
_version = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlaxStorage::Tick()
|
void FlaxStorage::Tick(double time)
|
||||||
{
|
{
|
||||||
// Check if chunks are locked
|
// Skip if file is in use
|
||||||
if (Platform::AtomicRead(&_chunksLock) != 0)
|
if (Platform::AtomicRead(&_chunksLock) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const double now = Platform::GetTimeSeconds();
|
|
||||||
bool wasAnyUsed = false;
|
bool wasAnyUsed = false;
|
||||||
const float unusedDataChunksLifetime = ContentStorageManager::UnusedDataChunksLifetime.GetTotalSeconds();
|
const float unusedDataChunksLifetime = ContentStorageManager::UnusedDataChunksLifetime.GetTotalSeconds();
|
||||||
for (int32 i = 0; i < _chunks.Count(); i++)
|
for (int32 i = 0; i < _chunks.Count(); i++)
|
||||||
{
|
{
|
||||||
auto chunk = _chunks.Get()[i];
|
auto chunk = _chunks.Get()[i];
|
||||||
const bool wasUsed = (now - chunk->LastAccessTime) < unusedDataChunksLifetime;
|
const bool wasUsed = (time - chunk->LastAccessTime) < unusedDataChunksLifetime;
|
||||||
if (!wasUsed && chunk->IsLoaded())
|
if (!wasUsed && chunk->IsLoaded())
|
||||||
{
|
{
|
||||||
chunk->Unload();
|
chunk->Unload();
|
||||||
@@ -1421,7 +1417,7 @@ void FlaxStorage::Tick()
|
|||||||
wasAnyUsed |= wasUsed;
|
wasAnyUsed |= wasUsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release file handles in none of chunks was not used
|
// Release file handles in none of chunks is in use
|
||||||
if (!wasAnyUsed && Platform::AtomicRead(&_chunksLock) == 0)
|
if (!wasAnyUsed && Platform::AtomicRead(&_chunksLock) == 0)
|
||||||
{
|
{
|
||||||
CloseFileHandles();
|
CloseFileHandles();
|
||||||
|
|||||||
@@ -416,7 +416,7 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ticks this instance.
|
/// Ticks this instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Tick();
|
void Tick(double time);
|
||||||
|
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
void OnRename(const StringView& newPath);
|
void OnRename(const StringView& newPath);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace FlaxEditor.Content.Settings
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The layers names.
|
/// The layers names.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EditorOrder(10), EditorDisplay("Layers", EditorDisplayAttribute.InlineStyle), Collection(ReadOnly = true, Display = CollectionAttribute.DisplayType.Inline)]
|
[EditorOrder(10), EditorDisplay("Layers", EditorDisplayAttribute.InlineStyle), Collection(CanResize = true, Display = CollectionAttribute.DisplayType.Inline)]
|
||||||
public string[] Layers = new string[32];
|
public string[] Layers = new string[32];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -32,41 +32,39 @@ Color::Color(const Color32& color)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Color::FromHex(const String& hexString, bool& isValid)
|
Color Color::FromHex(const String& hex, bool& isValid)
|
||||||
{
|
{
|
||||||
int32 r, g, b, a = 255;
|
int32 r, g, b, a = 255;
|
||||||
isValid = true;
|
isValid = true;
|
||||||
|
int32 startIndex = !hex.IsEmpty() && hex[0] == Char('#') ? 1 : 0;
|
||||||
int32 startIndex = !hexString.IsEmpty() && hexString[0] == Char('#') ? 1 : 0;
|
if (hex.Length() == 3 + startIndex)
|
||||||
if (hexString.Length() == 3 + startIndex)
|
|
||||||
{
|
{
|
||||||
r = StringUtils::HexDigit(hexString[startIndex++]);
|
r = StringUtils::HexDigit(hex[startIndex++]);
|
||||||
g = StringUtils::HexDigit(hexString[startIndex++]);
|
g = StringUtils::HexDigit(hex[startIndex++]);
|
||||||
b = StringUtils::HexDigit(hexString[startIndex]);
|
b = StringUtils::HexDigit(hex[startIndex]);
|
||||||
|
|
||||||
r = (r << 4) + r;
|
r = (r << 4) + r;
|
||||||
g = (g << 4) + g;
|
g = (g << 4) + g;
|
||||||
b = (b << 4) + b;
|
b = (b << 4) + b;
|
||||||
}
|
}
|
||||||
else if (hexString.Length() == 6 + startIndex)
|
else if (hex.Length() == 6 + startIndex)
|
||||||
{
|
{
|
||||||
r = (StringUtils::HexDigit(hexString[startIndex + 0]) << 4) + StringUtils::HexDigit(hexString[startIndex + 1]);
|
r = (StringUtils::HexDigit(hex[startIndex + 0]) << 4) + StringUtils::HexDigit(hex[startIndex + 1]);
|
||||||
g = (StringUtils::HexDigit(hexString[startIndex + 2]) << 4) + StringUtils::HexDigit(hexString[startIndex + 3]);
|
g = (StringUtils::HexDigit(hex[startIndex + 2]) << 4) + StringUtils::HexDigit(hex[startIndex + 3]);
|
||||||
b = (StringUtils::HexDigit(hexString[startIndex + 4]) << 4) + StringUtils::HexDigit(hexString[startIndex + 5]);
|
b = (StringUtils::HexDigit(hex[startIndex + 4]) << 4) + StringUtils::HexDigit(hex[startIndex + 5]);
|
||||||
}
|
}
|
||||||
else if (hexString.Length() == 8 + startIndex)
|
else if (hex.Length() == 8 + startIndex)
|
||||||
{
|
{
|
||||||
r = (StringUtils::HexDigit(hexString[startIndex + 0]) << 4) + StringUtils::HexDigit(hexString[startIndex + 1]);
|
r = (StringUtils::HexDigit(hex[startIndex + 0]) << 4) + StringUtils::HexDigit(hex[startIndex + 1]);
|
||||||
g = (StringUtils::HexDigit(hexString[startIndex + 2]) << 4) + StringUtils::HexDigit(hexString[startIndex + 3]);
|
g = (StringUtils::HexDigit(hex[startIndex + 2]) << 4) + StringUtils::HexDigit(hex[startIndex + 3]);
|
||||||
b = (StringUtils::HexDigit(hexString[startIndex + 4]) << 4) + StringUtils::HexDigit(hexString[startIndex + 5]);
|
b = (StringUtils::HexDigit(hex[startIndex + 4]) << 4) + StringUtils::HexDigit(hex[startIndex + 5]);
|
||||||
a = (StringUtils::HexDigit(hexString[startIndex + 6]) << 4) + StringUtils::HexDigit(hexString[startIndex + 7]);
|
a = (StringUtils::HexDigit(hex[startIndex + 6]) << 4) + StringUtils::HexDigit(hex[startIndex + 7]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
r = g = b = 0;
|
r = g = b = 0;
|
||||||
isValid = false;
|
isValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FromBytes(r, g, b, a);
|
return FromBytes(r, g, b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,8 +120,9 @@ String Color::ToHexString() const
|
|||||||
const byte r = static_cast<byte>(R * MAX_uint8);
|
const byte r = static_cast<byte>(R * MAX_uint8);
|
||||||
const byte g = static_cast<byte>(G * MAX_uint8);
|
const byte g = static_cast<byte>(G * MAX_uint8);
|
||||||
const byte b = static_cast<byte>(B * MAX_uint8);
|
const byte b = static_cast<byte>(B * MAX_uint8);
|
||||||
|
const byte a = static_cast<byte>(A * MAX_uint8);
|
||||||
|
|
||||||
Char result[6];
|
Char result[8];
|
||||||
|
|
||||||
result[0] = digits[r >> 4 & 0x0f];
|
result[0] = digits[r >> 4 & 0x0f];
|
||||||
result[1] = digits[r & 0x0f];
|
result[1] = digits[r & 0x0f];
|
||||||
@@ -134,7 +133,10 @@ String Color::ToHexString() const
|
|||||||
result[4] = digits[b >> 4 & 0x0f];
|
result[4] = digits[b >> 4 & 0x0f];
|
||||||
result[5] = digits[b & 0x0f];
|
result[5] = digits[b & 0x0f];
|
||||||
|
|
||||||
return String(result, 6);
|
result[6] = digits[a >> 4 & 0x0f];
|
||||||
|
result[7] = digits[a & 0x0f];
|
||||||
|
|
||||||
|
return String(result, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Color::IsTransparent() const
|
bool Color::IsTransparent() const
|
||||||
|
|||||||
@@ -230,36 +230,93 @@ namespace FlaxEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates <see cref="Color"/> from the RGB value and separate alpha channel.
|
/// Creates <see cref="Color"/> from the RGB value (bottom bits contain Blue) and separate alpha channel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rgb">The packed RGB value.</param>
|
/// <param name="rgb">The packed RGB value (bottom bits contain Blue).</param>
|
||||||
/// <param name="a">The alpha channel value.</param>
|
/// <param name="a">The alpha channel value.</param>
|
||||||
/// <returns>The color.</returns>
|
/// <returns>The color.</returns>
|
||||||
public static Color FromRGB(uint rgb, float a = 1.0f)
|
public static Color FromRGB(uint rgb, float a = 1.0f)
|
||||||
{
|
{
|
||||||
return new Color(
|
return new Color(((rgb >> 16) & 0xff) / 255.0f, ((rgb >> 8) & 0xff) / 255.0f, (rgb & 0xff) / 255.0f, a);
|
||||||
((rgb >> 16) & 0xff) / 255.0f,
|
|
||||||
((rgb >> 8) & 0xff) / 255.0f,
|
|
||||||
(rgb & 0xff) / 255.0f,
|
|
||||||
a);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates <see cref="Color"/> from the RGBA value.
|
/// Creates <see cref="Color"/> from the ARGB value (bottom bits contain Blue).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rgb">The packed RGBA value.</param>
|
/// <param name="argb">The packed ARGB value (bottom bits contain Blue).</param>
|
||||||
/// <returns>The color.</returns>
|
/// <returns>The color.</returns>
|
||||||
public static Color FromRGBA(uint rgb)
|
public static Color FromARGB(uint argb)
|
||||||
{
|
{
|
||||||
return new Color(
|
return new Color(((argb >> 16) & 0xff) / 255.0f, ((argb >> 8) & 0xff) / 255.0f, ((argb >> 0) & 0xff) / 255.0f, ((argb >> 24) & 0xff) / 255.0f);
|
||||||
((rgb >> 16) & 0xff) / 255.0f,
|
|
||||||
((rgb >> 8) & 0xff) / 255.0f,
|
|
||||||
(rgb & 0xff) / 255.0f,
|
|
||||||
((rgb >> 24) & 0xff) / 255.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the color value as the hexadecimal string.
|
/// Creates <see cref="Color"/> from the RGBA value (bottom bits contain Alpha).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rgba">The packed RGBA value (bottom bits Alpha Red).</param>
|
||||||
|
/// <returns>The color.</returns>
|
||||||
|
public static Color FromRGBA(uint rgba)
|
||||||
|
{
|
||||||
|
return new Color(((rgba >> 24) & 0xff) / 255.0f, ((rgba >> 16) & 0xff) / 255.0f, ((rgba >> 8) & 0xff) / 255.0f, ((rgba >> 0) & 0xff) / 255.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates <see cref="Color"/> from the Hex string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hex">The hexadecimal color string.</param>
|
||||||
|
/// <returns>The output color value.</returns>
|
||||||
|
public static Color FromHex(string hex)
|
||||||
|
{
|
||||||
|
FromHex(hex, out var color);
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates <see cref="Color"/> from the Hex string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hex">The hexadecimal color string.</param>
|
||||||
|
/// <param name="color">The output color value. Valid if method returns true.</param>
|
||||||
|
/// <returns>True if method was able to convert color, otherwise false.</returns>
|
||||||
|
public static bool FromHex(string hex, out Color color)
|
||||||
|
{
|
||||||
|
int r, g, b, a = 255;
|
||||||
|
bool isValid = true;
|
||||||
|
|
||||||
|
int startIndex = hex.Length != 0 && hex[0] == '#' ? 1 : 0;
|
||||||
|
if (hex.Length == 3 + startIndex)
|
||||||
|
{
|
||||||
|
r = StringUtils.HexDigit(hex[startIndex++]);
|
||||||
|
g = StringUtils.HexDigit(hex[startIndex++]);
|
||||||
|
b = StringUtils.HexDigit(hex[startIndex]);
|
||||||
|
r = (r << 4) + r;
|
||||||
|
g = (g << 4) + g;
|
||||||
|
b = (b << 4) + b;
|
||||||
|
}
|
||||||
|
else if (hex.Length == 6 + startIndex)
|
||||||
|
{
|
||||||
|
r = (StringUtils.HexDigit(hex[startIndex + 0]) << 4) + StringUtils.HexDigit(hex[startIndex + 1]);
|
||||||
|
g = (StringUtils.HexDigit(hex[startIndex + 2]) << 4) + StringUtils.HexDigit(hex[startIndex + 3]);
|
||||||
|
b = (StringUtils.HexDigit(hex[startIndex + 4]) << 4) + StringUtils.HexDigit(hex[startIndex + 5]);
|
||||||
|
}
|
||||||
|
else if (hex.Length == 8 + startIndex)
|
||||||
|
{
|
||||||
|
r = (StringUtils.HexDigit(hex[startIndex + 0]) << 4) + StringUtils.HexDigit(hex[startIndex + 1]);
|
||||||
|
g = (StringUtils.HexDigit(hex[startIndex + 2]) << 4) + StringUtils.HexDigit(hex[startIndex + 3]);
|
||||||
|
b = (StringUtils.HexDigit(hex[startIndex + 4]) << 4) + StringUtils.HexDigit(hex[startIndex + 5]);
|
||||||
|
a = (StringUtils.HexDigit(hex[startIndex + 6]) << 4) + StringUtils.HexDigit(hex[startIndex + 7]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = g = b = 0;
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
color = new Color(r, g, b, a);
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the color value as the hexadecimal string (in RGBA order).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Hex string.</returns>
|
/// <returns>Hex string.</returns>
|
||||||
public string ToHexString()
|
public string ToHexString()
|
||||||
@@ -287,7 +344,7 @@ namespace FlaxEngine
|
|||||||
|
|
||||||
return new string(result);
|
return new string(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates <see cref="Color"/> from the text string (hex or color name).
|
/// Creates <see cref="Color"/> from the text string (hex or color name).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -126,9 +126,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes from packed RGB value of the color and separate alpha channel value.
|
/// Initializes from packed RGB value (bottom bits contain Blue) of the color and separate alpha channel value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rgb">The packed RGB value.</param>
|
/// <param name="rgb">The packed RGB value (bottom bits contain Blue).</param>
|
||||||
/// <param name="a">The alpha channel.</param>
|
/// <param name="a">The alpha channel.</param>
|
||||||
/// <returns>The color.</returns>
|
/// <returns>The color.</returns>
|
||||||
static Color FromRGB(uint32 rgb, float a = 1.0f)
|
static Color FromRGB(uint32 rgb, float a = 1.0f)
|
||||||
@@ -137,22 +137,32 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes from packed RGBA value.
|
/// Initializes from packed ARGB value (bottom bits contain Blue).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rgba">The packed RGBA value.</param>
|
/// <param name="argb">The packed ARGB value (bottom bits contain Blue).</param>
|
||||||
|
/// <returns>The color.</returns>
|
||||||
|
static Color FromARGB(uint32 argb)
|
||||||
|
{
|
||||||
|
return Color((float)((argb >> 16) & 0xff) / 255.0f,(float)((argb >> 8) & 0xff) / 255.0f, (float)((argb >> 0) & 0xff) / 255.0f, (float)((argb >> 24) & 0xff) / 255.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes from packed RGBA value (bottom bits contain Alpha).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rgba">The packed RGBA value (bottom bits contain Alpha).</param>
|
||||||
/// <returns>The color.</returns>
|
/// <returns>The color.</returns>
|
||||||
static Color FromRGBA(uint32 rgba)
|
static Color FromRGBA(uint32 rgba)
|
||||||
{
|
{
|
||||||
return Color(static_cast<float>(rgba >> 16 & 0xff) / 255.0f, static_cast<float>(rgba >> 8 & 0xff) / 255.0f, static_cast<float>(rgba & 0xff) / 255.0f, static_cast<float>(rgba >> 24 & 0xff) / 255.0f);
|
return Color((float)((rgba >> 24) & 0xff) / 255.0f,(float)((rgba >> 16) & 0xff) / 255.0f, (float)((rgba >> 8) & 0xff) / 255.0f, (float)((rgba >> 0) & 0xff) / 255.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Color FromHex(const String& hexString)
|
static Color FromHex(const String& hex)
|
||||||
{
|
{
|
||||||
bool isValid;
|
bool isValid;
|
||||||
return FromHex(hexString, isValid);
|
return FromHex(hex, isValid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Color FromHex(const String& hexString, bool& isValid);
|
static Color FromHex(const String& hex, bool& isValid);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates RGB color from Hue[0-360], Saturation[0-1] and Value[0-1].
|
/// Creates RGB color from Hue[0-360], Saturation[0-1] and Value[0-1].
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ void RenderTask::DrawAll()
|
|||||||
// Sort tasks (by Order property)
|
// Sort tasks (by Order property)
|
||||||
Sorting::QuickSortObj(Tasks.Get(), Tasks.Count());
|
Sorting::QuickSortObj(Tasks.Get(), Tasks.Count());
|
||||||
|
|
||||||
// Render all that shit
|
// Render all tasks
|
||||||
for (auto task : Tasks)
|
for (auto task : Tasks)
|
||||||
{
|
{
|
||||||
if (task->CanDraw())
|
if (task->CanDraw())
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the brush proxies per surface.
|
/// Gets the brush proxies per surface.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_PROPERTY(Attributes="Serialize, EditorOrder(100), EditorDisplay(\"Surfaces\", EditorDisplayAttribute.InlineStyle), Collection(CanReorderItems = false, NotNullItems = true, ReadOnly = true)")
|
API_PROPERTY(Attributes="Serialize, EditorOrder(100), EditorDisplay(\"Surfaces\", EditorDisplayAttribute.InlineStyle), Collection(CanReorderItems = false, NotNullItems = true, CanResize = true)")
|
||||||
Array<BrushSurface> GetSurfaces() const;
|
Array<BrushSurface> GetSurfaces() const;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -349,6 +349,11 @@ void Camera::Draw(RenderContext& renderContext)
|
|||||||
_previewModel->Draw(renderContext, draw);
|
_previewModel->Draw(renderContext, draw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Load preview model if it doesnt exist. Ex: prefabs
|
||||||
|
else if (EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::EditorSprites) && !_previewModel)
|
||||||
|
{
|
||||||
|
_previewModel = Content::LoadAsyncInternal<Model>(TEXT("Editor/Camera/O_Camera"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "Engine/Debug/DebugDraw.h"
|
#include "Engine/Debug/DebugDraw.h"
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the model entries collection. Each entry contains data how to render meshes using this entry (transformation, material, shadows casting, etc.).
|
/// Gets the model entries collection. Each entry contains data how to render meshes using this entry (transformation, material, shadows casting, etc.).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_PROPERTY(Attributes="Serialize, EditorOrder(1000), EditorDisplay(\"Entries\", EditorDisplayAttribute.InlineStyle), Collection(CanReorderItems=false, NotNullItems=true, ReadOnly=true, Spacing=10)")
|
API_PROPERTY(Attributes="Serialize, EditorOrder(1000), EditorDisplay(\"Entries\", EditorDisplayAttribute.InlineStyle), Collection(CanReorderItems=false, NotNullItems=true, CanResize=false, Spacing=10)")
|
||||||
FORCE_INLINE const Array<ModelInstanceEntry>& GetEntries() const
|
FORCE_INLINE const Array<ModelInstanceEntry>& GetEntries() const
|
||||||
{
|
{
|
||||||
return Entries;
|
return Entries;
|
||||||
|
|||||||
@@ -1392,12 +1392,20 @@ void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerCli
|
|||||||
if (ownerClientId == NetworkManager::LocalClientId)
|
if (ownerClientId == NetworkManager::LocalClientId)
|
||||||
{
|
{
|
||||||
// Ensure local client owns that object actually
|
// Ensure local client owns that object actually
|
||||||
CHECK(localRole == NetworkObjectRole::OwnedAuthoritative);
|
if (localRole != NetworkObjectRole::OwnedAuthoritative)
|
||||||
|
{
|
||||||
|
LOG(Error, "Cannot change overship of object (Id={}) to the local client (Id={}) if the local role is not set to OwnedAuthoritative.", obj->GetID(), ownerClientId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Ensure local client doesn't own that object since it's owned by other client
|
// Ensure local client doesn't own that object since it's owned by other client
|
||||||
CHECK(localRole != NetworkObjectRole::OwnedAuthoritative);
|
if (localRole == NetworkObjectRole::OwnedAuthoritative)
|
||||||
|
{
|
||||||
|
LOG(Error, "Cannot change overship of object (Id={}) to the remote client (Id={}) if the local role is set to OwnedAuthoritative.", obj->GetID(), ownerClientId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
item.HasOwnership = true;
|
item.HasOwnership = true;
|
||||||
@@ -1421,7 +1429,13 @@ void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerCli
|
|||||||
if (item.OwnerClientId != ownerClientId)
|
if (item.OwnerClientId != ownerClientId)
|
||||||
{
|
{
|
||||||
// Change role locally
|
// Change role locally
|
||||||
CHECK(localRole != NetworkObjectRole::OwnedAuthoritative);
|
#if !BUILD_RELEASE
|
||||||
|
if (localRole == NetworkObjectRole::OwnedAuthoritative)
|
||||||
|
{
|
||||||
|
LOG(Error, "Cannot change overship of object (Id={}) to the remote client (Id={}) if the local role is set to OwnedAuthoritative.", obj->GetID(), ownerClientId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (Hierarchy && item.Role == NetworkObjectRole::OwnedAuthoritative)
|
if (Hierarchy && item.Role == NetworkObjectRole::OwnedAuthoritative)
|
||||||
Hierarchy->RemoveObject(obj);
|
Hierarchy->RemoveObject(obj);
|
||||||
item.OwnerClientId = ownerClientId;
|
item.OwnerClientId = ownerClientId;
|
||||||
@@ -1433,7 +1447,13 @@ void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerCli
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Allow to change local role of the object (except ownership)
|
// Allow to change local role of the object (except ownership)
|
||||||
CHECK(localRole != NetworkObjectRole::OwnedAuthoritative);
|
#if !BUILD_RELEASE
|
||||||
|
if (localRole == NetworkObjectRole::OwnedAuthoritative)
|
||||||
|
{
|
||||||
|
LOG(Error, "Cannot change overship of object (Id={}) to the remote client (Id={}) if the local role is set to OwnedAuthoritative.", obj->GetID(), ownerClientId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (Hierarchy && it->Item.Role == NetworkObjectRole::OwnedAuthoritative)
|
if (Hierarchy && it->Item.Role == NetworkObjectRole::OwnedAuthoritative)
|
||||||
Hierarchy->RemoveObject(obj);
|
Hierarchy->RemoveObject(obj);
|
||||||
item.Role = localRole;
|
item.Role = localRole;
|
||||||
@@ -2211,7 +2231,6 @@ void NetworkInternal::OnNetworkMessageObjectRpc(NetworkEvent& event, NetworkClie
|
|||||||
if (!obj)
|
if (!obj)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
// Validate RPC
|
// Validate RPC
|
||||||
if (info->Server && NetworkManager::IsClient())
|
if (info->Server && NetworkManager::IsClient())
|
||||||
{
|
{
|
||||||
@@ -2234,7 +2253,7 @@ void NetworkInternal::OnNetworkMessageObjectRpc(NetworkEvent& event, NetworkClie
|
|||||||
// Execute RPC
|
// Execute RPC
|
||||||
info->Execute(obj, stream, info->Tag);
|
info->Execute(obj, stream, info->Tag);
|
||||||
}
|
}
|
||||||
else if(info->Channel != static_cast<uint8>(NetworkChannelType::Unreliable) && info->Channel != static_cast<uint8>(NetworkChannelType::UnreliableOrdered))
|
else if (info->Channel != static_cast<uint8>(NetworkChannelType::Unreliable) && info->Channel != static_cast<uint8>(NetworkChannelType::UnreliableOrdered))
|
||||||
{
|
{
|
||||||
NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Unknown object {} RPC {}::{}", msgData.ObjectId, String(msgData.RpcTypeName), String(msgData.RpcName));
|
NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Unknown object {} RPC {}::{}", msgData.ObjectId, String(msgData.RpcTypeName), String(msgData.RpcName));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ void ParticleEffect::Sync()
|
|||||||
|
|
||||||
SceneRenderTask* ParticleEffect::GetRenderTask() const
|
SceneRenderTask* ParticleEffect::GetRenderTask() const
|
||||||
{
|
{
|
||||||
const uint64 minFrame = Engine::UpdateCount - 2;
|
const uint64 minFrame = Engine::FrameCount - 2;
|
||||||
|
|
||||||
// Custom task
|
// Custom task
|
||||||
const auto customViewRenderTask = CustomViewRenderTask.Get();
|
const auto customViewRenderTask = CustomViewRenderTask.Get();
|
||||||
|
|||||||
@@ -155,9 +155,9 @@ bool FontManager::AddNewEntry(Font* font, Char c, FontCharacterEntry& entry)
|
|||||||
// Get the index to the glyph in the font face
|
// Get the index to the glyph in the font face
|
||||||
const FT_UInt glyphIndex = FT_Get_Char_Index(face, c);
|
const FT_UInt glyphIndex = FT_Get_Char_Index(face, c);
|
||||||
#if !BUILD_RELEASE
|
#if !BUILD_RELEASE
|
||||||
if (glyphIndex == 0)
|
if (glyphIndex == 0 && c >= '!')
|
||||||
{
|
{
|
||||||
LOG(Warning, "Font `{}` doesn't contain character `\\u{:x}`, consider choosing another font. ", String(face->family_name), c);
|
LOG(Warning, "Font `{}` doesn't contain character `\\u{:x}`, consider choosing another font.", String(face->family_name), c);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -339,6 +339,32 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
|
|||||||
}
|
}
|
||||||
setup.UseTemporalAAJitter = aaMode == AntialiasingMode::TemporalAntialiasing;
|
setup.UseTemporalAAJitter = aaMode == AntialiasingMode::TemporalAntialiasing;
|
||||||
|
|
||||||
|
// Disable TAA jitter in debug modes
|
||||||
|
switch (renderContext.View.Mode)
|
||||||
|
{
|
||||||
|
case ViewMode::Unlit:
|
||||||
|
case ViewMode::Diffuse:
|
||||||
|
case ViewMode::Normals:
|
||||||
|
case ViewMode::Depth:
|
||||||
|
case ViewMode::Emissive:
|
||||||
|
case ViewMode::AmbientOcclusion:
|
||||||
|
case ViewMode::Metalness:
|
||||||
|
case ViewMode::Roughness:
|
||||||
|
case ViewMode::Specular:
|
||||||
|
case ViewMode::SpecularColor:
|
||||||
|
case ViewMode::SubsurfaceColor:
|
||||||
|
case ViewMode::ShadingModel:
|
||||||
|
case ViewMode::Reflections:
|
||||||
|
case ViewMode::GlobalSDF:
|
||||||
|
case ViewMode::GlobalSurfaceAtlas:
|
||||||
|
case ViewMode::LightmapUVsDensity:
|
||||||
|
case ViewMode::MaterialComplexity:
|
||||||
|
case ViewMode::Wireframe:
|
||||||
|
case ViewMode::NoPostFx:
|
||||||
|
setup.UseTemporalAAJitter = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Customize setup (by postfx or custom gameplay effects)
|
// Customize setup (by postfx or custom gameplay effects)
|
||||||
renderContext.Task->SetupRender(renderContext);
|
renderContext.Task->SetupRender(renderContext);
|
||||||
for (PostProcessEffect* e : renderContext.List->PostFx)
|
for (PostProcessEffect* e : renderContext.List->PostFx)
|
||||||
@@ -506,8 +532,13 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
|
|||||||
EyeAdaptationPass::Instance()->Render(renderContext, lightBuffer);
|
EyeAdaptationPass::Instance()->Render(renderContext, lightBuffer);
|
||||||
PostProcessingPass::Instance()->Render(renderContext, lightBuffer, tempBuffer, colorGradingLUT);
|
PostProcessingPass::Instance()->Render(renderContext, lightBuffer, tempBuffer, colorGradingLUT);
|
||||||
RenderTargetPool::Release(colorGradingLUT);
|
RenderTargetPool::Release(colorGradingLUT);
|
||||||
RenderTargetPool::Release(lightBuffer);
|
|
||||||
context->ResetRenderTarget();
|
context->ResetRenderTarget();
|
||||||
|
if (aaMode == AntialiasingMode::TemporalAntialiasing)
|
||||||
|
{
|
||||||
|
TAA::Instance()->Render(renderContext, tempBuffer, lightBuffer->View());
|
||||||
|
Swap(lightBuffer, tempBuffer);
|
||||||
|
}
|
||||||
|
RenderTargetPool::Release(lightBuffer);
|
||||||
context->SetRenderTarget(task->GetOutputView());
|
context->SetRenderTarget(task->GetOutputView());
|
||||||
context->SetViewportAndScissors(task->GetOutputViewport());
|
context->SetViewportAndScissors(task->GetOutputViewport());
|
||||||
context->Draw(tempBuffer);
|
context->Draw(tempBuffer);
|
||||||
|
|||||||
@@ -46,6 +46,11 @@ namespace FlaxEngine
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanReorderItems = true;
|
public bool CanReorderItems = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether items can be added or removed from this collection.
|
||||||
|
/// </summary>
|
||||||
|
public bool CanResize = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets whether the items of this collection can be null. If <c>true</c>, applications using this collection should prevent user to add null items to the collection.
|
/// Gets or sets whether the items of this collection can be null. If <c>true</c>, applications using this collection should prevent user to add null items to the collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -23,11 +23,14 @@ namespace FlaxEngine
|
|||||||
public int FontSize;
|
public int FontSize;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The custom header color (as 32-bit uint).
|
/// The custom header color (as 32-bit uint in RGB order, bottom bits contain Blue).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint Color;
|
public uint Color;
|
||||||
|
|
||||||
private HeaderAttribute()
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="HeaderAttribute"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public HeaderAttribute()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace FlaxEngine;
|
namespace FlaxEngine;
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ public class WatermarkAttribute : Attribute
|
|||||||
public string WatermarkText;
|
public string WatermarkText;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The watermark color.
|
/// The watermark color (as 32-bit uint in RGB order, bottom bits contain Blue).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint WatermarkColor;
|
public uint WatermarkColor;
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ public class WatermarkAttribute : Attribute
|
|||||||
public WatermarkAttribute(string text)
|
public WatermarkAttribute(string text)
|
||||||
{
|
{
|
||||||
WatermarkText = text;
|
WatermarkText = text;
|
||||||
WatermarkColor = 0; // default color of watermark in textbox
|
WatermarkColor = 0; // Default color of watermark in textbox
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#if FLAX_TESTS
|
#if FLAX_TESTS
|
||||||
|
using System;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace FlaxEngine.Tests
|
namespace FlaxEngine.Tests
|
||||||
@@ -37,6 +38,15 @@ namespace FlaxEngine.Tests
|
|||||||
Assert.AreEqual(Color.Maroon, ColorHSV.FromColor(Color.Maroon).ToColor());
|
Assert.AreEqual(Color.Maroon, ColorHSV.FromColor(Color.Maroon).ToColor());
|
||||||
Assert.AreEqual(new Color(184, 209, 219, 255).ToRgba(), ColorHSV.FromColor(new Color(184, 209, 219, 255)).ToColor().ToRgba());
|
Assert.AreEqual(new Color(184, 209, 219, 255).ToRgba(), ColorHSV.FromColor(new Color(184, 209, 219, 255)).ToColor().ToRgba());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestHexConversion()
|
||||||
|
{
|
||||||
|
string hex = Color.Blue.AlphaMultiplied(0.5f).ToHexString();
|
||||||
|
Color col1 = Color.FromHex(hex);
|
||||||
|
Color col2 = Color.FromRGBA(0x0000FF7F);
|
||||||
|
Assert.AreEqual((Color32)col1, (Color32)col2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace FlaxEngine.GUI
|
namespace FlaxEngine.GUI
|
||||||
{
|
{
|
||||||
@@ -204,7 +205,9 @@ namespace FlaxEngine.GUI
|
|||||||
{
|
{
|
||||||
_navigationHeldTimeUp = _navigationHeldTimeDown = _navigationHeldTimeLeft = _navigationHeldTimeRight = 0;
|
_navigationHeldTimeUp = _navigationHeldTimeDown = _navigationHeldTimeLeft = _navigationHeldTimeRight = 0;
|
||||||
_navigationRateTimeUp = _navigationRateTimeDown = _navigationRateTimeLeft = _navigationRateTimeRight = 0;
|
_navigationRateTimeUp = _navigationRateTimeDown = _navigationRateTimeLeft = _navigationRateTimeRight = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
if (ContainsFocus || IndexInParent == 0)
|
||||||
{
|
{
|
||||||
UpdateNavigation(deltaTime, _canvas.NavigateUp.Name, NavDirection.Up, ref _navigationHeldTimeUp, ref _navigationRateTimeUp);
|
UpdateNavigation(deltaTime, _canvas.NavigateUp.Name, NavDirection.Up, ref _navigationHeldTimeUp, ref _navigationRateTimeUp);
|
||||||
UpdateNavigation(deltaTime, _canvas.NavigateDown.Name, NavDirection.Down, ref _navigationHeldTimeDown, ref _navigationRateTimeDown);
|
UpdateNavigation(deltaTime, _canvas.NavigateDown.Name, NavDirection.Down, ref _navigationHeldTimeDown, ref _navigationRateTimeDown);
|
||||||
@@ -216,13 +219,30 @@ namespace FlaxEngine.GUI
|
|||||||
base.Update(deltaTime);
|
base.Update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ConditionalNavigate(NavDirection direction)
|
||||||
|
{
|
||||||
|
// Only currently focused canvas updates its navigation
|
||||||
|
if (!ContainsFocus)
|
||||||
|
{
|
||||||
|
// Special case when no canvas nor game UI is focused so let the first canvas to start the navigation into the UI
|
||||||
|
if (IndexInParent == 0 && Parent is CanvasContainer canvasContainer && !canvasContainer.ContainsFocus && GameRoot.ContainsFocus)
|
||||||
|
{
|
||||||
|
// Nothing is focused so go to the first control
|
||||||
|
var focused = OnNavigate(direction, Float2.Zero, this, new List<Control>());
|
||||||
|
focused?.NavigationFocus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Navigate(direction);
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateNavigation(float deltaTime, string actionName, NavDirection direction, ref float heldTime, ref float rateTime)
|
private void UpdateNavigation(float deltaTime, string actionName, NavDirection direction, ref float heldTime, ref float rateTime)
|
||||||
{
|
{
|
||||||
if (Input.GetAction(actionName))
|
if (Input.GetAction(actionName))
|
||||||
{
|
{
|
||||||
if (heldTime <= Mathf.Epsilon)
|
if (heldTime <= Mathf.Epsilon)
|
||||||
{
|
{
|
||||||
Navigate(direction);
|
ConditionalNavigate(direction);
|
||||||
}
|
}
|
||||||
if (heldTime > _canvas.NavigationInputRepeatDelay)
|
if (heldTime > _canvas.NavigationInputRepeatDelay)
|
||||||
{
|
{
|
||||||
@@ -230,7 +250,7 @@ namespace FlaxEngine.GUI
|
|||||||
}
|
}
|
||||||
if (rateTime > _canvas.NavigationInputRepeatRate)
|
if (rateTime > _canvas.NavigationInputRepeatRate)
|
||||||
{
|
{
|
||||||
Navigate(direction);
|
ConditionalNavigate(direction);
|
||||||
rateTime = 0;
|
rateTime = 0;
|
||||||
}
|
}
|
||||||
heldTime += deltaTime;
|
heldTime += deltaTime;
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ namespace FlaxEngine.GUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the custom material used to render the text. It must has domain set to GUI and have a public texture parameter named Font used to sample font atlas texture with font characters data.
|
/// Gets or sets the custom material used to render the text. It has to have domain set to GUI and have a public texture parameter named Font used to sample font atlas texture with font characters data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[EditorDisplay("Text Style"), EditorOrder(2025)]
|
[EditorDisplay("Text Style"), EditorOrder(2025)]
|
||||||
public MaterialBase Material { get; set; }
|
public MaterialBase Material { get; set; }
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ namespace FlaxEngine.GUI
|
|||||||
textBlock.Range = new TextRange
|
textBlock.Range = new TextRange
|
||||||
{
|
{
|
||||||
StartIndex = start + line.FirstCharIndex,
|
StartIndex = start + line.FirstCharIndex,
|
||||||
EndIndex = start + line.LastCharIndex,
|
EndIndex = start + line.LastCharIndex + 1,
|
||||||
};
|
};
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1590,14 +1590,18 @@ namespace Flax.Build.Plugins
|
|||||||
context.Failed = true;
|
context.Failed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method.IsVirtual)
|
if (method.IsVirtual)
|
||||||
{
|
{
|
||||||
MonoCecil.CompilationError($"Not supported virtual RPC method '{method.FullName}'.", method);
|
MonoCecil.CompilationError($"Not supported virtual RPC method '{method.FullName}'.", method);
|
||||||
context.Failed = true;
|
context.Failed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (method.CustomAttributes.FirstOrDefault(x => x.AttributeType.FullName == "System.Runtime.CompilerServices.AsyncStateMachineAttribute") != null)
|
||||||
|
{
|
||||||
|
MonoCecil.CompilationError($"Not supported async RPC method '{method.FullName}'.", method);
|
||||||
|
context.Failed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
ModuleDefinition module = type.Module;
|
ModuleDefinition module = type.Module;
|
||||||
var voidType = module.TypeSystem.Void;
|
var voidType = module.TypeSystem.Void;
|
||||||
if (method.ReturnType != voidType)
|
if (method.ReturnType != voidType)
|
||||||
@@ -1606,7 +1610,6 @@ namespace Flax.Build.Plugins
|
|||||||
context.Failed = true;
|
context.Failed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (method.IsStatic)
|
if (method.IsStatic)
|
||||||
{
|
{
|
||||||
MonoCecil.CompilationError($"Not supported static RPC method '{method.FullName}'.", method);
|
MonoCecil.CompilationError($"Not supported static RPC method '{method.FullName}'.", method);
|
||||||
@@ -1634,7 +1637,6 @@ namespace Flax.Build.Plugins
|
|||||||
context.Failed = true;
|
context.Failed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!methodRPC.IsServer && !methodRPC.IsClient)
|
if (!methodRPC.IsServer && !methodRPC.IsClient)
|
||||||
{
|
{
|
||||||
MonoCecil.CompilationError($"Network RPC {method.Name} in {type.FullName} needs to have Server or Client specifier.", method);
|
MonoCecil.CompilationError($"Network RPC {method.Name} in {type.FullName} needs to have Server or Client specifier.", method);
|
||||||
|
|||||||
Reference in New Issue
Block a user