Merge branch 'PE-1.4' of https://github.com/plemsoft/FlaxEngine into plemsoft-PE-1.4
This commit is contained in:
@@ -54,7 +54,12 @@ namespace FlaxEditor.Gizmo
|
||||
if (!_isActive || !IsActive)
|
||||
return;
|
||||
|
||||
Matrix m1, m2, m3;
|
||||
//PE: As all axisMesh have the same pivot, add a little offset to the x axisMesh,
|
||||
//PE: This way SortDrawCalls is able to sort the draw order.
|
||||
//PE: https://github.com/FlaxEngine/FlaxEngine/issues/680
|
||||
//PE: @Artist To fix the rotate, add new "wider" circleMesh, so direction is visible.
|
||||
|
||||
Matrix m1, m2, m3 , mx1;
|
||||
bool isXAxis = _activeAxis == Axis.X || _activeAxis == Axis.XY || _activeAxis == Axis.ZX;
|
||||
bool isYAxis = _activeAxis == Axis.Y || _activeAxis == Axis.XY || _activeAxis == Axis.YZ;
|
||||
bool isZAxis = _activeAxis == Axis.Z || _activeAxis == Axis.YZ || _activeAxis == Axis.ZX;
|
||||
@@ -70,6 +75,8 @@ namespace FlaxEditor.Gizmo
|
||||
break;
|
||||
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3);
|
||||
Matrix.Multiply(ref m3, ref world, out m1);
|
||||
mx1 = m1;
|
||||
mx1.M41 += 0.05f;
|
||||
var axisMesh = _modelTranslateAxis.LODs[0].Meshes[0];
|
||||
var boxMesh = _modelBox.LODs[0].Meshes[0];
|
||||
var boxSize = 10.0f;
|
||||
@@ -90,7 +97,7 @@ namespace FlaxEditor.Gizmo
|
||||
boxMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialWireFocus : _materialWire, ref m3);
|
||||
|
||||
// X axis
|
||||
axisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m1);
|
||||
axisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref mx1);
|
||||
|
||||
// Y axis
|
||||
Matrix.RotationZ(Mathf.PiOverTwo, out m2);
|
||||
@@ -143,12 +150,15 @@ namespace FlaxEditor.Gizmo
|
||||
break;
|
||||
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m3);
|
||||
Matrix.Multiply(ref m3, ref world, out m1);
|
||||
mx1 = m1;
|
||||
mx1.M41 -= 0.05f;
|
||||
|
||||
var axisMesh = _modelScaleAxis.LODs[0].Meshes[0];
|
||||
var boxMesh = _modelBox.LODs[0].Meshes[0];
|
||||
|
||||
// X axis
|
||||
Matrix.RotationY(-Mathf.PiOverTwo, out m2);
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
Matrix.Multiply(ref m2, ref mx1, out m3);
|
||||
axisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
|
||||
|
||||
// Y axis
|
||||
|
||||
@@ -289,10 +289,29 @@ namespace FlaxEditor.Gizmo
|
||||
{
|
||||
float snapValue = isScaling ? ScaleSnapValue : TranslationSnapValue;
|
||||
_translationScaleSnapDelta += delta;
|
||||
delta = new Vector3(
|
||||
(int)(_translationScaleSnapDelta.X / snapValue) * snapValue,
|
||||
(int)(_translationScaleSnapDelta.Y / snapValue) * snapValue,
|
||||
(int)(_translationScaleSnapDelta.Z / snapValue) * snapValue);
|
||||
if (!isScaling && snapValue < 0.0f)
|
||||
{
|
||||
//PE: Snap to object bounding box
|
||||
GetSelectedObjectsBounds(out var b, out _);
|
||||
float X, Y, Z;
|
||||
if (b.Minimum.X < 0.0f) X = (float) Math.Abs(b.Minimum.X) + b.Maximum.X;
|
||||
else X = (float) b.Minimum.X - b.Maximum.X;
|
||||
if (b.Minimum.Y < 0.0f) Y = (float) Math.Abs(b.Minimum.Y) + b.Maximum.Y;
|
||||
else Y = (float) b.Minimum.Y - b.Maximum.Y;
|
||||
if (b.Minimum.Z < 0.0f) Z = (float) Math.Abs(b.Minimum.Z) + b.Maximum.Z;
|
||||
else Z = (float) b.Minimum.Z - b.Maximum.Z;
|
||||
delta = new Vector3(
|
||||
(int)(_translationScaleSnapDelta.X / X) * X,
|
||||
(int)(_translationScaleSnapDelta.Y / Y) * Y,
|
||||
(int)(_translationScaleSnapDelta.Z / Z) * Z);
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = new Vector3(
|
||||
(int)(_translationScaleSnapDelta.X / snapValue) * snapValue,
|
||||
(int)(_translationScaleSnapDelta.Y / snapValue) * snapValue,
|
||||
(int)(_translationScaleSnapDelta.Z / snapValue) * snapValue);
|
||||
}
|
||||
_translationScaleSnapDelta -= delta;
|
||||
}
|
||||
|
||||
@@ -446,7 +465,7 @@ namespace FlaxEditor.Gizmo
|
||||
}
|
||||
|
||||
// Apply transformation (but to the parents, not whole selection pool)
|
||||
if (anyValid)
|
||||
if (anyValid || (!_isTransforming && Owner.UseDuplicate) )
|
||||
{
|
||||
StartTransforming();
|
||||
|
||||
|
||||
@@ -68,6 +68,10 @@ namespace FlaxEditor.Options
|
||||
[EditorDisplay("Common"), EditorOrder(220)]
|
||||
public InputBinding ContentFinder = new InputBinding(KeyboardKeys.O, KeyboardKeys.Control);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "R")]
|
||||
[EditorDisplay("Common"), EditorOrder(230)]
|
||||
public InputBinding RotateSelection = new InputBinding(KeyboardKeys.R);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Scene
|
||||
|
||||
@@ -326,6 +326,10 @@ namespace FlaxEditor.Viewport
|
||||
var button = translateSnappingCM.AddButton(v.ToString());
|
||||
button.Tag = v;
|
||||
}
|
||||
var buttonBB = translateSnappingCM.AddButton("Bounding Box");
|
||||
buttonBB.Tag = -1.0f;
|
||||
|
||||
|
||||
translateSnappingCM.ButtonClicked += OnWidgetTranslateSnapClick;
|
||||
translateSnappingCM.VisibleChanged += OnWidgetTranslateSnapShowHide;
|
||||
_translateSnapping.Parent = translateSnappingWidget;
|
||||
@@ -378,6 +382,7 @@ namespace FlaxEditor.Viewport
|
||||
InputActions.Add(options => options.RotateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Rotate);
|
||||
InputActions.Add(options => options.ScaleMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Scale);
|
||||
InputActions.Add(options => options.FocusSelection, FocusSelection);
|
||||
InputActions.Add(options => options.RotateSelection, RotateSelection);
|
||||
InputActions.Add(options => options.Delete, _editor.SceneEditing.Delete);
|
||||
}
|
||||
|
||||
@@ -667,7 +672,10 @@ namespace FlaxEditor.Viewport
|
||||
{
|
||||
var v = (float)button.Tag;
|
||||
TransformGizmo.TranslationSnapValue = v;
|
||||
_translateSnapping.Text = v.ToString();
|
||||
if (v < 0.0f)
|
||||
_translateSnapping.Text = "Bounding Box";
|
||||
else
|
||||
_translateSnapping.Text = v.ToString();
|
||||
// cache value
|
||||
_editor.ProjectCache.SetCustomData("TranslateSnapValue", TransformGizmo.TranslationSnapValue.ToString("N"));
|
||||
}
|
||||
@@ -696,6 +704,49 @@ namespace FlaxEditor.Viewport
|
||||
Gizmos.ForEach(x => x.OnSelectionChanged(selection));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Press "R" to rotate the selected gizmo objects 45 degrees.
|
||||
/// </summary>
|
||||
public void RotateSelection()
|
||||
{
|
||||
var win = (WindowRootControl)Root;
|
||||
var selection = _editor.SceneEditing.Selection;
|
||||
var IsShiftDown = win.GetKey(KeyboardKeys.Shift);
|
||||
|
||||
Quaternion rotationDelta;
|
||||
if(IsShiftDown)
|
||||
rotationDelta = Quaternion.Euler(0.0f, -45.0f, 0.0f);
|
||||
else
|
||||
rotationDelta = Quaternion.Euler(0.0f, 45.0f, 0.0f);
|
||||
|
||||
bool useObjCenter = TransformGizmo.ActivePivot == TransformGizmoBase.PivotType.ObjectCenter;
|
||||
Vector3 gizmoPosition = TransformGizmo.Position;
|
||||
|
||||
//PE: Rotate selected objects.
|
||||
bool isPlayMode = Editor.Instance.StateMachine.IsPlayMode;
|
||||
for (int i = 0; i < selection.Count; i++)
|
||||
{
|
||||
var obj = selection[i];
|
||||
if (isPlayMode && obj.CanTransform == false)
|
||||
continue;
|
||||
var trans = obj.Transform;
|
||||
Vector3 pivotOffset = trans.Translation - gizmoPosition;
|
||||
if (useObjCenter || pivotOffset.IsZero)
|
||||
{
|
||||
trans.Orientation *= Quaternion.Invert(trans.Orientation) * rotationDelta * trans.Orientation;
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix.RotationQuaternion(ref trans.Orientation, out var transWorld);
|
||||
Matrix.RotationQuaternion(ref rotationDelta, out var deltaWorld);
|
||||
Matrix world = transWorld * Matrix.Translation(pivotOffset) * deltaWorld * Matrix.Translation(-pivotOffset);
|
||||
trans.SetRotation(ref world);
|
||||
trans.Translation += world.TranslationVector;
|
||||
}
|
||||
obj.Transform = trans;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Focuses the viewport on the current selection of the gizmo.
|
||||
/// </summary>
|
||||
|
||||
@@ -130,6 +130,10 @@ void AudioSource::Play()
|
||||
{
|
||||
// Request faster streaming update
|
||||
Clip->RequestStreamingUpdate();
|
||||
|
||||
// PE: If we are looping and streaming also update streaming buffers.
|
||||
if(_loop)
|
||||
RequestStreamingBuffersUpdate();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -379,8 +379,27 @@ void AssetsCache::RegisterAssets(FlaxStorage* storage)
|
||||
// Check if storage contains ID which has been already registered
|
||||
if (FindAsset(e.ID, info))
|
||||
{
|
||||
#if PLATFORM_WINDOWS
|
||||
//PE: Windows - if you start your project using a shortcut/VS commandline -project , and using a upper/lower drive letter, it could ruin your scene.
|
||||
//PE: On windows case do not matter so...
|
||||
if (storagePath.ToLower() != info.Path.ToLower())
|
||||
{
|
||||
LOG(Warning, "Founded duplicated asset \'{0}\'. Locations: \'{1}\' and \'{2}\'", e.ID, storagePath, info.Path);
|
||||
duplicatedEntries.Add(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
//PE: Remove from _registry so we can add it again later with the original ID, so we dont loose relations.
|
||||
for (auto i = _registry.Begin(); i.IsNotEnd(); ++i)
|
||||
{
|
||||
if (i->Value.Info.Path.ToLower() == storagePath.ToLower())
|
||||
_registry.Remove(i);
|
||||
}
|
||||
}
|
||||
#else
|
||||
LOG(Warning, "Founded duplicated asset \'{0}\'. Locations: \'{1}\' and \'{2}\'", e.ID, storagePath, info.Path);
|
||||
duplicatedEntries.Add(i);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -215,7 +215,8 @@ bool String::IsANSI() const
|
||||
bool result = true;
|
||||
for (int32 i = 0; i < _length; i++)
|
||||
{
|
||||
if (_data[i] > 255)
|
||||
//PE: Ansi is max 7 bit so...
|
||||
if (_data[i] > 127)
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
|
||||
@@ -868,6 +868,23 @@ ScriptingObject* Scripting::TryFindObject(Guid id, MClass* type)
|
||||
return result;
|
||||
}
|
||||
|
||||
ScriptingObject* Scripting::TryFindObject(MClass* mclass)
|
||||
{
|
||||
if (mclass == nullptr)
|
||||
return nullptr;
|
||||
|
||||
ScopeLock lock(_objectsLocker);
|
||||
|
||||
for (auto i = _objectsDictionary.Begin(); i.IsNotEnd(); ++i)
|
||||
{
|
||||
const auto obj = i->Value;
|
||||
if(obj->GetClass() == mclass)
|
||||
return obj;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
ScriptingObject* Scripting::FindObject(const MObject* managedInstance)
|
||||
{
|
||||
if (managedInstance == nullptr)
|
||||
|
||||
@@ -144,6 +144,14 @@ public:
|
||||
/// <returns>The found object or null if missing.</returns>
|
||||
static ScriptingObject* FindObject(Guid id, MClass* type = nullptr);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tries to find the object by the given class.
|
||||
/// </summary>
|
||||
/// <returns>The found object or null if missing.</returns>
|
||||
static ScriptingObject* TryFindObject(MClass* type = nullptr);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tries to find the object by the given identifier.
|
||||
/// </summary>
|
||||
|
||||
@@ -641,6 +641,7 @@ bool ModelTool::ImportDataAssimp(const char* path, ImportedModelData& data, Opti
|
||||
aiProcess_JoinIdenticalVertices |
|
||||
aiProcess_LimitBoneWeights |
|
||||
aiProcess_Triangulate |
|
||||
aiProcess_SortByPType | //PE: Added aiProcess_SortByPType so we can ignore meshes with non triangle faces.
|
||||
aiProcess_GenUVCoords |
|
||||
aiProcess_FindDegenerates |
|
||||
aiProcess_FindInvalidData |
|
||||
|
||||
@@ -1552,10 +1552,14 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
|
||||
|
||||
int32 ModelTool::DetectLodIndex(const String& nodeName)
|
||||
{
|
||||
const int32 index = nodeName.FindLast(TEXT("LOD"));
|
||||
int32 index = nodeName.FindLast(TEXT("LOD"));
|
||||
if (index != -1)
|
||||
{
|
||||
int32 num;
|
||||
//PE: Many models use LOD_0... to indentify LOD levels.
|
||||
if (nodeName.Length() > 4 && nodeName[3] == '_')
|
||||
index++;
|
||||
|
||||
if (!StringUtils::Parse(nodeName.Get() + index + 3, &num))
|
||||
{
|
||||
if (num >= 0 && num < MODEL_MAX_LODS)
|
||||
|
||||
Reference in New Issue
Block a user