diff --git a/dev.project.json b/dev.project.json index ff75a16..386c371 100644 --- a/dev.project.json +++ b/dev.project.json @@ -5,7 +5,7 @@ "ReplicatedStorage": { "SmartBone": { - "$path": "src-build" + "$path": "src" } }, diff --git a/src/Components/Bone.luau b/src/Components/Bone.luau index fcd7d50..ca204ed 100644 --- a/src/Components/Bone.luau +++ b/src/Components/Bone.luau @@ -453,8 +453,9 @@ function Class.new(Bone: Bone, RootBone: Bone, RootPart: BasePart): IBone Radius = 0, Friction = 0, RotationLimit = 0, - Force = nil, - Gravity = nil, + Force = Vector3.zero, + Gravity = Vector3.zero, + GravityFalloff = 0, SolvedAnimatedCFrame = false, HasChild = false, @@ -585,9 +586,10 @@ function Class:StepPhysics(BoneTree, Force: Vector3, Delta: number) -- Parallel -- Custom forces per bone if self.Force or self.Gravity then debug.profilebegin("Solve Force") + Force = (self.Gravity or BoneTree.Settings.Gravity) + Force += (self.Force or BoneTree.Settings.Force) - Force = (Force + (self.Force or BoneTree.Settings.Force)) debug.profileend() end @@ -710,7 +712,7 @@ function Class:SolveTransform(BoneTree, Delta: number) -- Parallel safe --elseif ShouldAverage then -- ParentBone.RotationSum += Vector3.new(Rotation:ToEulerAnglesXYZ()) else - ParentBone.CalculatedWorldCFrame = BoneParent.WorldCFrame:Lerp(CFrame.new(ParentBone.Position) * Rotation, alpha) + ParentBone.CalculatedWorldCFrame = ReferenceCFrame:Lerp(CFrame.new(ParentBone.Position) * Rotation, alpha) --ParentBone.CalculatedWorldCFrame = CFrame.new(ParentBone.Position) * Rotation end @@ -744,10 +746,13 @@ function Class:ApplyTransform(BoneTree) -- end if ParentBone and BoneParent then - if ParentBone.Anchored and not BoneTree.Settings.AnchorsRotate then -- Anchored and anchors do not rotate - BoneParent.WorldCFrame = ParentBone.TransformOffset - elseif ParentBone.Anchored then -- Anchored and anchors rotate - BoneParent.WorldCFrame = CFrame.new(ParentBone.Position) * ParentBone.CalculatedWorldCFrame.Rotation + if ParentBone.Anchored then -- Anchored and anchors do not rotate + + if BoneTree.Settings.AnchorsRotate and not self.Anchored then + BoneParent.WorldCFrame = CFrame.new(ParentBone.Position) * ParentBone.CalculatedWorldCFrame.Rotation + else + BoneParent.WorldCFrame = ParentBone.TransformOffset + end else -- Not anchored BoneParent.WorldCFrame = ParentBone.CalculatedWorldCFrame end diff --git a/src/Components/BoneTree.luau b/src/Components/BoneTree.luau index 9986457..921f9fc 100644 --- a/src/Components/BoneTree.luau +++ b/src/Components/BoneTree.luau @@ -38,6 +38,7 @@ export type IBoneTree = { ObjectVelocity: Vector3, ObjectAcceleration: Vector3, ObjectPreviousPosition: Vector3, + DefaultRootOrientation: CFrame, } type ImOverlay = { @@ -157,6 +158,10 @@ end --- @prop ObjectPreviousPosition Vector3 --- Root parts previous position +--- @within BoneTree +--- @prop DefaultRootOrientation +--- The Default WorldSpace Orientation of the Root Bone + local Class = {} Class.__index = Class @@ -188,6 +193,7 @@ function Class.new(RootBone: Bone, RootPart: BasePart, Settings: { any }): IBone ObjectVelocity = Vector3.zero, ObjectAcceleration = Vector3.zero, ObjectPreviousPosition = RootPart.Position, + DefaultRootOrientation = (RootBone:IsA("Bone") and RootBone.WorldCFrame or CFrame.identity).Rotation, }, Class) self.InWorkspace = RootPart:IsDescendantOf(workspace) @@ -327,7 +333,20 @@ end function Class:StepPhysics(Delta: number) debug.profilebegin("BoneTree::StepPhysics") local Settings = self.Settings - local Force = (Settings.Gravity + Settings.Force) + + -- Calculate the effect of Gravity given deviation from the resting 'Skyward' UpVector and clamped by GravityFalloff Setting + + local DefaultRot, NewRot = self.DefaultRootOrientation.Rotation, self.Root.WorldCFrame.Rotation + local Transform = NewRot:ToWorldSpace(DefaultRot) + + local RelativeDotProduct = Transform.UpVector:Dot(Vector3.yAxis) + + local DistanceFromWorldUp = math.clamp(1 - RelativeDotProduct, 0, 1) + + local Gravity = Settings.Gravity + Gravity = Gravity * math.lerp((1 - Settings.GravityFalloff), 1, DistanceFromWorldUp) + + local Force = (Gravity + Settings.Force) if Settings.MatchWorkspaceWind == true then local GlobalWind = workspace.GlobalWind diff --git a/src/Dependencies/DefaultObjectSettings.luau b/src/Dependencies/DefaultObjectSettings.luau index 1d06b14..6c1bfcc 100644 --- a/src/Dependencies/DefaultObjectSettings.luau +++ b/src/Dependencies/DefaultObjectSettings.luau @@ -12,6 +12,7 @@ return table.freeze({ Constraint = "Spring", Force = Vector3.yAxis * FORCE_MULTIPLIER, Gravity = -Vector3.yAxis * 25, + GravityFalloff = 0, WindType = "Hybrid", MatchWorkspaceWind = true, diff --git a/src/Dependencies/Utilities.luau b/src/Dependencies/Utilities.luau index 0711322..15358b8 100644 --- a/src/Dependencies/Utilities.luau +++ b/src/Dependencies/Utilities.luau @@ -133,7 +133,7 @@ function module.GatherBoneSettings(Bone: Bone) RotationLimit = RotationLimit, Radius = Radius, Force = Force, - Gravity = Gravity, + Gravity = Gravity } return Settings