Skip to content

Commit 5f480b5

Browse files
authored
Add a transform.ChangeParent(child, parent, keepWorldPosition) Function (#111)
* add change parent * fix tests * fix children test
1 parent d9268f9 commit 5f480b5

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

features/hierarchy/example_test.go

+43
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,49 @@ func TestFindChildren(t *testing.T) {
172172
}
173173
}
174174

175+
func TestChangeParent(t *testing.T) {
176+
w := donburi.NewWorld()
177+
178+
parent1 := donburi.NewTag().SetName("parent1")
179+
parent2 := donburi.NewTag().SetName("parent2")
180+
child := donburi.NewTag().SetName("child")
181+
182+
p1e := w.Entry(w.Create(parent1))
183+
p2e := w.Entry(w.Create(parent2))
184+
ce := w.Entry(w.Create(child))
185+
186+
// no parent exists
187+
ChangeParent(ce, p1e)
188+
testChildren(t, []childrenTest{
189+
{
190+
Parent: p1e,
191+
Children: []*donburi.Entry{ce},
192+
},
193+
})
194+
195+
// change to same parent
196+
ChangeParent(ce, p1e)
197+
testChildren(t, []childrenTest{
198+
{
199+
Parent: p1e,
200+
Children: []*donburi.Entry{ce},
201+
},
202+
})
203+
204+
// change parent
205+
ChangeParent(ce, p2e)
206+
testChildren(t, []childrenTest{
207+
{
208+
Parent: p1e,
209+
Children: []*donburi.Entry{},
210+
},
211+
{
212+
Parent: p2e,
213+
Children: []*donburi.Entry{ce},
214+
},
215+
})
216+
}
217+
175218
type childrenTest struct {
176219
Parent *donburi.Entry
177220
Children []*donburi.Entry

features/hierarchy/parent.go

+33
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,39 @@ func HasParent(entry *donburi.Entry) bool {
8989
return entry.HasComponent(parentComponent)
9090
}
9191

92+
// ChangeParent changes a parent of the entry.
93+
func ChangeParent(child *donburi.Entry, newParent *donburi.Entry) {
94+
if !newParent.Valid() {
95+
panic("newParent is not valid")
96+
}
97+
if !child.Valid() {
98+
panic("child is not valid")
99+
}
100+
if !newParent.HasComponent(childrenComponent) {
101+
newParent.AddComponent(childrenComponent)
102+
}
103+
104+
if oldParent, ok := GetParent(child); ok {
105+
if oldParent == newParent {
106+
return
107+
}
108+
109+
if oldParent.Valid() {
110+
oldChildren := donburi.Get[childrenData](oldParent, childrenComponent)
111+
for i, c := range oldChildren.Children {
112+
if c == child {
113+
oldChildren.Children = append(oldChildren.Children[:i], oldChildren.Children[i+1:]...)
114+
break
115+
}
116+
}
117+
}
118+
119+
child.RemoveComponent(parentComponent)
120+
}
121+
122+
SetParent(child, newParent)
123+
}
124+
92125
func getParentData(entry *donburi.Entry) (*parentData, bool) {
93126
if HasParent(entry) {
94127
p := donburi.Get[parentData](entry, parentComponent)

features/transform/transform.go

+34
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ func AppendChild(parent, child *donburi.Entry, keepWorldPosition bool) {
4141
SetParent(child, parent, keepWorldPosition)
4242
}
4343

44+
// ChangeParent changes parent of the entry.
45+
func ChangeParent(child, parent *donburi.Entry, keepWorldPosition bool) {
46+
if !child.HasComponent(Transform) {
47+
panic("entry does not have transform component")
48+
}
49+
RemoveParent(child, keepWorldPosition)
50+
hierarchy.ChangeParent(child, parent)
51+
SetParent(child, parent, keepWorldPosition)
52+
}
53+
4454
// SetParent sets parent to the entry.
4555
func SetParent(entry, parent *donburi.Entry, keepWorldPosition bool) {
4656
if !entry.HasComponent(Transform) {
@@ -73,6 +83,30 @@ func GetParent(entry *donburi.Entry) (*donburi.Entry, bool) {
7383
return hierarchy.GetParent(entry)
7484
}
7585

86+
// RemoveParent removes parent of the entry.
87+
func RemoveParent(entry *donburi.Entry, keepWorldPosition bool) {
88+
d := GetTransform(entry)
89+
if !d.hasParent {
90+
return
91+
}
92+
parent, _ := GetParent(entry)
93+
d.hasParent = false
94+
if keepWorldPosition {
95+
parentPos := WorldPosition(parent)
96+
97+
d.LocalPosition = d.LocalPosition.Add(parentPos)
98+
d.LocalRotation += WorldRotation(parent)
99+
100+
ws := WorldScale(parent)
101+
if ws.X != 0 {
102+
d.LocalScale.X = d.LocalScale.X * ws.X
103+
}
104+
if ws.Y != 0 {
105+
d.LocalScale.Y = d.LocalScale.Y * ws.Y
106+
}
107+
}
108+
}
109+
76110
// GetChildren returns children of the entry.
77111
func GetChildren(entry *donburi.Entry) ([]*donburi.Entry, bool) {
78112
return hierarchy.GetChildren(entry)

features/transform/transform_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ func TestTransform(t *testing.T) {
3939
Rotation: 180,
4040
Scale: dmath.Vec2{X: 2, Y: 3},
4141
})
42+
43+
transform.RemoveParent(parent, false)
44+
45+
testWorldTransform(t, child, &testTransform{
46+
Position: dmath.Vec2{X: 1, Y: 2},
47+
Rotation: 180,
48+
Scale: dmath.Vec2{X: 2, Y: 3},
49+
})
4250
}
4351

4452
func TestTransformKeepWorldPosition(t *testing.T) {
@@ -64,6 +72,14 @@ func TestTransformKeepWorldPosition(t *testing.T) {
6472
Rotation: 90,
6573
Scale: dmath.Vec2{X: 1.5, Y: 1.5},
6674
})
75+
76+
transform.RemoveParent(parent, true)
77+
78+
testWorldTransform(t, child, &testTransform{
79+
Position: dmath.Vec2{X: 1, Y: 2},
80+
Rotation: 90,
81+
Scale: dmath.Vec2{X: 1.5, Y: 1.5},
82+
})
6783
}
6884

6985
func TestTransformDefaultValue(t *testing.T) {

0 commit comments

Comments
 (0)