@quenty/adorneeutils 3.5.0 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/package.json +2 -2
- package/src/Shared/AdorneeUtils.lua +32 -0
- package/src/Shared/AdorneeUtils.spec.lua +51 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [3.6.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/adorneeutils@3.5.0...@quenty/adorneeutils@3.6.0) (2026-09-02)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- **adorneeutils:** Add AdorneeUtils.setBoundingBoxCFrame ([d4b0fe8](https://github.com/Quenty/NevermoreEngine/commit/d4b0fe8f04b9e5ce26de76c47e387e6031ad87ec))
|
|
11
|
+
|
|
6
12
|
# [3.5.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/adorneeutils@3.4.0...@quenty/adorneeutils@3.5.0) (2026-08-28)
|
|
7
13
|
|
|
8
14
|
**Note:** Version bump only for package @quenty/adorneeutils
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/adorneeutils",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0",
|
|
4
4
|
"description": "AdorneeUtils - Generic adornee functions to make attaching to objects in Roblox easier.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"publishConfig": {
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "278f4ca25486a8ba0601704b27a11da8c77499c9"
|
|
41
41
|
}
|
|
@@ -69,6 +69,38 @@ function AdorneeUtils.getBoundingBox(adornee: Instance): (CFrame?, Vector3?)
|
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
+
--[=[
|
|
73
|
+
Moves the adornee so its bounding box sits at the given cframe, keeping every part where it
|
|
74
|
+
sits relative to the others.
|
|
75
|
+
|
|
76
|
+
This is the counterpart to [AdorneeUtils.getBoundingBox], and is not the same as `PivotTo`,
|
|
77
|
+
which moves the adornee by its pivot rather than by the center of its bounds.
|
|
78
|
+
|
|
79
|
+
@param adornee Instance
|
|
80
|
+
@param cframe CFrame -- New bounding box cframe
|
|
81
|
+
@return boolean -- False when the adornee has no bounding box to move
|
|
82
|
+
]=]
|
|
83
|
+
function AdorneeUtils.setBoundingBoxCFrame(adornee: Instance, cframe: CFrame): boolean
|
|
84
|
+
assert(typeof(adornee) == "Instance", "Adornee must by of type 'Instance'")
|
|
85
|
+
assert(typeof(cframe) == "CFrame", "Bad cframe")
|
|
86
|
+
|
|
87
|
+
local bbCFrame = AdorneeUtils.getBoundingBox(adornee)
|
|
88
|
+
if not bbCFrame then
|
|
89
|
+
return false
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
local relativeCFrames: { [BasePart]: CFrame } = {}
|
|
93
|
+
for _, part in AdorneeUtils.getParts(adornee) do
|
|
94
|
+
relativeCFrames[part] = bbCFrame:ToObjectSpace(part.CFrame)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
for part, relativeCFrame in relativeCFrames do
|
|
98
|
+
part.CFrame = cframe:ToWorldSpace(relativeCFrame)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
return true
|
|
102
|
+
end
|
|
103
|
+
|
|
72
104
|
--[=[
|
|
73
105
|
Returns whether a part is a part of an adornee
|
|
74
106
|
@param adornee Instance
|
|
@@ -439,6 +439,57 @@ describe("AdorneeUtils.getBoundingBox", function()
|
|
|
439
439
|
end)
|
|
440
440
|
end)
|
|
441
441
|
|
|
442
|
+
describe("AdorneeUtils.setBoundingBoxCFrame", function()
|
|
443
|
+
it("puts the bounding box where it was asked to go", function()
|
|
444
|
+
local controller = setup()
|
|
445
|
+
local model = controller.newModel()
|
|
446
|
+
|
|
447
|
+
local target = CFrame.new(20, 8, -4)
|
|
448
|
+
local moved = AdorneeUtils.setBoundingBoxCFrame(model, target)
|
|
449
|
+
|
|
450
|
+
local cframe = AdorneeUtils.getBoundingBox(model)
|
|
451
|
+
|
|
452
|
+
expect(moved).toBe(true)
|
|
453
|
+
expect(cframe).toEqual(target)
|
|
454
|
+
|
|
455
|
+
controller:Destroy()
|
|
456
|
+
end)
|
|
457
|
+
|
|
458
|
+
it("keeps parts where they sit relative to each other", function()
|
|
459
|
+
local controller = setup()
|
|
460
|
+
local model, first, second = controller.newModel()
|
|
461
|
+
|
|
462
|
+
local offset = first.CFrame:ToObjectSpace(second.CFrame)
|
|
463
|
+
|
|
464
|
+
AdorneeUtils.setBoundingBoxCFrame(model, CFrame.Angles(0, math.pi / 2, 0) + Vector3.new(20, 8, -4))
|
|
465
|
+
|
|
466
|
+
expect(first.CFrame:ToObjectSpace(second.CFrame)).toEqual(offset)
|
|
467
|
+
|
|
468
|
+
controller:Destroy()
|
|
469
|
+
end)
|
|
470
|
+
|
|
471
|
+
it("moves a lone part", function()
|
|
472
|
+
local controller = setup()
|
|
473
|
+
local part = controller.newPart(Vector3.new(4, 1, 2), CFrame.new(1, 2, 3))
|
|
474
|
+
|
|
475
|
+
local moved = AdorneeUtils.setBoundingBoxCFrame(part, CFrame.new(7, 7, 7))
|
|
476
|
+
|
|
477
|
+
expect(moved).toBe(true)
|
|
478
|
+
expect(part.CFrame).toEqual(CFrame.new(7, 7, 7))
|
|
479
|
+
|
|
480
|
+
controller:Destroy()
|
|
481
|
+
end)
|
|
482
|
+
|
|
483
|
+
it("reports nothing moved when the adornee has no parts", function()
|
|
484
|
+
local controller = setup()
|
|
485
|
+
local folder = controller.newFolder()
|
|
486
|
+
|
|
487
|
+
expect(AdorneeUtils.setBoundingBoxCFrame(folder, CFrame.new(1, 2, 3))).toBe(false)
|
|
488
|
+
|
|
489
|
+
controller:Destroy()
|
|
490
|
+
end)
|
|
491
|
+
end)
|
|
492
|
+
|
|
442
493
|
describe("AdorneeUtils.isPartOfAdornee", function()
|
|
443
494
|
it("returns true when the part is the adornee", function()
|
|
444
495
|
local controller = setup()
|