260 lines
6.5 KiB
Go
260 lines
6.5 KiB
Go
package components
|
|
|
|
import (
|
|
"aego/core/mathx"
|
|
"aego/scene"
|
|
"aego/schema"
|
|
)
|
|
|
|
type BodyType uint8
|
|
|
|
const (
|
|
Static BodyType = iota
|
|
Kinematic
|
|
Dynamic
|
|
)
|
|
|
|
type MassMode uint8
|
|
|
|
const (
|
|
MassAuto MassMode = iota
|
|
MassOverride
|
|
)
|
|
|
|
const (
|
|
NameBody = "physics.Body2D"
|
|
NameBox = "physics.BoxCollider2D"
|
|
NameCircle = "physics.CircleCollider2D"
|
|
NameCapsule = "physics.CapsuleCollider2D"
|
|
NamePolygon = "physics.PolygonCollider2D"
|
|
NameEdge = "physics.EdgeCollider2D"
|
|
NameDistance = "physics.DistanceJoint2D"
|
|
NameRevolute = "physics.RevoluteJoint2D"
|
|
|
|
MaxPolygonPoints = 8
|
|
)
|
|
|
|
type Kind uint8
|
|
|
|
const (
|
|
KindBox Kind = iota
|
|
KindCircle
|
|
KindCapsule
|
|
KindPolygon
|
|
KindEdge
|
|
KindCount
|
|
)
|
|
|
|
var Names = [KindCount]string{NameBox, NameCircle, NameCapsule, NamePolygon, NameEdge}
|
|
|
|
var (
|
|
TypeBody = schema.HashName(NameBody)
|
|
TypeDistance = schema.HashName(NameDistance)
|
|
TypeRevolute = schema.HashName(NameRevolute)
|
|
colliderTypes = [KindCount]schema.TypeID{
|
|
schema.HashName(NameBox),
|
|
schema.HashName(NameCircle),
|
|
schema.HashName(NameCapsule),
|
|
schema.HashName(NamePolygon),
|
|
schema.HashName(NameEdge),
|
|
}
|
|
)
|
|
|
|
func ColliderType(k Kind) schema.TypeID {
|
|
return colliderTypes[k]
|
|
}
|
|
|
|
func Is(t schema.TypeID) bool {
|
|
if t == TypeBody || t == TypeDistance || t == TypeRevolute {
|
|
return true
|
|
}
|
|
for _, c := range colliderTypes {
|
|
if c == t {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
type Body2D struct {
|
|
Type BodyType `aego:"type"`
|
|
MassMode MassMode `aego:"massMode"`
|
|
Mass float32 `aego:"mass,min=0,hidden"`
|
|
GravityScale float32 `aego:"gravityScale"`
|
|
LinearDamping float32 `aego:"linearDamping,min=0"`
|
|
AngularDamping float32 `aego:"angularDamping,min=0"`
|
|
FixedRotation bool `aego:"fixedRotation"`
|
|
Bullet bool `aego:"bullet"`
|
|
AllowSleep bool `aego:"allowSleep"`
|
|
Interpolate bool `aego:"interpolate"`
|
|
Layer int32 `aego:"layer,min=0,max=31"`
|
|
Mask int64 `aego:"mask"`
|
|
Velocity mathx.Vec2 `aego:"velocity,transient,readonly,category=Runtime"`
|
|
AngularVelocity float32 `aego:"angularVelocity,transient,readonly,category=Runtime"`
|
|
Awake bool `aego:"awake,transient,readonly,category=Runtime"`
|
|
}
|
|
|
|
type ColliderCommon struct {
|
|
Offset mathx.Vec2 `aego:"offset"`
|
|
IsTrigger bool `aego:"isTrigger"`
|
|
Friction float32 `aego:"friction,min=0"`
|
|
Restitution float32 `aego:"restitution,min=0"`
|
|
Density float32 `aego:"density,min=0"`
|
|
}
|
|
|
|
type BoxCollider2D struct {
|
|
ColliderCommon
|
|
Size mathx.Vec2 `aego:"size"`
|
|
}
|
|
|
|
type CircleCollider2D struct {
|
|
ColliderCommon
|
|
Radius float32 `aego:"radius,min=0"`
|
|
}
|
|
|
|
type CapsuleCollider2D struct {
|
|
ColliderCommon
|
|
Length float32 `aego:"length,min=0"`
|
|
Radius float32 `aego:"radius,min=0"`
|
|
}
|
|
|
|
type PolygonCollider2D struct {
|
|
ColliderCommon
|
|
Points []mathx.Vec2 `aego:"points"`
|
|
}
|
|
|
|
type EdgeCollider2D struct {
|
|
ColliderCommon
|
|
Points []mathx.Vec2 `aego:"points"`
|
|
Loop bool `aego:"loop"`
|
|
OneSided bool `aego:"oneSided"`
|
|
}
|
|
|
|
type DistanceJoint2D struct {
|
|
Target scene.NodeRef `aego:"target"`
|
|
AnchorA mathx.Vec2 `aego:"anchorA"`
|
|
AnchorB mathx.Vec2 `aego:"anchorB"`
|
|
Length float32 `aego:"length,min=0"`
|
|
MinLength float32 `aego:"minLength,min=0"`
|
|
MaxLength float32 `aego:"maxLength,min=0"`
|
|
Stiffness float32 `aego:"stiffness,min=0"`
|
|
Damping float32 `aego:"damping,min=0"`
|
|
CollideConnected bool `aego:"collideConnected"`
|
|
}
|
|
|
|
type RevoluteJoint2D struct {
|
|
Target scene.NodeRef `aego:"target"`
|
|
Anchor mathx.Vec2 `aego:"anchor"`
|
|
EnableLimit bool `aego:"enableLimit"`
|
|
Lower float32 `aego:"lower"`
|
|
Upper float32 `aego:"upper"`
|
|
EnableMotor bool `aego:"enableMotor"`
|
|
Speed float32 `aego:"speed"`
|
|
MaxTorque float32 `aego:"maxTorque,min=0"`
|
|
CollideConnected bool `aego:"collideConnected"`
|
|
}
|
|
|
|
func DefaultBody2D() Body2D {
|
|
return Body2D{Type: Dynamic, GravityScale: 1, AllowSleep: true, Mask: -1}
|
|
}
|
|
|
|
func DefaultCommon() ColliderCommon {
|
|
return ColliderCommon{Friction: 0.6, Density: 1}
|
|
}
|
|
|
|
func DefaultBox() BoxCollider2D {
|
|
return BoxCollider2D{ColliderCommon: DefaultCommon(), Size: mathx.Vec2{X: 1, Y: 1}}
|
|
}
|
|
|
|
func DefaultCircle() CircleCollider2D {
|
|
return CircleCollider2D{ColliderCommon: DefaultCommon(), Radius: 0.5}
|
|
}
|
|
|
|
func DefaultCapsule() CapsuleCollider2D {
|
|
return CapsuleCollider2D{ColliderCommon: DefaultCommon(), Length: 1, Radius: 0.25}
|
|
}
|
|
|
|
func DefaultPolygon() PolygonCollider2D {
|
|
return PolygonCollider2D{ColliderCommon: DefaultCommon(), Points: []mathx.Vec2{
|
|
{X: -0.5, Y: -0.5}, {X: 0.5, Y: -0.5}, {X: 0.5, Y: 0.5}, {X: -0.5, Y: 0.5},
|
|
}}
|
|
}
|
|
|
|
func DefaultEdge() EdgeCollider2D {
|
|
return EdgeCollider2D{ColliderCommon: DefaultCommon(), Points: []mathx.Vec2{{X: -2}, {X: 2}}}
|
|
}
|
|
|
|
func DefaultDistance() DistanceJoint2D {
|
|
return DistanceJoint2D{}
|
|
}
|
|
|
|
func DefaultRevolute() RevoluteJoint2D {
|
|
return RevoluteJoint2D{}
|
|
}
|
|
|
|
type Collider struct {
|
|
Kind Kind
|
|
Common ColliderCommon
|
|
Size mathx.Vec2
|
|
Radius float32
|
|
Length float32
|
|
Points []mathx.Vec2
|
|
Loop bool
|
|
OneSided bool
|
|
}
|
|
|
|
func HasCollider(s *scene.Scene, h scene.NodeHandle, k Kind) bool {
|
|
switch k {
|
|
case KindBox:
|
|
return scene.Has[BoxCollider2D](s, h)
|
|
case KindCircle:
|
|
return scene.Has[CircleCollider2D](s, h)
|
|
case KindCapsule:
|
|
return scene.Has[CapsuleCollider2D](s, h)
|
|
case KindPolygon:
|
|
return scene.Has[PolygonCollider2D](s, h)
|
|
case KindEdge:
|
|
return scene.Has[EdgeCollider2D](s, h)
|
|
}
|
|
return false
|
|
}
|
|
|
|
func Read(s *scene.Scene, h scene.NodeHandle, k Kind, dst *Collider) bool {
|
|
*dst = Collider{Kind: k}
|
|
switch k {
|
|
case KindBox:
|
|
c, ok := scene.Get[BoxCollider2D](s, h)
|
|
if !ok {
|
|
return false
|
|
}
|
|
dst.Common, dst.Size = c.ColliderCommon, c.Size
|
|
case KindCircle:
|
|
c, ok := scene.Get[CircleCollider2D](s, h)
|
|
if !ok {
|
|
return false
|
|
}
|
|
dst.Common, dst.Radius = c.ColliderCommon, c.Radius
|
|
case KindCapsule:
|
|
c, ok := scene.Get[CapsuleCollider2D](s, h)
|
|
if !ok {
|
|
return false
|
|
}
|
|
dst.Common, dst.Length, dst.Radius = c.ColliderCommon, c.Length, c.Radius
|
|
case KindPolygon:
|
|
c, ok := scene.Get[PolygonCollider2D](s, h)
|
|
if !ok {
|
|
return false
|
|
}
|
|
dst.Common, dst.Points = c.ColliderCommon, c.Points
|
|
case KindEdge:
|
|
c, ok := scene.Get[EdgeCollider2D](s, h)
|
|
if !ok {
|
|
return false
|
|
}
|
|
dst.Common, dst.Points, dst.Loop, dst.OneSided = c.ColliderCommon, c.Points, c.Loop, c.OneSided
|
|
default:
|
|
return false
|
|
}
|
|
return true
|
|
}
|