153 lines
2.8 KiB
Go
153 lines
2.8 KiB
Go
package gg
|
|
|
|
import (
|
|
//"github.com/hajimehoshi/ebiten/v2"
|
|
//"math"
|
|
)
|
|
|
|
type Transformer interface {
|
|
GetTransform() Transform
|
|
}
|
|
|
|
// The structure represents basic transformation
|
|
// features: positioning, rotating and scaling.
|
|
type Transform struct {
|
|
// Absolute (if no parent) position and
|
|
// the scale.
|
|
Position, Scale Vector
|
|
// The object rotation in radians.
|
|
Rotation Float
|
|
// The not scaled offset vector from upper left corner
|
|
// which the object should be rotated around.
|
|
Around Vector
|
|
// If is not nil then the upper values will be relational to
|
|
// the parent ones.
|
|
Parent Transformer
|
|
}
|
|
|
|
func (t Transform) GetTransform() Transform {
|
|
return t
|
|
}
|
|
|
|
// Returns the default Transform structure.
|
|
func T() Transform {
|
|
ret := Transform{
|
|
// Rotate around
|
|
Scale: Vector{1, 1},
|
|
// Rotate around the center.
|
|
Around: V(.5, .5),
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (t *Transform) SetAbsPosition(absPosition Vector) {
|
|
if t.Parent == nil {
|
|
t.Position = absPosition
|
|
return
|
|
}
|
|
m := t.ParentMatrix()
|
|
m.Invert()
|
|
t.Position = absPosition.Apply(m)
|
|
}
|
|
|
|
// Get the absolute representation of the transform.
|
|
func (t Transform) Abs() Transform {
|
|
if t.Parent == nil {
|
|
return t
|
|
}
|
|
|
|
ret := T()
|
|
ret.Position = t.AbsPosition()
|
|
ret.Rotation = t.AbsRotation()
|
|
ret.Scale = t.AbsScale()
|
|
|
|
return ret
|
|
}
|
|
|
|
func (t Transform) AbsPosition() Vector {
|
|
if t.Parent == nil {
|
|
return t.Position
|
|
}
|
|
return t.Position.Apply(t.ParentMatrix())
|
|
}
|
|
|
|
func (t Transform) AbsScale() Vector {
|
|
if t.Parent == nil {
|
|
return t.Scale
|
|
}
|
|
return V2(1)
|
|
}
|
|
|
|
func (t Transform) AbsRotation() Float {
|
|
if t.Parent == nil {
|
|
return t.Rotation
|
|
}
|
|
return t.Rotation + t.Parent.GetTransform().AbsRotation()
|
|
}
|
|
|
|
func (t *Transform) SetAbsRotation(rot Float) {
|
|
if t.Parent == nil {
|
|
t.Rotation = rot
|
|
}
|
|
t.Rotation -= t.Parent.GetTransform().AbsRotation()
|
|
}
|
|
|
|
func (t *Transform) Connected() bool {
|
|
return t.Parent != nil
|
|
}
|
|
|
|
func (t *Transform) Connect(parent Transformer) {
|
|
absPosition := t.AbsPosition()
|
|
absRotation := t.AbsRotation()
|
|
t.Parent = parent
|
|
t.SetAbsPosition(absPosition)
|
|
t.SetAbsRotation(absRotation)
|
|
}
|
|
|
|
func (t *Transform) Disconnect() {
|
|
if t.Parent == nil {
|
|
return
|
|
}
|
|
*t = t.Abs()
|
|
}
|
|
|
|
func (t Transform) ParentMatrix() Matrix {
|
|
g := Matrix{}
|
|
if t.Parent == nil {
|
|
return g
|
|
}
|
|
|
|
p := t.Parent.GetTransform()
|
|
g = p.ParentMatrix()
|
|
|
|
g.Scale(p.Scale.X, p.Scale.Y)
|
|
g.Rotate(p.Rotation)
|
|
g.Translate(p.Position.X, p.Position.Y)
|
|
|
|
return g
|
|
}
|
|
|
|
// Returns the GeoM with corresponding
|
|
// to the transfrom transformation.
|
|
func (t Transform)Matrix() Matrix {
|
|
g := Matrix{}
|
|
|
|
// Scale first.
|
|
g.Scale(t.Scale.X, t.Scale.Y)
|
|
|
|
// Then move and rotate.
|
|
g.Translate(
|
|
-t.Around.X * t.Scale.X,
|
|
-t.Around.Y * t.Scale.Y,
|
|
)
|
|
g.Rotate(t.Rotation)
|
|
|
|
// And finally move to the absolute position.
|
|
g.Translate(t.Position.X, t.Position.Y)
|
|
|
|
m := t.ParentMatrix()
|
|
g.Concat(m)
|
|
|
|
return g
|
|
}
|
|
|