Мой вариант системы энтити - правда он 2Д и на БМаксе, но тут исповедуется моя религия.
Private
Type TPivot Extends TEntity
Field _parent:TPivot {no_save = 1}
Field _childs:TListEx = New TListEx
Field _ang:Float
Field _pos:Float2 = New Float2
Field _scl:Float2 = New Float2.Create(1.0, 1.0)
Field _tps:Float2 = New Float2
Field _call(entity:TEntity, dt:Float) = NullCallBack {no_save = 1}
Function NullCallBack(entity:TEntity, dt:Float)
End Function
Method SetCallBack(func(entity:TEntity, dt:Float) = Null, isGlobal:Byte = False) Final
Super.SetCallBack(func, isGlobal)
If func = Null Then func = NullCallBack
_call = func
End Method
Method New()
world.AddLast(Self)
End Method
Method Free()
Super.Free()
_pos = Null
_scl = Null
_tps = Null
_ang = Null
_childs = Null
GetParentList().Remove(Self)
_parent = Null
End Method
Method Copy:TEntity(parent:TEntity = Null)
Local pivot:TPivot = New TPivot
pivot.name = "copy_" + name
pivot.hide = hide
'pivot.data = data
pivot._pos = _pos.Copy()
pivot._scl = _scl.Copy()
pivot._tps = _tps.Copy()
pivot._ang = _ang
pivot.SetParent(parent)
If parent Then pivot.SetPosition(New Float2)
Return pivot
End Method
Method ToString:String()
Return "Pivot"
End Method
Method SetPosition(position:Float2, isGlobal:Byte = False) Final
If isGlobal And _parent
_tps = position.Sub(_parent.GetGlobalTransformedPosition())
_pos = _tps.UnRotate(New Float2.ForAngle(_parent._ang))
_pos = _pos.Div(_parent._scl)
Else
_pos = position.Copy()
Transform()
End If
'TranslateChilds()
End Method
Method GetPosition:Float2(isGlobal:Byte = False) Final
If isGlobal
Return GetGlobalTransformedPosition()
Else
Return _pos.Copy()
End If
End Method
Method SetRotation(angle:Float, isGlobal:Byte = False) Final
Local da:Float = _ang
If isGlobal
_ang = angle
Else
_ang = angle + GetParentAngle()
End If
RotateChilds(_ang - da)
End Method
Method GetRotation:Float(isGlobal:Byte = False) Final
If isGlobal Then Return _ang
Return _ang - GetParentAngle()
End Method
Method SetScale(scale:Float2, isGlobal:Byte = False) Final
Local ds:Float2 = _scl.Copy()
If isGlobal
_scl = scale.Copy()
Else
_scl = scale.Mul(GetParentScale())
End If
ScaleChilds(_scl.Div(ds))
End Method
Method GetScale:Float2(isGlobal:Byte = False) Final
If isGlobal Then Return _scl.Copy()
Return _scl.Div(GetParentScale())
End Method
Method SetTransform(angle:Float, scale:Float2, isGlobal:Byte = False) Final
Local da:Float = _ang
Local ds:Float2 = _scl.Copy()
If isGlobal
_ang = angle
_scl = scale.Copy()
Else
_ang = angle + GetParentAngle()
_scl = _scl.Mul(GetParentScale())
End If
TransformChilds(_scl.Div(ds), _ang - da)
End Method
Method SetParent(parent:TEntity) Final
If _parent = parent Then Return
GetParentList().Remove(Self)
_parent = TPivot(parent)
GetParentList().AddLast(Self)
If _parent
_ang = _parent._ang
_scl = _parent._scl.Copy()
SetPosition(New Float2)
End If
End Method
Method GetParent:TEntity() Final
Return _parent
End Method
Method CountChildren:Int() Final
Return _childs.Count()
End Method
Method GetChild:TEntity(index:Int) Final
Return TEntity(_childs.ValueAtIndex(index))
End Method
Method ObjectEnumerator:TListEnum() Final
Return _childs.ObjectEnumerator()
End Method
Method Intersect:Byte(entity:TEntity)
Select entity.ToString()
Case "Pivot" Return False
End Select
End Method
Method SetOrder(order:Int) Final
Local list:TListEx = GetParentList()
Select Sgn(order)
Case 1 list.MoveDown(Self, order)
Case - 1 list.MoveUp(Self, - order)
End Select
End Method
'PRIVATE
Method Build(parent:TPivot)
'If _parent = parent Then Return
For Local child:TPivot = EachIn _childs
child.Build(Self)
Next
_parent = parent
If Not GetParentList().Contains(Self) Then GetParentList().AddLast(Self)
End Method
Method Update(dt:Float)
If hide Then Return
_call(Self, dt)
For Local child:TPivot = EachIn _childs
child.Update(dt)
Next
End Method
Method Draw(position:Float2)
If hide Then Return
Local mypos:Float2 = position.Add(_tps)
If Debug
.SetTransform()
.SetColor(255, 255, 255)
.SetAlpha(1.0)
.SetBlend(ALPHABLEND)
DrawOval(mypos.x - 3, mypos.y - 3, 6, 6)
End If
For Local child:TPivot = EachIn _childs
child.Draw(mypos)
Next
End Method
Method GetParentList:TListEx() Final
If _parent Then Return _parent._childs
Return world
End Method
Method GetParentScale:Float2() Final
If _parent Then Return _parent._scl
Return New Float2.Create(1.0, 1.0)
End Method
Method GetParentAngle:Float() Final
If _parent Then Return _parent._ang
Return 0.0
End Method
Method ScaleChilds(ds:Float2) Final
For Local child:TPivot = EachIn _childs
child._scl = child._scl.Mul(ds)
child.Transform()
child.ScaleChilds(ds)
Next
End Method
Method RotateChilds(da:Float) Final
For Local child:TPivot = EachIn _childs
child._ang:+da
child.Transform()
child.RotateChilds(da)
Next
End Method
'Method TranslateChilds()
' For Local child:TPivot = EachIn _childs
' 'Calc BBox
' child.TranslateChilds()
' Next
'End Method
Method TransformChilds(ds:Float2, da:Float) Final
For Local child:TPivot = EachIn _childs
child._scl = child._scl.Mul(ds)
child._ang:+da
child.Transform()
child.TransformChilds(ds, da)
Next
End Method
Method Transform() Final
_tps = _pos.Mul(GetParentScale())
_tps = _tps.Rotate(New Float2.ForAngle(GetParentAngle()))
End Method
Method GetGlobalTransformedPosition:Float2() Final
Local pos:Float2 = _tps.Copy()
Local pivot:TPivot = _parent
While pivot
pos = pos.Add(pivot._tps)
pivot = pivot._parent
Wend
Return pos
End Method
'*******************
Method GetPick:Byte()
End Method
Method GetAlpha:Float()
End Method
Method GetBlend:Byte()
End Method
Method GetColor:TColor()
End Method
Method Align(vector:Float2) Final
SetRotation(vector.ToAngle() + 90.0, True)
End Method
Method Point(target:TEntity) Final
Align(TPivot(target).GetGlobalTransformedPosition().Sub(GetGlobalTransformedPosition()))
End Method
Method Delta:Float(target:TEntity) Final
Return (target.GetRotation(True) - _ang)
End Method
Method Distance:Float(target:TEntity) Final
Return GetGlobalTransformedPosition().Sub(TPivot(target).GetGlobalTransformedPosition()).Length()
End Method
Method Move(speed:Float2) Final
_pos = _pos.Add(speed.Rotate(New Float2.ForAngle(_ang)))
Transform()
End Method
Method Turn(speed:Float) Final
_ang:+speed
RotateChilds(speed)
End Method
Method Translate(speed:Float2) Final
_pos = _pos.Add(speed)
_tps = _tps.Add(speed)
Transform()
End Method
End Type