283 lines
5.3 KiB
Go
283 lines
5.3 KiB
Go
package scene
|
|
|
|
import "aego/core/mathx"
|
|
|
|
func (s *Scene) Local(h NodeHandle) Transform2D {
|
|
n, ok := s.nodes.Get(h)
|
|
if !ok {
|
|
return IdentityTransform()
|
|
}
|
|
return n.local
|
|
}
|
|
|
|
func (s *Scene) local2D(h NodeHandle) (*nodeData, bool) {
|
|
n, ok := s.node(h)
|
|
if !ok || n.space == Space3D {
|
|
return nil, false
|
|
}
|
|
return n, true
|
|
}
|
|
|
|
func (s *Scene) SetLocal(h NodeHandle, t Transform2D) {
|
|
n, ok := s.local2D(h)
|
|
if !ok {
|
|
return
|
|
}
|
|
n.local = t
|
|
s.markWorldDirty(h)
|
|
}
|
|
|
|
func (s *Scene) SetPosition(h NodeHandle, p mathx.Vec2) {
|
|
n, ok := s.local2D(h)
|
|
if !ok {
|
|
return
|
|
}
|
|
n.local.Position = p
|
|
s.markWorldDirty(h)
|
|
}
|
|
|
|
func (s *Scene) SetRotation(h NodeHandle, r float32) {
|
|
n, ok := s.local2D(h)
|
|
if !ok {
|
|
return
|
|
}
|
|
n.local.Rotation = r
|
|
s.markWorldDirty(h)
|
|
}
|
|
|
|
func (s *Scene) SetScale(h NodeHandle, sc mathx.Vec2) {
|
|
n, ok := s.local2D(h)
|
|
if !ok {
|
|
return
|
|
}
|
|
n.local.Scale = sc
|
|
s.markWorldDirty(h)
|
|
}
|
|
|
|
func (s *Scene) Local3D(h NodeHandle) Transform3D {
|
|
n, ok := s.nodes.Get(h)
|
|
if !ok || n.slot < 0 {
|
|
return IdentityTransform3D()
|
|
}
|
|
return s.three[n.slot].local
|
|
}
|
|
|
|
func (s *Scene) local3D(h NodeHandle) (*node3, bool) {
|
|
n, ok := s.node(h)
|
|
if !ok || n.slot < 0 {
|
|
return nil, false
|
|
}
|
|
return &s.three[n.slot], true
|
|
}
|
|
|
|
func (s *Scene) SetLocal3D(h NodeHandle, t Transform3D) {
|
|
e, ok := s.local3D(h)
|
|
if !ok {
|
|
return
|
|
}
|
|
e.local = t
|
|
s.markWorldDirty(h)
|
|
}
|
|
|
|
func (s *Scene) SetPosition3D(h NodeHandle, p mathx.Vec3) {
|
|
e, ok := s.local3D(h)
|
|
if !ok {
|
|
return
|
|
}
|
|
e.local.Position = p
|
|
s.markWorldDirty(h)
|
|
}
|
|
|
|
func (s *Scene) SetRotation3D(h NodeHandle, q mathx.Quat) {
|
|
e, ok := s.local3D(h)
|
|
if !ok {
|
|
return
|
|
}
|
|
e.local.Rotation = q
|
|
s.markWorldDirty(h)
|
|
}
|
|
|
|
func (s *Scene) SetScale3D(h NodeHandle, sc mathx.Vec3) {
|
|
e, ok := s.local3D(h)
|
|
if !ok {
|
|
return
|
|
}
|
|
e.local.Scale = sc
|
|
s.markWorldDirty(h)
|
|
}
|
|
|
|
func (s *Scene) Pose(h NodeHandle) Pose {
|
|
n, ok := s.nodes.Get(h)
|
|
if !ok {
|
|
return Pose{T2: IdentityTransform(), T3: IdentityTransform3D()}
|
|
}
|
|
p := Pose{Space: n.space, T2: n.local, T3: IdentityTransform3D()}
|
|
if n.slot >= 0 {
|
|
p.T3 = s.three[n.slot].local
|
|
}
|
|
return p
|
|
}
|
|
|
|
func (s *Scene) SetPose(h NodeHandle, p Pose) {
|
|
if s.Space(h) != p.Space {
|
|
return
|
|
}
|
|
if p.Space == Space3D {
|
|
s.SetLocal3D(h, p.T3)
|
|
return
|
|
}
|
|
s.SetLocal(h, p.T2)
|
|
}
|
|
|
|
func (s *Scene) markWorldDirty(h NodeHandle) {
|
|
n, ok := s.nodes.Get(h)
|
|
if !ok || n.has(flagWorldDirty) {
|
|
return
|
|
}
|
|
n.set(flagWorldDirty, true)
|
|
for c := n.firstChild; !c.IsZero(); {
|
|
child, ok := s.nodes.Get(c)
|
|
if !ok {
|
|
break
|
|
}
|
|
next := child.nextSib
|
|
s.markWorldDirty(c)
|
|
c = next
|
|
}
|
|
}
|
|
|
|
func (s *Scene) World(h NodeHandle) mathx.Mat3 {
|
|
n, ok := s.nodes.Get(h)
|
|
if !ok {
|
|
return mathx.Mat3Identity()
|
|
}
|
|
if n.has(flagWorldDirty) {
|
|
s.UpdateTransforms()
|
|
n, _ = s.nodes.Get(h)
|
|
}
|
|
return n.world
|
|
}
|
|
|
|
func (s *Scene) WorldPosition(h NodeHandle) mathx.Vec2 {
|
|
m := s.World(h)
|
|
return mathx.Vec2{X: m[6], Y: m[7]}
|
|
}
|
|
|
|
func (s *Scene) World4(h NodeHandle) mathx.Mat4 {
|
|
n, ok := s.nodes.Get(h)
|
|
if !ok {
|
|
return mathx.Mat4Identity()
|
|
}
|
|
if n.has(flagWorldDirty) {
|
|
s.UpdateTransforms()
|
|
n, _ = s.nodes.Get(h)
|
|
}
|
|
if n.space == Space3D {
|
|
return s.three[n.slot].world
|
|
}
|
|
if !n.has(flagUnder3D) {
|
|
return mathx.Mat4Lift(n.world)
|
|
}
|
|
for a := n.parent; !a.IsZero(); {
|
|
an, ok := s.nodes.Get(a)
|
|
if !ok {
|
|
break
|
|
}
|
|
if an.space == Space3D {
|
|
return s.three[an.slot].world.Mul(mathx.Mat4Lift(n.world))
|
|
}
|
|
a = an.parent
|
|
}
|
|
return mathx.Mat4Lift(n.world)
|
|
}
|
|
|
|
func (s *Scene) WorldPosition3D(h NodeHandle) mathx.Vec3 {
|
|
return s.World4(h).Translation()
|
|
}
|
|
|
|
func (s *Scene) Enabled(h NodeHandle) bool {
|
|
n, ok := s.nodes.Get(h)
|
|
return ok && n.has(flagEnabled)
|
|
}
|
|
|
|
func (s *Scene) SetEnabled(h NodeHandle, v bool) {
|
|
n, ok := s.node(h)
|
|
if !ok || n.has(flagEnabled) == v {
|
|
return
|
|
}
|
|
n.set(flagEnabled, v)
|
|
s.markWorldDirty(h)
|
|
s.touch()
|
|
}
|
|
|
|
func (s *Scene) EffectiveEnabled(h NodeHandle) bool {
|
|
n, ok := s.nodes.Get(h)
|
|
return ok && n.has(flagEffective)
|
|
}
|
|
|
|
func (s *Scene) Layers(h NodeHandle) uint64 {
|
|
n, ok := s.nodes.Get(h)
|
|
if !ok {
|
|
return 0
|
|
}
|
|
return n.layers
|
|
}
|
|
|
|
func (s *Scene) SetLayers(h NodeHandle, m uint64) {
|
|
n, ok := s.node(h)
|
|
if !ok {
|
|
return
|
|
}
|
|
n.layers = m
|
|
s.touch()
|
|
}
|
|
|
|
func (s *Scene) UpdateTransforms() {
|
|
track := len(s.pres) > 0 || s.presActive
|
|
s.render = s.render[:0]
|
|
for _, h := range s.PreOrder() {
|
|
n, ok := s.nodes.Get(h)
|
|
if !ok || !n.has(flagAlive) {
|
|
continue
|
|
}
|
|
if h == s.root {
|
|
if n.has(flagWorldDirty) {
|
|
n.world = n.local.Matrix()
|
|
n.set(flagWorldDirty, false)
|
|
}
|
|
n.set(flagEffective, n.has(flagEnabled))
|
|
n.rslot = 0
|
|
continue
|
|
}
|
|
p, ok := s.nodes.Get(n.parent)
|
|
if !ok {
|
|
continue
|
|
}
|
|
parent3 := p.space == Space3D
|
|
n.set(flagUnder3D, n.space == Space2D && (parent3 || p.has(flagUnder3D)))
|
|
if n.has(flagWorldDirty) {
|
|
switch {
|
|
case n.space == Space3D:
|
|
e := &s.three[n.slot]
|
|
m := e.local.Matrix()
|
|
if parent3 {
|
|
m = s.three[p.slot].world.Mul(m)
|
|
}
|
|
e.world = m
|
|
n.world = mathx.Mat3TRS(mathx.Vec2{X: m[12], Y: -m[13]}, 0, mathx.Vec2{X: 1, Y: 1})
|
|
case parent3:
|
|
n.world = n.local.Matrix()
|
|
default:
|
|
n.world = p.world.Mul(n.local.Matrix())
|
|
}
|
|
n.set(flagWorldDirty, false)
|
|
}
|
|
n.set(flagEffective, n.has(flagEnabled) && p.has(flagEffective) && !n.has(flagPendingDestroy))
|
|
if track {
|
|
s.renderOf(n, p, parent3)
|
|
}
|
|
}
|
|
s.presActive = len(s.pres) > 0
|
|
s.presDirty = false
|
|
}
|