diff --git a/Source/Editor/Surface/VisjectSurface.Formatting.cs b/Source/Editor/Surface/VisjectSurface.Formatting.cs index 39ac58242..e1b9a6777 100644 --- a/Source/Editor/Surface/VisjectSurface.Formatting.cs +++ b/Source/Editor/Surface/VisjectSurface.Formatting.cs @@ -176,10 +176,10 @@ namespace FlaxEditor.Surface if (connectedNodes.Count == 0) return; - for (int i = 0; i < connectedNodes.Count - 1; i++) + for (int i = 0; i < connectedNodes.Count; i++) { SurfaceNode nodeA = connectedNodes[i]; - List connectedOutputBoxes = nodeA.GetBoxes().Where(b => b.IsOutput && b.HasAnyConnection).ToList(); + List connectedOutputBoxes = nodeA.GetBoxes().Where(b => b.HasAnyConnection).ToList(); for (int j = 0; j < connectedOutputBoxes.Count; j++) { diff --git a/Source/Engine/Content/Assets/Texture.cpp b/Source/Engine/Content/Assets/Texture.cpp index e31b40a25..4e3aec94d 100644 --- a/Source/Engine/Content/Assets/Texture.cpp +++ b/Source/Engine/Content/Assets/Texture.cpp @@ -36,7 +36,7 @@ bool Texture::Save(const StringView& path) bool Texture::Save(const StringView& path, const InitData* customData) { - if (OnCheckSave()) + if (OnCheckSave(path)) return true; ScopeLock lock(Locker); diff --git a/Source/Engine/Physics/Actors/RigidBody.cpp b/Source/Engine/Physics/Actors/RigidBody.cpp index 565bd9fbd..e8fe0b6aa 100644 --- a/Source/Engine/Physics/Actors/RigidBody.cpp +++ b/Source/Engine/Physics/Actors/RigidBody.cpp @@ -159,9 +159,10 @@ void RigidBody::SetCenterOfMassOffset(const Float3& value) { if (value == _centerOfMassOffset) return; + Float3 delta = value - _centerOfMassOffset; _centerOfMassOffset = value; if (_actor) - PhysicsBackend::SetRigidDynamicActorCenterOfMassOffset(_actor, _centerOfMassOffset); + PhysicsBackend::AddRigidDynamicActorCenterOfMassOffset(_actor, delta); } void RigidBody::SetConstraints(const RigidbodyConstraints value) @@ -338,6 +339,32 @@ void RigidBody::AddMovement(const Vector3& translation, const Quaternion& rotati SetTransform(t); } +#if USE_EDITOR + +#include "Engine/Debug/DebugDraw.h" + +void RigidBody::OnDebugDrawSelected() +{ + // Draw center of mass + if (!_centerOfMassOffset.IsZero()) + { + DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(GetPosition() + (GetOrientation() * (GetCenterOfMass() - GetCenterOfMassOffset())), 5.0f), Color::Red, 0, false); + } + DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(GetPosition() + (GetOrientation() * GetCenterOfMass()), 2.5f), Color::Aqua, 0, false); + + // Draw all attached colliders + for (Actor* child : Children) + { + const auto collider = Cast(child); + if (collider && collider->GetAttachedRigidBody() == this) + collider->OnDebugDrawSelf(); + } + + Actor::OnDebugDrawSelected(); +} + +#endif + void RigidBody::OnCollisionEnter(const Collision& c) { CollisionEnter(c); @@ -514,7 +541,7 @@ void RigidBody::BeginPlay(SceneBeginData* data) // Apply the Center Of Mass offset if (!_centerOfMassOffset.IsZero()) - PhysicsBackend::SetRigidDynamicActorCenterOfMassOffset(_actor, _centerOfMassOffset); + PhysicsBackend::AddRigidDynamicActorCenterOfMassOffset(_actor, _centerOfMassOffset); // Register actor PhysicsBackend::AddSceneActor(scene, _actor); diff --git a/Source/Engine/Physics/Actors/RigidBody.h b/Source/Engine/Physics/Actors/RigidBody.h index f9f36edf9..82599ebb8 100644 --- a/Source/Engine/Physics/Actors/RigidBody.h +++ b/Source/Engine/Physics/Actors/RigidBody.h @@ -487,6 +487,9 @@ public: void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void AddMovement(const Vector3& translation, const Quaternion& rotation) override; +#if USE_EDITOR + void OnDebugDrawSelected() override; +#endif // [IPhysicsActor] void* GetPhysicsActor() const override; diff --git a/Source/Engine/Physics/Colliders/BoxCollider.cpp b/Source/Engine/Physics/Colliders/BoxCollider.cpp index 160120f87..1e90cb91f 100644 --- a/Source/Engine/Physics/Colliders/BoxCollider.cpp +++ b/Source/Engine/Physics/Colliders/BoxCollider.cpp @@ -86,7 +86,7 @@ void BoxCollider::OnDebugDraw() namespace { - OrientedBoundingBox GetWriteBox(const Vector3& min, const Vector3& max, const float margin) + OrientedBoundingBox GetWireBox(const Vector3& min, const Vector3& max, const float margin) { OrientedBoundingBox box; const Vector3 vec = max - min; @@ -111,11 +111,40 @@ namespace } } -void BoxCollider::OnDebugDrawSelected() +void BoxCollider::OnDebugDrawSelf() { const Color color = Color::GreenYellow; DEBUG_DRAW_WIRE_BOX(_bounds, color * 0.3f, 0, false); + Vector3 corners[8]; + _bounds.GetCorners(corners); + const float margin = Math::Min(1.0f, (float)_bounds.GetSize().MinValue() * 0.01f); + const Color wiresColor = color.AlphaMultiplied(0.6f); + if (margin > 0.05f) + { + DEBUG_DRAW_BOX(GetWireBox(corners[0], corners[1], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[0], corners[3], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[0], corners[4], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[1], corners[2], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[1], corners[5], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[2], corners[3], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[2], corners[6], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[3], corners[7], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[4], corners[5], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[4], corners[7], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[5], corners[6], margin), wiresColor, 0, true); + DEBUG_DRAW_BOX(GetWireBox(corners[6], corners[7], margin), wiresColor, 0, true); + } + else + { + DEBUG_DRAW_WIRE_BOX(_bounds, wiresColor, 0, true); + } +} + +void BoxCollider::OnDebugDrawSelected() +{ + OnDebugDrawSelf(); + if (_contactOffset > 0) { OrientedBoundingBox contactBounds = _bounds; @@ -123,24 +152,6 @@ void BoxCollider::OnDebugDrawSelected() DEBUG_DRAW_WIRE_BOX(contactBounds, Color::Blue.AlphaMultiplied(0.2f), 0, false); } - Vector3 corners[8]; - _bounds.GetCorners(corners); - const float margin = 1.0f; - const Color wiresColor = color.AlphaMultiplied(0.6f); - DEBUG_DRAW_BOX(GetWriteBox(corners[0], corners[1], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[0], corners[3], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[0], corners[4], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[1], corners[2], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[1], corners[5], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[2], corners[3], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[2], corners[6], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[3], corners[7], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[4], corners[5], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[4], corners[7], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[5], corners[6], margin), wiresColor, 0, true); - DEBUG_DRAW_BOX(GetWriteBox(corners[6], corners[7], margin), wiresColor, 0, true); - - // Base Collider::OnDebugDrawSelected(); } diff --git a/Source/Engine/Physics/Colliders/BoxCollider.h b/Source/Engine/Physics/Colliders/BoxCollider.h index c0eeaea5c..7dbbc830d 100644 --- a/Source/Engine/Physics/Colliders/BoxCollider.h +++ b/Source/Engine/Physics/Colliders/BoxCollider.h @@ -52,6 +52,7 @@ public: // [Collider] #if USE_EDITOR void OnDebugDraw() override; + void OnDebugDrawSelf() override; void OnDebugDrawSelected() override; #endif bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override; diff --git a/Source/Engine/Physics/Colliders/CapsuleCollider.cpp b/Source/Engine/Physics/Colliders/CapsuleCollider.cpp index 8a9e1d1cf..83ce85115 100644 --- a/Source/Engine/Physics/Colliders/CapsuleCollider.cpp +++ b/Source/Engine/Physics/Colliders/CapsuleCollider.cpp @@ -52,6 +52,17 @@ void CapsuleCollider::DrawPhysicsDebug(RenderView& view) DEBUG_DRAW_WIRE_CAPSULE(_transform.LocalToWorld(_center), rotation, radius, height, Color::GreenYellow * 0.8f, 0, true); } +void CapsuleCollider::OnDebugDrawSelf() +{ + Quaternion rotation; + Quaternion::Multiply(_transform.Orientation, Quaternion::Euler(0, 90, 0), rotation); + const float minSize = 0.001f; + const float radius = Math::Max(Math::Abs(_radius) * _cachedScale, minSize); + const float height = Math::Max(Math::Abs(_height) * _cachedScale, minSize); + const Vector3 position = _transform.LocalToWorld(_center); + DEBUG_DRAW_WIRE_CAPSULE(position, rotation, radius, height, Color::GreenYellow, 0, false); +} + void CapsuleCollider::OnDebugDrawSelected() { Quaternion rotation; diff --git a/Source/Engine/Physics/Colliders/CapsuleCollider.h b/Source/Engine/Physics/Colliders/CapsuleCollider.h index 234916f87..784d346eb 100644 --- a/Source/Engine/Physics/Colliders/CapsuleCollider.h +++ b/Source/Engine/Physics/Colliders/CapsuleCollider.h @@ -56,6 +56,7 @@ public: public: // [Collider] #if USE_EDITOR + void OnDebugDrawSelf() override; void OnDebugDrawSelected() override; #endif bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override; diff --git a/Source/Engine/Physics/Colliders/Collider.h b/Source/Engine/Physics/Colliders/Collider.h index edc73b8a3..d05646072 100644 --- a/Source/Engine/Physics/Colliders/Collider.h +++ b/Source/Engine/Physics/Colliders/Collider.h @@ -158,6 +158,12 @@ protected: /// void RemoveStaticActor(); +private: + friend RigidBody; +#if USE_EDITOR + virtual void OnDebugDrawSelf() {} +#endif + public: // [PhysicsColliderActor] RigidBody* GetAttachedRigidBody() const override; diff --git a/Source/Engine/Physics/Colliders/MeshCollider.cpp b/Source/Engine/Physics/Colliders/MeshCollider.cpp index e4e6948e3..91731e7de 100644 --- a/Source/Engine/Physics/Colliders/MeshCollider.cpp +++ b/Source/Engine/Physics/Colliders/MeshCollider.cpp @@ -85,13 +85,18 @@ void MeshCollider::DrawPhysicsDebug(RenderView& view) } } -void MeshCollider::OnDebugDrawSelected() +void MeshCollider::OnDebugDrawSelf() { if (CollisionData && CollisionData->IsLoaded()) { const auto& debugLines = CollisionData->GetDebugLines(); DEBUG_DRAW_LINES(Span(debugLines.Get(), debugLines.Count()), _transform.GetWorld(), Color::GreenYellow, 0, false); } +} + +void MeshCollider::OnDebugDrawSelected() +{ + OnDebugDrawSelf(); // Base Collider::OnDebugDrawSelected(); diff --git a/Source/Engine/Physics/Colliders/MeshCollider.h b/Source/Engine/Physics/Colliders/MeshCollider.h index 44314adff..2e1ce533a 100644 --- a/Source/Engine/Physics/Colliders/MeshCollider.h +++ b/Source/Engine/Physics/Colliders/MeshCollider.h @@ -31,6 +31,7 @@ public: bool CanAttach(RigidBody* rigidBody) const override; bool CanBeTrigger() const override; #if USE_EDITOR + void OnDebugDrawSelf() override; void OnDebugDrawSelected() override; #endif bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override; diff --git a/Source/Engine/Physics/Colliders/SphereCollider.cpp b/Source/Engine/Physics/Colliders/SphereCollider.cpp index f40d9e4af..0576ae6cf 100644 --- a/Source/Engine/Physics/Colliders/SphereCollider.cpp +++ b/Source/Engine/Physics/Colliders/SphereCollider.cpp @@ -35,9 +35,14 @@ void SphereCollider::DrawPhysicsDebug(RenderView& view) DEBUG_DRAW_WIRE_SPHERE(_sphere, Color::GreenYellow * 0.8f, 0, true); } -void SphereCollider::OnDebugDrawSelected() +void SphereCollider::OnDebugDrawSelf() { DEBUG_DRAW_WIRE_SPHERE(_sphere, Color::GreenYellow, 0, false); +} + +void SphereCollider::OnDebugDrawSelected() +{ + OnDebugDrawSelf(); if (_contactOffset > 0) { diff --git a/Source/Engine/Physics/Colliders/SphereCollider.h b/Source/Engine/Physics/Colliders/SphereCollider.h index 67addf17b..47459cf34 100644 --- a/Source/Engine/Physics/Colliders/SphereCollider.h +++ b/Source/Engine/Physics/Colliders/SphereCollider.h @@ -36,6 +36,7 @@ public: public: // [Collider] #if USE_EDITOR + void OnDebugDrawSelf() override; void OnDebugDrawSelected() override; #endif bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override; diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp index 5805301ff..8d61e9ba5 100644 --- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp +++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp @@ -2518,7 +2518,7 @@ Vector3 PhysicsBackend::GetRigidDynamicActorCenterOfMass(void* actor) return P2C(actorPhysX->getCMassLocalPose().p); } -void PhysicsBackend::SetRigidDynamicActorCenterOfMassOffset(void* actor, const Float3& value) +void PhysicsBackend::AddRigidDynamicActorCenterOfMassOffset(void* actor, const Float3& value) { auto actorPhysX = (PxRigidDynamic*)actor; auto pose = actorPhysX->getCMassLocalPose(); diff --git a/Source/Engine/Physics/PhysicsBackend.h b/Source/Engine/Physics/PhysicsBackend.h index dacd6c7fd..4307d2c6d 100644 --- a/Source/Engine/Physics/PhysicsBackend.h +++ b/Source/Engine/Physics/PhysicsBackend.h @@ -164,7 +164,7 @@ public: static Vector3 GetRigidDynamicActorAngularVelocity(void* actor); static void SetRigidDynamicActorAngularVelocity(void* actor, const Vector3& value, bool wakeUp); static Vector3 GetRigidDynamicActorCenterOfMass(void* actor); - static void SetRigidDynamicActorCenterOfMassOffset(void* actor, const Float3& value); + static void AddRigidDynamicActorCenterOfMassOffset(void* actor, const Float3& value); static bool GetRigidDynamicActorIsSleeping(void* actor); static void RigidDynamicActorSleep(void* actor); static void RigidDynamicActorWakeUp(void* actor); diff --git a/Source/Engine/Render2D/Font.cpp b/Source/Engine/Render2D/Font.cpp index cf478abda..63c59ff70 100644 --- a/Source/Engine/Render2D/Font.cpp +++ b/Source/Engine/Render2D/Font.cpp @@ -388,7 +388,10 @@ int32 Font::HitTestText(const StringView& text, const Float2& location, const Te if (dst < smallestDst) { // Pointer is behind the last character in the line - smallestIndex = line.LastCharIndex + 1; + if (text[line.LastCharIndex] == '\n' && lineIndex != lines.Count() - 1) + smallestIndex = line.LastCharIndex; + else + smallestIndex = line.LastCharIndex + 1; // Fix for last line //if (lineIndex == lines.Count() - 1) diff --git a/Source/ThirdParty/rapidjson/prettywriter.h b/Source/ThirdParty/rapidjson/prettywriter.h index fe45df1d1..c66b6d734 100644 --- a/Source/ThirdParty/rapidjson/prettywriter.h +++ b/Source/ThirdParty/rapidjson/prettywriter.h @@ -108,7 +108,6 @@ public: } bool String(const Ch* str, SizeType length, bool copy = false) { - RAPIDJSON_ASSERT(str != 0); (void)copy; PrettyPrefix(kStringType); return Base::EndValue(Base::WriteString(str, length));