You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
234 lines
7.5 KiB
C#
234 lines
7.5 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace Otter {
|
|
public class Bone : Component {
|
|
|
|
public Bone Parent;
|
|
public Skeleton Skeleton;
|
|
public string Name;
|
|
public int Depth { get; private set; }
|
|
|
|
public List<Bone> Children = new List<Bone>();
|
|
|
|
public bool AutoAddEntities;
|
|
|
|
public bool InheritScale = false;
|
|
public bool InheritRotation = true;
|
|
|
|
public float X { get { return x; } set { LocalX = value; } }
|
|
public float Y { get { return y; } set { LocalY = value; } }
|
|
public float Rotation { get { return rotation; } set { LocalRotation = value; } }
|
|
public float ScaleX { get { return scaleX; } set { LocalScaleX = value; } }
|
|
public float ScaleY { get { return scaleY; } set { LocalScaleY = value; } }
|
|
|
|
public bool FlipX { get { return flipX; } set { LocalFlipX = value; } }
|
|
public bool FlipY { get { return flipY; } set { LocalFlipY = value; } }
|
|
|
|
public float LocalX;
|
|
public float LocalY;
|
|
public float LocalRotation;
|
|
public float LocalScaleX = 1;
|
|
public float LocalScaleY = 1;
|
|
|
|
public bool LocalFlipX;
|
|
public bool LocalFlipY;
|
|
|
|
public float BaseX { get; private set; }
|
|
public float BaseY { get; private set; }
|
|
public float BaseRotation { get; private set; }
|
|
public float BaseScaleX { get; private set; }
|
|
public float BaseScaleY { get; private set; }
|
|
|
|
float x;
|
|
float y;
|
|
float rotation;
|
|
float scaleX = 1;
|
|
float scaleY = 1;
|
|
bool flipX;
|
|
bool flipY;
|
|
|
|
float slotRotation;
|
|
bool slotFlipX;
|
|
bool slotFlipY;
|
|
float slotScaleX;
|
|
float slotScaleY;
|
|
|
|
public bool FlipGraphicX;
|
|
public bool FlipGraphicY;
|
|
|
|
internal Entity BoneEntity { get; private set; }
|
|
|
|
public struct BoneSlot {
|
|
public float Rotation;
|
|
public bool FlipX;
|
|
public bool FlipY;
|
|
public float ScaleX;
|
|
public float ScaleY;
|
|
}
|
|
|
|
public BoneSlot Slot { get; private set; }
|
|
|
|
public Bone(float x = 0, float y = 0, float rotation = 0, float scaleX = 1, float scaleY = 1) {
|
|
BaseX = x;
|
|
BaseY = y;
|
|
BaseScaleX = scaleX;
|
|
BaseScaleY = scaleY;
|
|
BaseRotation = rotation;
|
|
ScaleX = 1;
|
|
ScaleY = 1;
|
|
|
|
Visible = false;
|
|
}
|
|
|
|
public Bone(Entity e, float x = 0, float y = 0, float rotation = 0, float scaleX = 1, float scaleY = 1) : this(x, y, rotation, scaleX, scaleY) {
|
|
SetEntity(e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add a bone as a child of this bone. This should be done via a Skeleton!
|
|
/// </summary>
|
|
/// <param name="e">The bone to add.</param>
|
|
/// <returns>The added bone.</returns>
|
|
public Bone AddBone(Bone e) {
|
|
Children.Add(e);
|
|
e.Parent = this;
|
|
return e;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets all the children of a specified Bone.
|
|
/// </summary>
|
|
/// <returns>A list of bones that are the children of the specified Bone.</returns>
|
|
public List<Bone> GetAllChildren() {
|
|
var bones = new List<Bone>();
|
|
foreach (var c in Children) {
|
|
bones.AddRange(c.GetAllChildren());
|
|
bones.Add(c);
|
|
}
|
|
return bones;
|
|
}
|
|
|
|
public Bone SetEntity(Entity e) {
|
|
e.AddComponent(this);
|
|
BoneEntity = e;
|
|
return this;
|
|
}
|
|
|
|
public override void Added() {
|
|
base.Added();
|
|
BoneEntity = null;
|
|
}
|
|
|
|
public void UpdateTransforms() {
|
|
LocalRotation = Util.WrapAngle(LocalRotation); // Don't want the angle to get CRAZY
|
|
|
|
if (Parent != null) {
|
|
flipX = LocalFlipX ^ Parent.FlipX;
|
|
flipY = LocalFlipY ^ Parent.FlipY;
|
|
var pos = new Vector2(Parent.FlipX ? -LocalX - BaseX : LocalX + BaseX, Parent.FlipY ? -LocalY - BaseY : LocalY + BaseY);
|
|
|
|
if (InheritScale) {
|
|
scaleX = Parent.ScaleX * LocalScaleX * BaseScaleX;
|
|
scaleY = Parent.ScaleY * LocalScaleY * BaseScaleY;
|
|
}
|
|
else {
|
|
scaleX = LocalScaleX * BaseScaleX;
|
|
scaleY = LocalScaleY * BaseScaleY;
|
|
}
|
|
|
|
pos.X *= Parent.ScaleX;
|
|
pos.Y *= Parent.ScaleY;
|
|
|
|
pos.X += Parent.X;
|
|
pos.Y += Parent.Y;
|
|
|
|
if (InheritRotation) {
|
|
rotation = Parent.Rotation + LocalRotation + BaseRotation;
|
|
}
|
|
else {
|
|
rotation = LocalRotation + BaseRotation;
|
|
}
|
|
|
|
pos = Util.RotateAround(pos.X, pos.Y, Parent.X, Parent.Y, (Parent.FlipX ^ Parent.FlipY ? -Parent.Rotation : Parent.Rotation));
|
|
|
|
x = pos.X;
|
|
y = pos.Y;
|
|
|
|
Depth = Parent.Depth + 1;
|
|
}
|
|
else {
|
|
rotation = LocalRotation + BaseRotation;
|
|
scaleX = LocalScaleX * BaseScaleX;
|
|
scaleY = LocalScaleY * BaseScaleY;
|
|
x = LocalX + BaseX;
|
|
y = LocalY + BaseY;
|
|
flipX = LocalFlipX;
|
|
flipY = LocalFlipY;
|
|
|
|
Depth = 0;
|
|
}
|
|
|
|
rotation = Util.WrapAngle(rotation); // No crazy angles please.
|
|
|
|
if (Entity != null) {
|
|
var flipGraphicX = false;
|
|
var flipGraphicY = false;
|
|
|
|
if (FlipX && !FlipY) {
|
|
slotRotation = 180 - Rotation;
|
|
flipGraphicY = true;
|
|
}
|
|
else if (FlipY && !FlipX) {
|
|
slotRotation = -Rotation;
|
|
flipGraphicY = true;
|
|
}
|
|
else if (FlipX && FlipY) {
|
|
slotRotation = 180 + Rotation;
|
|
}
|
|
else {
|
|
slotRotation = Rotation;
|
|
}
|
|
|
|
if (InheritScale) {
|
|
slotScaleX = ScaleX;
|
|
slotScaleY = ScaleY;
|
|
}
|
|
else {
|
|
slotScaleX = LocalScaleX * BaseScaleX;
|
|
slotScaleY = LocalScaleY * BaseScaleY;
|
|
}
|
|
|
|
slotFlipX = flipGraphicX ^ FlipGraphicX;
|
|
slotFlipY = flipGraphicY ^ FlipGraphicY;
|
|
|
|
Entity.X = X;
|
|
Entity.Y = Y;
|
|
|
|
Slot = new BoneSlot() {
|
|
FlipX = slotFlipX,
|
|
FlipY = slotFlipY,
|
|
Rotation = slotRotation,
|
|
ScaleX = slotScaleX,
|
|
ScaleY = slotScaleY
|
|
};
|
|
|
|
if (!Entity.IsInScene && AutoAddEntities) {
|
|
if (Skeleton.Entity.IsInScene) {
|
|
Skeleton.Entity.Scene.Add(Entity);
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (var c in Children) {
|
|
c.UpdateTransforms();
|
|
}
|
|
}
|
|
|
|
public override void Render() {
|
|
base.Render();
|
|
//Draw.Circle(X - 3, Y - 3, 3, Color.Black, Color.White, 3);
|
|
}
|
|
|
|
}
|
|
}
|