gg/transform.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
}