Browse Source

[godot] Port 4.2 changes and expose in GDScript/C#

Mario Zechner 1 year ago
parent
commit
e623140c99

+ 529 - 514
spine-cpp/spine-cpp/src/spine/Skeleton.cpp

@@ -55,677 +55,692 @@
 
 
 using namespace spine;
 using namespace spine;
 
 
-Skeleton::Skeleton(SkeletonData *skeletonData) : _data(skeletonData),
-												 _skin(NULL),
-												 _color(1, 1, 1, 1),
-												 _scaleX(1),
-												 _scaleY(1),
-												 _x(0),
-												 _y(0),
-												 _time(0) {
-	_bones.ensureCapacity(_data->getBones().size());
-	for (size_t i = 0; i < _data->getBones().size(); ++i) {
-		BoneData *data = _data->getBones()[i];
+Skeleton::Skeleton(SkeletonData *skeletonData)
+    : _data(skeletonData), _skin(NULL), _color(1, 1, 1, 1), _scaleX(1),
+      _scaleY(1), _x(0), _y(0), _time(0) {
+  _bones.ensureCapacity(_data->getBones().size());
+  for (size_t i = 0; i < _data->getBones().size(); ++i) {
+    BoneData *data = _data->getBones()[i];
 
 
-		Bone *bone;
-		if (data->getParent() == NULL) {
-			bone = new (__FILE__, __LINE__) Bone(*data, *this, NULL);
-		} else {
-			Bone *parent = _bones[data->getParent()->getIndex()];
-			bone = new (__FILE__, __LINE__) Bone(*data, *this, parent);
-			parent->getChildren().add(bone);
-		}
+    Bone *bone;
+    if (data->getParent() == NULL) {
+      bone = new (__FILE__, __LINE__) Bone(*data, *this, NULL);
+    } else {
+      Bone *parent = _bones[data->getParent()->getIndex()];
+      bone = new (__FILE__, __LINE__) Bone(*data, *this, parent);
+      parent->getChildren().add(bone);
+    }
 
 
-		_bones.add(bone);
-	}
+    _bones.add(bone);
+  }
 
 
-	_slots.ensureCapacity(_data->getSlots().size());
-	_drawOrder.ensureCapacity(_data->getSlots().size());
-	for (size_t i = 0; i < _data->getSlots().size(); ++i) {
-		SlotData *data = _data->getSlots()[i];
+  _slots.ensureCapacity(_data->getSlots().size());
+  _drawOrder.ensureCapacity(_data->getSlots().size());
+  for (size_t i = 0; i < _data->getSlots().size(); ++i) {
+    SlotData *data = _data->getSlots()[i];
 
 
-		Bone *bone = _bones[data->getBoneData().getIndex()];
-		Slot *slot = new (__FILE__, __LINE__) Slot(*data, *bone);
+    Bone *bone = _bones[data->getBoneData().getIndex()];
+    Slot *slot = new (__FILE__, __LINE__) Slot(*data, *bone);
 
 
-		_slots.add(slot);
-		_drawOrder.add(slot);
-	}
+    _slots.add(slot);
+    _drawOrder.add(slot);
+  }
 
 
-	_ikConstraints.ensureCapacity(_data->getIkConstraints().size());
-	for (size_t i = 0; i < _data->getIkConstraints().size(); ++i) {
-		IkConstraintData *data = _data->getIkConstraints()[i];
+  _ikConstraints.ensureCapacity(_data->getIkConstraints().size());
+  for (size_t i = 0; i < _data->getIkConstraints().size(); ++i) {
+    IkConstraintData *data = _data->getIkConstraints()[i];
 
 
-		IkConstraint *constraint = new (__FILE__, __LINE__) IkConstraint(*data, *this);
+    IkConstraint *constraint =
+        new (__FILE__, __LINE__) IkConstraint(*data, *this);
 
 
-		_ikConstraints.add(constraint);
-	}
+    _ikConstraints.add(constraint);
+  }
 
 
-	_transformConstraints.ensureCapacity(_data->getTransformConstraints().size());
-	for (size_t i = 0; i < _data->getTransformConstraints().size(); ++i) {
-		TransformConstraintData *data = _data->getTransformConstraints()[i];
+  _transformConstraints.ensureCapacity(_data->getTransformConstraints().size());
+  for (size_t i = 0; i < _data->getTransformConstraints().size(); ++i) {
+    TransformConstraintData *data = _data->getTransformConstraints()[i];
 
 
-		TransformConstraint *constraint = new (__FILE__, __LINE__) TransformConstraint(*data, *this);
+    TransformConstraint *constraint =
+        new (__FILE__, __LINE__) TransformConstraint(*data, *this);
 
 
-		_transformConstraints.add(constraint);
-	}
+    _transformConstraints.add(constraint);
+  }
 
 
-	_pathConstraints.ensureCapacity(_data->getPathConstraints().size());
-	for (size_t i = 0; i < _data->getPathConstraints().size(); ++i) {
-		PathConstraintData *data = _data->getPathConstraints()[i];
+  _pathConstraints.ensureCapacity(_data->getPathConstraints().size());
+  for (size_t i = 0; i < _data->getPathConstraints().size(); ++i) {
+    PathConstraintData *data = _data->getPathConstraints()[i];
 
 
-		PathConstraint *constraint = new (__FILE__, __LINE__) PathConstraint(*data, *this);
+    PathConstraint *constraint =
+        new (__FILE__, __LINE__) PathConstraint(*data, *this);
 
 
-		_pathConstraints.add(constraint);
-	}
+    _pathConstraints.add(constraint);
+  }
 
 
-	_physicsConstraints.ensureCapacity(_data->getPhysicsConstraints().size());
-	for (size_t i = 0; i < _data->getPhysicsConstraints().size(); ++i) {
-		PhysicsConstraintData *data = _data->getPhysicsConstraints()[i];
+  _physicsConstraints.ensureCapacity(_data->getPhysicsConstraints().size());
+  for (size_t i = 0; i < _data->getPhysicsConstraints().size(); ++i) {
+    PhysicsConstraintData *data = _data->getPhysicsConstraints()[i];
 
 
-		PhysicsConstraint *constraint = new (__FILE__, __LINE__) PhysicsConstraint(*data, *this);
+    PhysicsConstraint *constraint =
+        new (__FILE__, __LINE__) PhysicsConstraint(*data, *this);
 
 
-		_physicsConstraints.add(constraint);
-	}
+    _physicsConstraints.add(constraint);
+  }
 
 
-	updateCache();
+  updateCache();
 }
 }
 
 
 Skeleton::~Skeleton() {
 Skeleton::~Skeleton() {
-	ContainerUtil::cleanUpVectorOfPointers(_bones);
-	ContainerUtil::cleanUpVectorOfPointers(_slots);
-	ContainerUtil::cleanUpVectorOfPointers(_ikConstraints);
-	ContainerUtil::cleanUpVectorOfPointers(_transformConstraints);
-	ContainerUtil::cleanUpVectorOfPointers(_pathConstraints);
-    ContainerUtil::cleanUpVectorOfPointers(_physicsConstraints);
+  ContainerUtil::cleanUpVectorOfPointers(_bones);
+  ContainerUtil::cleanUpVectorOfPointers(_slots);
+  ContainerUtil::cleanUpVectorOfPointers(_ikConstraints);
+  ContainerUtil::cleanUpVectorOfPointers(_transformConstraints);
+  ContainerUtil::cleanUpVectorOfPointers(_pathConstraints);
+  ContainerUtil::cleanUpVectorOfPointers(_physicsConstraints);
 }
 }
 
 
 void Skeleton::updateCache() {
 void Skeleton::updateCache() {
-	_updateCache.clear();
-
-	for (size_t i = 0, n = _bones.size(); i < n; ++i) {
-		Bone *bone = _bones[i];
-		bone->_sorted = bone->_data.isSkinRequired();
-		bone->_active = !bone->_sorted;
-	}
-
-	if (_skin) {
-		Vector<BoneData *> &skinBones = _skin->getBones();
-		for (size_t i = 0, n = skinBones.size(); i < n; i++) {
-			Bone *bone = _bones[skinBones[i]->getIndex()];
-			do {
-				bone->_sorted = false;
-				bone->_active = true;
-				bone = bone->_parent;
-			} while (bone);
-		}
-	}
-
-	size_t ikCount = _ikConstraints.size();
-	size_t transformCount = _transformConstraints.size();
-	size_t pathCount = _pathConstraints.size();
-	size_t physicsCount = _physicsConstraints.size();
-	size_t constraintCount = ikCount + transformCount + pathCount + physicsCount;
-
-	size_t i = 0;
+  _updateCache.clear();
+
+  for (size_t i = 0, n = _bones.size(); i < n; ++i) {
+    Bone *bone = _bones[i];
+    bone->_sorted = bone->_data.isSkinRequired();
+    bone->_active = !bone->_sorted;
+  }
+
+  if (_skin) {
+    Vector<BoneData *> &skinBones = _skin->getBones();
+    for (size_t i = 0, n = skinBones.size(); i < n; i++) {
+      Bone *bone = _bones[skinBones[i]->getIndex()];
+      do {
+        bone->_sorted = false;
+        bone->_active = true;
+        bone = bone->_parent;
+      } while (bone);
+    }
+  }
+
+  size_t ikCount = _ikConstraints.size();
+  size_t transformCount = _transformConstraints.size();
+  size_t pathCount = _pathConstraints.size();
+  size_t physicsCount = _physicsConstraints.size();
+  size_t constraintCount = ikCount + transformCount + pathCount + physicsCount;
+
+  size_t i = 0;
 continue_outer:
 continue_outer:
-	for (; i < constraintCount; ++i) {
-		for (size_t ii = 0; ii < ikCount; ++ii) {
-			IkConstraint *constraint = _ikConstraints[ii];
-			if (constraint->getData().getOrder() == i) {
-				sortIkConstraint(constraint);
-				i++;
-				goto continue_outer;
-			}
-		}
-
-		for (size_t ii = 0; ii < transformCount; ++ii) {
-			TransformConstraint *constraint = _transformConstraints[ii];
-			if (constraint->getData().getOrder() == i) {
-				sortTransformConstraint(constraint);
-				i++;
-				goto continue_outer;
-			}
-		}
-
-		for (size_t ii = 0; ii < pathCount; ++ii) {
-			PathConstraint *constraint = _pathConstraints[ii];
-			if (constraint->getData().getOrder() == i) {
-				sortPathConstraint(constraint);
-				i++;
-				goto continue_outer;
-			}
-		}
-
-		for (size_t ii = 0; ii < physicsCount; ++ii) {
-			PhysicsConstraint *constraint = _physicsConstraints[ii];
-			if (constraint->getData().getOrder() == i) {
-				sortPhysicsConstraint(constraint);
-				i++;
-				goto continue_outer;
-			}
-		}
-	}
-
-	size_t n = _bones.size();
-	for (i = 0; i < n; ++i) {
-		sortBone(_bones[i]);
-	}
+  for (; i < constraintCount; ++i) {
+    for (size_t ii = 0; ii < ikCount; ++ii) {
+      IkConstraint *constraint = _ikConstraints[ii];
+      if (constraint->getData().getOrder() == i) {
+        sortIkConstraint(constraint);
+        i++;
+        goto continue_outer;
+      }
+    }
+
+    for (size_t ii = 0; ii < transformCount; ++ii) {
+      TransformConstraint *constraint = _transformConstraints[ii];
+      if (constraint->getData().getOrder() == i) {
+        sortTransformConstraint(constraint);
+        i++;
+        goto continue_outer;
+      }
+    }
+
+    for (size_t ii = 0; ii < pathCount; ++ii) {
+      PathConstraint *constraint = _pathConstraints[ii];
+      if (constraint->getData().getOrder() == i) {
+        sortPathConstraint(constraint);
+        i++;
+        goto continue_outer;
+      }
+    }
+
+    for (size_t ii = 0; ii < physicsCount; ++ii) {
+      PhysicsConstraint *constraint = _physicsConstraints[ii];
+      if (constraint->getData().getOrder() == i) {
+        sortPhysicsConstraint(constraint);
+        i++;
+        goto continue_outer;
+      }
+    }
+  }
+
+  size_t n = _bones.size();
+  for (i = 0; i < n; ++i) {
+    sortBone(_bones[i]);
+  }
 }
 }
 
 
 void Skeleton::printUpdateCache() {
 void Skeleton::printUpdateCache() {
-	for (size_t i = 0; i < _updateCache.size(); i++) {
-		Updatable *updatable = _updateCache[i];
-		if (updatable->getRTTI().isExactly(Bone::rtti)) {
-			printf("bone %s\n", ((Bone *) updatable)->getData().getName().buffer());
-		} else if (updatable->getRTTI().isExactly(TransformConstraint::rtti)) {
-			printf("transform constraint %s\n", ((TransformConstraint *) updatable)->getData().getName().buffer());
-		} else if (updatable->getRTTI().isExactly(IkConstraint::rtti)) {
-			printf("ik constraint %s\n", ((IkConstraint *) updatable)->getData().getName().buffer());
-		} else if (updatable->getRTTI().isExactly(PathConstraint::rtti)) {
-			printf("path constraint %s\n", ((PathConstraint *) updatable)->getData().getName().buffer());
-		} else if (updatable->getRTTI().isExactly(PhysicsConstraint::rtti)) {
-            printf("physics constraint %s\n", ((PhysicsConstraint *) updatable)->getData().getName().buffer());
-        }
-	}
+  for (size_t i = 0; i < _updateCache.size(); i++) {
+    Updatable *updatable = _updateCache[i];
+    if (updatable->getRTTI().isExactly(Bone::rtti)) {
+      printf("bone %s\n", ((Bone *)updatable)->getData().getName().buffer());
+    } else if (updatable->getRTTI().isExactly(TransformConstraint::rtti)) {
+      printf("transform constraint %s\n",
+             ((TransformConstraint *)updatable)->getData().getName().buffer());
+    } else if (updatable->getRTTI().isExactly(IkConstraint::rtti)) {
+      printf("ik constraint %s\n",
+             ((IkConstraint *)updatable)->getData().getName().buffer());
+    } else if (updatable->getRTTI().isExactly(PathConstraint::rtti)) {
+      printf("path constraint %s\n",
+             ((PathConstraint *)updatable)->getData().getName().buffer());
+    } else if (updatable->getRTTI().isExactly(PhysicsConstraint::rtti)) {
+      printf("physics constraint %s\n",
+             ((PhysicsConstraint *)updatable)->getData().getName().buffer());
+    }
+  }
 }
 }
 
 
 void Skeleton::updateWorldTransform(Physics physics) {
 void Skeleton::updateWorldTransform(Physics physics) {
-	for (size_t i = 0, n = _bones.size(); i < n; i++) {
-		Bone *bone = _bones[i];
-		bone->_ax = bone->_x;
-		bone->_ay = bone->_y;
-		bone->_arotation = bone->_rotation;
-		bone->_ascaleX = bone->_scaleX;
-		bone->_ascaleY = bone->_scaleY;
-		bone->_ashearX = bone->_shearX;
-		bone->_ashearY = bone->_shearY;
-	}
-
-	for (size_t i = 0, n = _updateCache.size(); i < n; ++i) {
-		Updatable *updatable = _updateCache[i];
-		updatable->update(physics);
-	}
+  for (size_t i = 0, n = _bones.size(); i < n; i++) {
+    Bone *bone = _bones[i];
+    bone->_ax = bone->_x;
+    bone->_ay = bone->_y;
+    bone->_arotation = bone->_rotation;
+    bone->_ascaleX = bone->_scaleX;
+    bone->_ascaleY = bone->_scaleY;
+    bone->_ashearX = bone->_shearX;
+    bone->_ashearY = bone->_shearY;
+  }
+
+  for (size_t i = 0, n = _updateCache.size(); i < n; ++i) {
+    Updatable *updatable = _updateCache[i];
+    updatable->update(physics);
+  }
 }
 }
 
 
 void Skeleton::updateWorldTransform(Physics physics, Bone *parent) {
 void Skeleton::updateWorldTransform(Physics physics, Bone *parent) {
-	// Apply the parent bone transform to the root bone. The root bone always inherits scale, rotation and reflection.
-	Bone *rootBone = getRootBone();
-	float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d;
-	rootBone->_worldX = pa * _x + pb * _y + parent->_worldX;
-	rootBone->_worldY = pc * _x + pd * _y + parent->_worldY;
-
-	float rx = (rootBone->_rotation + rootBone->_shearX) * MathUtil::Deg_Rad;
-	float ry = (rootBone->_rotation + 90 + rootBone->_shearY) * MathUtil::Deg_Rad;
-	float la = MathUtil::cos(rx) * rootBone->_scaleX;
-	float lb = MathUtil::cos(ry) * rootBone->_scaleY;
-	float lc = MathUtil::sin(rx) * rootBone->_scaleX;
-	float ld = MathUtil::sin(ry) * rootBone->_scaleY;
-	rootBone->_a = (pa * la + pb * lc) * _scaleX;
-	rootBone->_b = (pa * lb + pb * ld) * _scaleX;
-	rootBone->_c = (pc * la + pd * lc) * _scaleY;
-	rootBone->_d = (pc * lb + pd * ld) * _scaleY;
-
-	// Update everything except root bone.
-	Bone *rb = getRootBone();
-	for (size_t i = 0, n = _updateCache.size(); i < n; i++) {
-		Updatable *updatable = _updateCache[i];
-		if (updatable != rb) updatable->update(physics);
-	}
+  // Apply the parent bone transform to the root bone. The root bone always
+  // inherits scale, rotation and reflection.
+  Bone *rootBone = getRootBone();
+  float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d;
+  rootBone->_worldX = pa * _x + pb * _y + parent->_worldX;
+  rootBone->_worldY = pc * _x + pd * _y + parent->_worldY;
+
+  float rx = (rootBone->_rotation + rootBone->_shearX) * MathUtil::Deg_Rad;
+  float ry = (rootBone->_rotation + 90 + rootBone->_shearY) * MathUtil::Deg_Rad;
+  float la = MathUtil::cos(rx) * rootBone->_scaleX;
+  float lb = MathUtil::cos(ry) * rootBone->_scaleY;
+  float lc = MathUtil::sin(rx) * rootBone->_scaleX;
+  float ld = MathUtil::sin(ry) * rootBone->_scaleY;
+  rootBone->_a = (pa * la + pb * lc) * _scaleX;
+  rootBone->_b = (pa * lb + pb * ld) * _scaleX;
+  rootBone->_c = (pc * la + pd * lc) * _scaleY;
+  rootBone->_d = (pc * lb + pd * ld) * _scaleY;
+
+  // Update everything except root bone.
+  Bone *rb = getRootBone();
+  for (size_t i = 0, n = _updateCache.size(); i < n; i++) {
+    Updatable *updatable = _updateCache[i];
+    if (updatable != rb)
+      updatable->update(physics);
+  }
 }
 }
 
 
 void Skeleton::setToSetupPose() {
 void Skeleton::setToSetupPose() {
-	setBonesToSetupPose();
-	setSlotsToSetupPose();
+  setBonesToSetupPose();
+  setSlotsToSetupPose();
 }
 }
 
 
 void Skeleton::setBonesToSetupPose() {
 void Skeleton::setBonesToSetupPose() {
-	for (size_t i = 0, n = _bones.size(); i < n; ++i) {
-		_bones[i]->setToSetupPose();
-	}
+  for (size_t i = 0, n = _bones.size(); i < n; ++i) {
+    _bones[i]->setToSetupPose();
+  }
 
 
-	for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) {
-		_ikConstraints[i]->setToSetupPose();
-	}
+  for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) {
+    _ikConstraints[i]->setToSetupPose();
+  }
 
 
-	for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) {
-		_transformConstraints[i]->setToSetupPose();
-	}
+  for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) {
+    _transformConstraints[i]->setToSetupPose();
+  }
 
 
-	for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) {
-		_pathConstraints[i]->setToSetupPose();
-	}
+  for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) {
+    _pathConstraints[i]->setToSetupPose();
+  }
 
 
-	for (size_t i = 0, n = _physicsConstraints.size(); i < n; ++i) {
-		_physicsConstraints[i]->setToSetupPose();
-	}
+  for (size_t i = 0, n = _physicsConstraints.size(); i < n; ++i) {
+    _physicsConstraints[i]->setToSetupPose();
+  }
 }
 }
 
 
 void Skeleton::setSlotsToSetupPose() {
 void Skeleton::setSlotsToSetupPose() {
-	_drawOrder.clear();
-	for (size_t i = 0, n = _slots.size(); i < n; ++i) {
-		_drawOrder.add(_slots[i]);
-	}
+  _drawOrder.clear();
+  for (size_t i = 0, n = _slots.size(); i < n; ++i) {
+    _drawOrder.add(_slots[i]);
+  }
 
 
-	for (size_t i = 0, n = _slots.size(); i < n; ++i) {
-		_slots[i]->setToSetupPose();
-	}
+  for (size_t i = 0, n = _slots.size(); i < n; ++i) {
+    _slots[i]->setToSetupPose();
+  }
 }
 }
 
 
 Bone *Skeleton::findBone(const String &boneName) {
 Bone *Skeleton::findBone(const String &boneName) {
-	return ContainerUtil::findWithDataName(_bones, boneName);
+  return ContainerUtil::findWithDataName(_bones, boneName);
 }
 }
 
 
 Slot *Skeleton::findSlot(const String &slotName) {
 Slot *Skeleton::findSlot(const String &slotName) {
-	return ContainerUtil::findWithDataName(_slots, slotName);
+  return ContainerUtil::findWithDataName(_slots, slotName);
 }
 }
 
 
 void Skeleton::setSkin(const String &skinName) {
 void Skeleton::setSkin(const String &skinName) {
-	Skin *foundSkin = skinName.isEmpty() ? NULL : _data->findSkin(skinName);
-	setSkin(foundSkin);
+  Skin *foundSkin = skinName.isEmpty() ? NULL : _data->findSkin(skinName);
+  setSkin(foundSkin);
 }
 }
 
 
 void Skeleton::setSkin(Skin *newSkin) {
 void Skeleton::setSkin(Skin *newSkin) {
-	if (_skin == newSkin) return;
-	if (newSkin != NULL) {
-		if (_skin != NULL) {
-			Skeleton &thisRef = *this;
-			newSkin->attachAll(thisRef, *_skin);
-		} else {
-			for (size_t i = 0, n = _slots.size(); i < n; ++i) {
-				Slot *slotP = _slots[i];
-				Slot &slot = *slotP;
-				const String &name = slot._data.getAttachmentName();
-				if (name.length() > 0) {
-					Attachment *attachment = newSkin->getAttachment(i, name);
-					if (attachment != NULL) {
-						slot.setAttachment(attachment);
-					}
-				}
-			}
-		}
-	}
+  if (_skin == newSkin)
+    return;
+  if (newSkin != NULL) {
+    if (_skin != NULL) {
+      Skeleton &thisRef = *this;
+      newSkin->attachAll(thisRef, *_skin);
+    } else {
+      for (size_t i = 0, n = _slots.size(); i < n; ++i) {
+        Slot *slotP = _slots[i];
+        Slot &slot = *slotP;
+        const String &name = slot._data.getAttachmentName();
+        if (name.length() > 0) {
+          Attachment *attachment = newSkin->getAttachment(i, name);
+          if (attachment != NULL) {
+            slot.setAttachment(attachment);
+          }
+        }
+      }
+    }
+  }
 
 
-	_skin = newSkin;
-	updateCache();
+  _skin = newSkin;
+  updateCache();
 }
 }
 
 
-Attachment *Skeleton::getAttachment(const String &slotName, const String &attachmentName) {
-	return getAttachment(_data->findSlot(slotName)->getIndex(), attachmentName);
+Attachment *Skeleton::getAttachment(const String &slotName,
+                                    const String &attachmentName) {
+  return getAttachment(_data->findSlot(slotName)->getIndex(), attachmentName);
 }
 }
 
 
-Attachment *Skeleton::getAttachment(int slotIndex, const String &attachmentName) {
-	if (attachmentName.isEmpty()) return NULL;
+Attachment *Skeleton::getAttachment(int slotIndex,
+                                    const String &attachmentName) {
+  if (attachmentName.isEmpty())
+    return NULL;
 
 
-	if (_skin != NULL) {
-		Attachment *attachment = _skin->getAttachment(slotIndex, attachmentName);
-		if (attachment != NULL) {
-			return attachment;
-		}
-	}
+  if (_skin != NULL) {
+    Attachment *attachment = _skin->getAttachment(slotIndex, attachmentName);
+    if (attachment != NULL) {
+      return attachment;
+    }
+  }
 
 
-	return _data->getDefaultSkin() != NULL ? _data->getDefaultSkin()->getAttachment(slotIndex, attachmentName) : NULL;
+  return _data->getDefaultSkin() != NULL
+             ? _data->getDefaultSkin()->getAttachment(slotIndex, attachmentName)
+             : NULL;
 }
 }
 
 
-void Skeleton::setAttachment(const String &slotName, const String &attachmentName) {
-	assert(slotName.length() > 0);
+void Skeleton::setAttachment(const String &slotName,
+                             const String &attachmentName) {
+  assert(slotName.length() > 0);
 
 
-	for (size_t i = 0, n = _slots.size(); i < n; ++i) {
-		Slot *slot = _slots[i];
-		if (slot->_data.getName() == slotName) {
-			Attachment *attachment = NULL;
-			if (attachmentName.length() > 0) {
-				attachment = getAttachment((int) i, attachmentName);
+  for (size_t i = 0, n = _slots.size(); i < n; ++i) {
+    Slot *slot = _slots[i];
+    if (slot->_data.getName() == slotName) {
+      Attachment *attachment = NULL;
+      if (attachmentName.length() > 0) {
+        attachment = getAttachment((int)i, attachmentName);
 
 
-				assert(attachment != NULL);
-			}
+        assert(attachment != NULL);
+      }
 
 
-			slot->setAttachment(attachment);
+      slot->setAttachment(attachment);
 
 
-			return;
-		}
-	}
+      return;
+    }
+  }
 
 
-	printf("Slot not found: %s", slotName.buffer());
+  printf("Slot not found: %s", slotName.buffer());
 
 
-	assert(false);
+  assert(false);
 }
 }
 
 
 IkConstraint *Skeleton::findIkConstraint(const String &constraintName) {
 IkConstraint *Skeleton::findIkConstraint(const String &constraintName) {
-	assert(constraintName.length() > 0);
+  assert(constraintName.length() > 0);
 
 
-	for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) {
-		IkConstraint *ikConstraint = _ikConstraints[i];
-		if (ikConstraint->_data.getName() == constraintName) {
-			return ikConstraint;
-		}
-	}
-	return NULL;
+  for (size_t i = 0, n = _ikConstraints.size(); i < n; ++i) {
+    IkConstraint *ikConstraint = _ikConstraints[i];
+    if (ikConstraint->_data.getName() == constraintName) {
+      return ikConstraint;
+    }
+  }
+  return NULL;
 }
 }
 
 
-TransformConstraint *Skeleton::findTransformConstraint(const String &constraintName) {
-	assert(constraintName.length() > 0);
+TransformConstraint *
+Skeleton::findTransformConstraint(const String &constraintName) {
+  assert(constraintName.length() > 0);
 
 
-	for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) {
-		TransformConstraint *transformConstraint = _transformConstraints[i];
-		if (transformConstraint->_data.getName() == constraintName) {
-			return transformConstraint;
-		}
-	}
+  for (size_t i = 0, n = _transformConstraints.size(); i < n; ++i) {
+    TransformConstraint *transformConstraint = _transformConstraints[i];
+    if (transformConstraint->_data.getName() == constraintName) {
+      return transformConstraint;
+    }
+  }
 
 
-	return NULL;
+  return NULL;
 }
 }
 
 
 PathConstraint *Skeleton::findPathConstraint(const String &constraintName) {
 PathConstraint *Skeleton::findPathConstraint(const String &constraintName) {
-	assert(constraintName.length() > 0);
+  assert(constraintName.length() > 0);
 
 
-	for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) {
-		PathConstraint *constraint = _pathConstraints[i];
-		if (constraint->_data.getName() == constraintName) {
-			return constraint;
-		}
-	}
+  for (size_t i = 0, n = _pathConstraints.size(); i < n; ++i) {
+    PathConstraint *constraint = _pathConstraints[i];
+    if (constraint->_data.getName() == constraintName) {
+      return constraint;
+    }
+  }
 
 
-	return NULL;
+  return NULL;
 }
 }
 
 
-void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector<float> &outVertexBuffer) {
-	float minX = FLT_MAX;
-	float minY = FLT_MAX;
-	float maxX = -FLT_MAX;
-	float maxY = -FLT_MAX;
+PhysicsConstraint *
+Skeleton::findPhysicsConstraint(const String &constraintName) {
+  assert(constraintName.length() > 0);
 
 
-	for (size_t i = 0; i < _drawOrder.size(); ++i) {
-		Slot *slot = _drawOrder[i];
-		if (!slot->_bone._active) continue;
-		size_t verticesLength = 0;
-		Attachment *attachment = slot->getAttachment();
+  for (size_t i = 0, n = _physicsConstraints.size(); i < n; ++i) {
+    PhysicsConstraint *constraint = _physicsConstraints[i];
+    if (constraint->_data.getName() == constraintName) {
+      return constraint;
+    }
+  }
 
 
-		if (attachment != NULL && attachment->getRTTI().instanceOf(RegionAttachment::rtti)) {
-			RegionAttachment *regionAttachment = static_cast<RegionAttachment *>(attachment);
+  return NULL;
+}
 
 
-			verticesLength = 8;
-			if (outVertexBuffer.size() < 8) {
-				outVertexBuffer.setSize(8, 0);
-			}
-			regionAttachment->computeWorldVertices(*slot, outVertexBuffer, 0);
-		} else if (attachment != NULL && attachment->getRTTI().instanceOf(MeshAttachment::rtti)) {
-			MeshAttachment *mesh = static_cast<MeshAttachment *>(attachment);
+void Skeleton::getBounds(float &outX, float &outY, float &outWidth,
+                         float &outHeight, Vector<float> &outVertexBuffer) {
+  float minX = FLT_MAX;
+  float minY = FLT_MAX;
+  float maxX = -FLT_MAX;
+  float maxY = -FLT_MAX;
 
 
-			verticesLength = mesh->getWorldVerticesLength();
-			if (outVertexBuffer.size() < verticesLength) {
-				outVertexBuffer.setSize(verticesLength, 0);
-			}
+  for (size_t i = 0; i < _drawOrder.size(); ++i) {
+    Slot *slot = _drawOrder[i];
+    if (!slot->_bone._active)
+      continue;
+    size_t verticesLength = 0;
+    Attachment *attachment = slot->getAttachment();
 
 
-			mesh->computeWorldVertices(*slot, 0, verticesLength, outVertexBuffer.buffer(), 0);
-		}
+    if (attachment != NULL &&
+        attachment->getRTTI().instanceOf(RegionAttachment::rtti)) {
+      RegionAttachment *regionAttachment =
+          static_cast<RegionAttachment *>(attachment);
 
 
-		for (size_t ii = 0; ii < verticesLength; ii += 2) {
-			float vx = outVertexBuffer[ii];
-			float vy = outVertexBuffer[ii + 1];
+      verticesLength = 8;
+      if (outVertexBuffer.size() < 8) {
+        outVertexBuffer.setSize(8, 0);
+      }
+      regionAttachment->computeWorldVertices(*slot, outVertexBuffer, 0);
+    } else if (attachment != NULL &&
+               attachment->getRTTI().instanceOf(MeshAttachment::rtti)) {
+      MeshAttachment *mesh = static_cast<MeshAttachment *>(attachment);
 
 
-			minX = MathUtil::min(minX, vx);
-			minY = MathUtil::min(minY, vy);
-			maxX = MathUtil::max(maxX, vx);
-			maxY = MathUtil::max(maxY, vy);
-		}
-	}
+      verticesLength = mesh->getWorldVerticesLength();
+      if (outVertexBuffer.size() < verticesLength) {
+        outVertexBuffer.setSize(verticesLength, 0);
+      }
 
 
-	outX = minX;
-	outY = minY;
-	outWidth = maxX - minX;
-	outHeight = maxY - minY;
-}
+      mesh->computeWorldVertices(*slot, 0, verticesLength,
+                                 outVertexBuffer.buffer(), 0);
+    }
 
 
-Bone *Skeleton::getRootBone() {
-	return _bones.size() == 0 ? NULL : _bones[0];
-}
+    for (size_t ii = 0; ii < verticesLength; ii += 2) {
+      float vx = outVertexBuffer[ii];
+      float vy = outVertexBuffer[ii + 1];
 
 
-SkeletonData *Skeleton::getData() {
-	return _data;
-}
+      minX = MathUtil::min(minX, vx);
+      minY = MathUtil::min(minY, vy);
+      maxX = MathUtil::max(maxX, vx);
+      maxY = MathUtil::max(maxY, vy);
+    }
+  }
 
 
-Vector<Bone *> &Skeleton::getBones() {
-	return _bones;
+  outX = minX;
+  outY = minY;
+  outWidth = maxX - minX;
+  outHeight = maxY - minY;
 }
 }
 
 
-Vector<Updatable *> &Skeleton::getUpdateCacheList() {
-	return _updateCache;
-}
+Bone *Skeleton::getRootBone() { return _bones.size() == 0 ? NULL : _bones[0]; }
 
 
-Vector<Slot *> &Skeleton::getSlots() {
-	return _slots;
-}
+SkeletonData *Skeleton::getData() { return _data; }
 
 
-Vector<Slot *> &Skeleton::getDrawOrder() {
-	return _drawOrder;
-}
+Vector<Bone *> &Skeleton::getBones() { return _bones; }
 
 
-Vector<IkConstraint *> &Skeleton::getIkConstraints() {
-	return _ikConstraints;
-}
+Vector<Updatable *> &Skeleton::getUpdateCacheList() { return _updateCache; }
+
+Vector<Slot *> &Skeleton::getSlots() { return _slots; }
+
+Vector<Slot *> &Skeleton::getDrawOrder() { return _drawOrder; }
+
+Vector<IkConstraint *> &Skeleton::getIkConstraints() { return _ikConstraints; }
 
 
 Vector<PathConstraint *> &Skeleton::getPathConstraints() {
 Vector<PathConstraint *> &Skeleton::getPathConstraints() {
-	return _pathConstraints;
+  return _pathConstraints;
 }
 }
 
 
 Vector<TransformConstraint *> &Skeleton::getTransformConstraints() {
 Vector<TransformConstraint *> &Skeleton::getTransformConstraints() {
-	return _transformConstraints;
+  return _transformConstraints;
 }
 }
 
 
 Vector<PhysicsConstraint *> &Skeleton::getPhysicsConstraints() {
 Vector<PhysicsConstraint *> &Skeleton::getPhysicsConstraints() {
-    return _physicsConstraints;
+  return _physicsConstraints;
 }
 }
 
 
-Skin *Skeleton::getSkin() {
-	return _skin;
-}
+Skin *Skeleton::getSkin() { return _skin; }
 
 
-Color &Skeleton::getColor() {
-	return _color;
-}
+Color &Skeleton::getColor() { return _color; }
 
 
 void Skeleton::setPosition(float x, float y) {
 void Skeleton::setPosition(float x, float y) {
-	_x = x;
-	_y = y;
+  _x = x;
+  _y = y;
 }
 }
 
 
-float Skeleton::getX() {
-	return _x;
-}
+float Skeleton::getX() { return _x; }
 
 
-void Skeleton::setX(float inValue) {
-	_x = inValue;
-}
+void Skeleton::setX(float inValue) { _x = inValue; }
 
 
-float Skeleton::getY() {
-	return _y;
-}
+float Skeleton::getY() { return _y; }
 
 
-void Skeleton::setY(float inValue) {
-	_y = inValue;
-}
+void Skeleton::setY(float inValue) { _y = inValue; }
 
 
-float Skeleton::getScaleX() {
-	return _scaleX;
-}
+float Skeleton::getScaleX() { return _scaleX; }
 
 
-void Skeleton::setScaleX(float inValue) {
-	_scaleX = inValue;
-}
+void Skeleton::setScaleX(float inValue) { _scaleX = inValue; }
 
 
-float Skeleton::getScaleY() {
-	return _scaleY * (Bone::isYDown() ? -1 : 1);
-}
+float Skeleton::getScaleY() { return _scaleY * (Bone::isYDown() ? -1 : 1); }
 
 
-void Skeleton::setScaleY(float inValue) {
-	_scaleY = inValue;
-}
+void Skeleton::setScaleY(float inValue) { _scaleY = inValue; }
 
 
 void Skeleton::sortIkConstraint(IkConstraint *constraint) {
 void Skeleton::sortIkConstraint(IkConstraint *constraint) {
-	constraint->_active = constraint->_target->_active && (!constraint->_data.isSkinRequired() ||
-														   (_skin && _skin->_constraints.contains(&constraint->_data)));
-	if (!constraint->_active) return;
+  constraint->_active =
+      constraint->_target->_active &&
+      (!constraint->_data.isSkinRequired() ||
+       (_skin && _skin->_constraints.contains(&constraint->_data)));
+  if (!constraint->_active)
+    return;
 
 
-	Bone *target = constraint->getTarget();
-	sortBone(target);
+  Bone *target = constraint->getTarget();
+  sortBone(target);
 
 
-	Vector<Bone *> &constrained = constraint->getBones();
-	Bone *parent = constrained[0];
-	sortBone(parent);
+  Vector<Bone *> &constrained = constraint->getBones();
+  Bone *parent = constrained[0];
+  sortBone(parent);
 
 
-	if (constrained.size() == 1) {
-		_updateCache.add(constraint);
-		sortReset(parent->_children);
-	} else {
-		Bone *child = constrained[constrained.size() - 1];
-		sortBone(child);
+  if (constrained.size() == 1) {
+    _updateCache.add(constraint);
+    sortReset(parent->_children);
+  } else {
+    Bone *child = constrained[constrained.size() - 1];
+    sortBone(child);
 
 
-		_updateCache.add(constraint);
+    _updateCache.add(constraint);
 
 
-		sortReset(parent->_children);
-		child->_sorted = true;
-	}
+    sortReset(parent->_children);
+    child->_sorted = true;
+  }
 }
 }
 
 
 void Skeleton::sortPathConstraint(PathConstraint *constraint) {
 void Skeleton::sortPathConstraint(PathConstraint *constraint) {
-	constraint->_active = constraint->_target->_bone._active && (!constraint->_data.isSkinRequired() || (_skin &&
-																										 _skin->_constraints.contains(
-																												 &constraint->_data)));
-	if (!constraint->_active) return;
-
-	Slot *slot = constraint->getTarget();
-	int slotIndex = slot->getData().getIndex();
-	Bone &slotBone = slot->getBone();
-	if (_skin != NULL) sortPathConstraintAttachment(_skin, slotIndex, slotBone);
-	if (_data->_defaultSkin != NULL && _data->_defaultSkin != _skin)
-		sortPathConstraintAttachment(_data->_defaultSkin, slotIndex, slotBone);
-	for (size_t ii = 0, nn = _data->_skins.size(); ii < nn; ii++)
-		sortPathConstraintAttachment(_data->_skins[ii], slotIndex, slotBone);
-
-	Attachment *attachment = slot->getAttachment();
-	if (attachment != NULL && attachment->getRTTI().instanceOf(PathAttachment::rtti))
-		sortPathConstraintAttachment(attachment, slotBone);
-
-	Vector<Bone *> &constrained = constraint->getBones();
-	size_t boneCount = constrained.size();
-	for (size_t i = 0; i < boneCount; ++i) {
-		sortBone(constrained[i]);
-	}
-
-	_updateCache.add(constraint);
-
-	for (size_t i = 0; i < boneCount; i++)
-		sortReset(constrained[i]->getChildren());
-	for (size_t i = 0; i < boneCount; i++)
-		constrained[i]->_sorted = true;
+  constraint->_active =
+      constraint->_target->_bone._active &&
+      (!constraint->_data.isSkinRequired() ||
+       (_skin && _skin->_constraints.contains(&constraint->_data)));
+  if (!constraint->_active)
+    return;
+
+  Slot *slot = constraint->getTarget();
+  int slotIndex = slot->getData().getIndex();
+  Bone &slotBone = slot->getBone();
+  if (_skin != NULL)
+    sortPathConstraintAttachment(_skin, slotIndex, slotBone);
+  if (_data->_defaultSkin != NULL && _data->_defaultSkin != _skin)
+    sortPathConstraintAttachment(_data->_defaultSkin, slotIndex, slotBone);
+  for (size_t ii = 0, nn = _data->_skins.size(); ii < nn; ii++)
+    sortPathConstraintAttachment(_data->_skins[ii], slotIndex, slotBone);
+
+  Attachment *attachment = slot->getAttachment();
+  if (attachment != NULL &&
+      attachment->getRTTI().instanceOf(PathAttachment::rtti))
+    sortPathConstraintAttachment(attachment, slotBone);
+
+  Vector<Bone *> &constrained = constraint->getBones();
+  size_t boneCount = constrained.size();
+  for (size_t i = 0; i < boneCount; ++i) {
+    sortBone(constrained[i]);
+  }
+
+  _updateCache.add(constraint);
+
+  for (size_t i = 0; i < boneCount; i++)
+    sortReset(constrained[i]->getChildren());
+  for (size_t i = 0; i < boneCount; i++)
+    constrained[i]->_sorted = true;
 }
 }
 
 
 void Skeleton::sortTransformConstraint(TransformConstraint *constraint) {
 void Skeleton::sortTransformConstraint(TransformConstraint *constraint) {
-	constraint->_active = constraint->_target->_active && (!constraint->_data.isSkinRequired() ||
-														   (_skin && _skin->_constraints.contains(&constraint->_data)));
-	if (!constraint->_active) return;
-
-	sortBone(constraint->getTarget());
-
-	Vector<Bone *> &constrained = constraint->getBones();
-	size_t boneCount = constrained.size();
-	if (constraint->_data.isLocal()) {
-		for (size_t i = 0; i < boneCount; i++) {
-			Bone *child = constrained[i];
-			sortBone(child->getParent());
-			sortBone(child);
-		}
-	} else {
-		for (size_t i = 0; i < boneCount; ++i) {
-			sortBone(constrained[i]);
-		}
-	}
-
-	_updateCache.add(constraint);
-
-	for (size_t i = 0; i < boneCount; ++i)
-		sortReset(constrained[i]->getChildren());
-	for (size_t i = 0; i < boneCount; ++i)
-		constrained[i]->_sorted = true;
+  constraint->_active =
+      constraint->_target->_active &&
+      (!constraint->_data.isSkinRequired() ||
+       (_skin && _skin->_constraints.contains(&constraint->_data)));
+  if (!constraint->_active)
+    return;
+
+  sortBone(constraint->getTarget());
+
+  Vector<Bone *> &constrained = constraint->getBones();
+  size_t boneCount = constrained.size();
+  if (constraint->_data.isLocal()) {
+    for (size_t i = 0; i < boneCount; i++) {
+      Bone *child = constrained[i];
+      sortBone(child->getParent());
+      sortBone(child);
+    }
+  } else {
+    for (size_t i = 0; i < boneCount; ++i) {
+      sortBone(constrained[i]);
+    }
+  }
+
+  _updateCache.add(constraint);
+
+  for (size_t i = 0; i < boneCount; ++i)
+    sortReset(constrained[i]->getChildren());
+  for (size_t i = 0; i < boneCount; ++i)
+    constrained[i]->_sorted = true;
 }
 }
 
 
 void Skeleton::sortPhysicsConstraint(PhysicsConstraint *constraint) {
 void Skeleton::sortPhysicsConstraint(PhysicsConstraint *constraint) {
-	Bone *bone = constraint->getBone();
-	constraint->_active = bone->_active && (!constraint->_data.isSkinRequired() ||
-											(_skin && _skin->_constraints.contains(&constraint->_data)));
-	if (!constraint->_active) return;
-
-	sortBone(bone);
-	_updateCache.add(constraint);
-	sortReset(bone->getChildren());
-	bone->_sorted = true;
-}
-
-void Skeleton::sortPathConstraintAttachment(Skin *skin, size_t slotIndex, Bone &slotBone) {
-	Skin::AttachmentMap::Entries attachments = skin->getAttachments();
-
-	while (attachments.hasNext()) {
-		Skin::AttachmentMap::Entry entry = attachments.next();
-		if (entry._slotIndex == slotIndex) {
-			Attachment *value = entry._attachment;
-			sortPathConstraintAttachment(value, slotBone);
-		}
-	}
-}
-
-void Skeleton::sortPathConstraintAttachment(Attachment *attachment, Bone &slotBone) {
-	if (attachment == NULL || !attachment->getRTTI().instanceOf(PathAttachment::rtti)) return;
-	Vector<int> &pathBones = static_cast<PathAttachment *>(attachment)->getBones();
-	if (pathBones.size() == 0)
-		sortBone(&slotBone);
-	else {
-		for (size_t i = 0, n = pathBones.size(); i < n;) {
-			size_t nn = pathBones[i++];
-			nn += i;
-			while (i < nn) {
-				sortBone(_bones[pathBones[i++]]);
-			}
-		}
-	}
+  Bone *bone = constraint->getBone();
+  constraint->_active =
+      bone->_active &&
+      (!constraint->_data.isSkinRequired() ||
+       (_skin && _skin->_constraints.contains(&constraint->_data)));
+  if (!constraint->_active)
+    return;
+
+  sortBone(bone);
+  _updateCache.add(constraint);
+  sortReset(bone->getChildren());
+  bone->_sorted = true;
+}
+
+void Skeleton::sortPathConstraintAttachment(Skin *skin, size_t slotIndex,
+                                            Bone &slotBone) {
+  Skin::AttachmentMap::Entries attachments = skin->getAttachments();
+
+  while (attachments.hasNext()) {
+    Skin::AttachmentMap::Entry entry = attachments.next();
+    if (entry._slotIndex == slotIndex) {
+      Attachment *value = entry._attachment;
+      sortPathConstraintAttachment(value, slotBone);
+    }
+  }
+}
+
+void Skeleton::sortPathConstraintAttachment(Attachment *attachment,
+                                            Bone &slotBone) {
+  if (attachment == NULL ||
+      !attachment->getRTTI().instanceOf(PathAttachment::rtti))
+    return;
+  Vector<int> &pathBones =
+      static_cast<PathAttachment *>(attachment)->getBones();
+  if (pathBones.size() == 0)
+    sortBone(&slotBone);
+  else {
+    for (size_t i = 0, n = pathBones.size(); i < n;) {
+      size_t nn = pathBones[i++];
+      nn += i;
+      while (i < nn) {
+        sortBone(_bones[pathBones[i++]]);
+      }
+    }
+  }
 }
 }
 
 
 void Skeleton::sortBone(Bone *bone) {
 void Skeleton::sortBone(Bone *bone) {
-	if (bone->_sorted) return;
-	Bone *parent = bone->_parent;
-	if (parent != NULL) sortBone(parent);
-	bone->_sorted = true;
-	_updateCache.add(bone);
+  if (bone->_sorted)
+    return;
+  Bone *parent = bone->_parent;
+  if (parent != NULL)
+    sortBone(parent);
+  bone->_sorted = true;
+  _updateCache.add(bone);
 }
 }
 
 
 void Skeleton::sortReset(Vector<Bone *> &bones) {
 void Skeleton::sortReset(Vector<Bone *> &bones) {
-	for (size_t i = 0, n = bones.size(); i < n; ++i) {
-		Bone *bone = bones[i];
-		if (!bone->_active) continue;
-		if (bone->_sorted) sortReset(bone->getChildren());
-		bone->_sorted = false;
-	}
+  for (size_t i = 0, n = bones.size(); i < n; ++i) {
+    Bone *bone = bones[i];
+    if (!bone->_active)
+      continue;
+    if (bone->_sorted)
+      sortReset(bone->getChildren());
+    bone->_sorted = false;
+  }
 }
 }
 
 
-float Skeleton::getTime() {
-	return _time;
-}
+float Skeleton::getTime() { return _time; }
 
 
-void Skeleton::setTime(float time) {
-	_time = time;
-}
+void Skeleton::setTime(float time) { _time = time; }
 
 
-void Skeleton::update(float delta) {
-	_time += delta;
-}
+void Skeleton::update(float delta) { _time += delta; }
 
 
 void Skeleton::physicsTranslate(float x, float y) {
 void Skeleton::physicsTranslate(float x, float y) {
-	for (int i = 0; i < (int) _physicsConstraints.size(); i++) {
-		_physicsConstraints[i]->translate(x, y);
-	}
+  for (int i = 0; i < (int)_physicsConstraints.size(); i++) {
+    _physicsConstraints[i]->translate(x, y);
+  }
 }
 }
 
 
 void Skeleton::physicsRotate(float x, float y, float degrees) {
 void Skeleton::physicsRotate(float x, float y, float degrees) {
-	for (int i = 0; i < (int) _physicsConstraints.size(); i++) {
-		_physicsConstraints[i]->rotate(x, y, degrees);
-	}
+  for (int i = 0; i < (int)_physicsConstraints.size(); i++) {
+    _physicsConstraints[i]->rotate(x, y, degrees);
+  }
 }
 }

+ 20 - 20
spine-godot/spine_godot/SpineAnimationTrack.cpp

@@ -62,10 +62,10 @@ void SpineAnimationTrack::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_time_scale"), &SpineAnimationTrack::get_time_scale);
 	ClassDB::bind_method(D_METHOD("get_time_scale"), &SpineAnimationTrack::get_time_scale);
 	ClassDB::bind_method(D_METHOD("set_alpha", "alpha"), &SpineAnimationTrack::set_alpha);
 	ClassDB::bind_method(D_METHOD("set_alpha", "alpha"), &SpineAnimationTrack::set_alpha);
 	ClassDB::bind_method(D_METHOD("get_alpha"), &SpineAnimationTrack::get_alpha);
 	ClassDB::bind_method(D_METHOD("get_alpha"), &SpineAnimationTrack::get_alpha);
-	ClassDB::bind_method(D_METHOD("set_attachment_threshold", "attachment_threshold"), &SpineAnimationTrack::set_attachment_threshold);
-	ClassDB::bind_method(D_METHOD("get_attachment_threshold"), &SpineAnimationTrack::get_attachment_threshold);
-	ClassDB::bind_method(D_METHOD("set_draw_order_threshold", "draw_order_threshold"), &SpineAnimationTrack::set_draw_order_threshold);
-	ClassDB::bind_method(D_METHOD("get_draw_order_threshold"), &SpineAnimationTrack::get_draw_order_threshold);
+	ClassDB::bind_method(D_METHOD("set_mix_attachment_threshold", "mix_attachment_threshold"), &SpineAnimationTrack::set_mix_attachment_threshold);
+	ClassDB::bind_method(D_METHOD("get_mix_attachment_threshold"), &SpineAnimationTrack::get_mix_attachment_threshold);
+	ClassDB::bind_method(D_METHOD("set_mix_draw_order_threshold", "mix_draw_order_threshold"), &SpineAnimationTrack::set_mix_draw_order_threshold);
+	ClassDB::bind_method(D_METHOD("get_mix_draw_order_threshold"), &SpineAnimationTrack::get_mix_draw_order_threshold);
 	ClassDB::bind_method(D_METHOD("set_mix_blend", "mix_blend"), &SpineAnimationTrack::set_mix_blend);
 	ClassDB::bind_method(D_METHOD("set_mix_blend", "mix_blend"), &SpineAnimationTrack::set_mix_blend);
 	ClassDB::bind_method(D_METHOD("get_mix_blend"), &SpineAnimationTrack::get_mix_blend);
 	ClassDB::bind_method(D_METHOD("get_mix_blend"), &SpineAnimationTrack::get_mix_blend);
 	ClassDB::bind_method(D_METHOD("set_blend_tree_mode", "blend_tree_mode_enabled"), &SpineAnimationTrack::set_blend_tree_mode);
 	ClassDB::bind_method(D_METHOD("set_blend_tree_mode", "blend_tree_mode_enabled"), &SpineAnimationTrack::set_blend_tree_mode);
@@ -100,8 +100,8 @@ SpineAnimationTrack::SpineAnimationTrack() : loop(false),
 											 shortest_rotation(false),
 											 shortest_rotation(false),
 											 time_scale(1),
 											 time_scale(1),
 											 alpha(1),
 											 alpha(1),
-											 attachment_threshold(0),
-											 draw_order_threshold(0),
+											 mix_attachment_threshold(0),
+											 mix_draw_order_threshold(0),
 											 mix_blend(SpineConstant::MixBlend_Replace),
 											 mix_blend(SpineConstant::MixBlend_Replace),
 											 blend_tree_mode(false),
 											 blend_tree_mode(false),
 											 debug(false),
 											 debug(false),
@@ -301,8 +301,8 @@ void SpineAnimationTrack::update_animation_state(const Variant &variant_sprite)
 					entry->setShortestRotation(shortest_rotation);
 					entry->setShortestRotation(shortest_rotation);
 					entry->setTimeScale(time_scale);
 					entry->setTimeScale(time_scale);
 					entry->setAlpha(alpha);
 					entry->setAlpha(alpha);
-					entry->setAttachmentThreshold(attachment_threshold);
-					entry->setDrawOrderThreshold(draw_order_threshold);
+					entry->setMixAttachmentThreshold(mix_attachment_threshold);
+					entry->setMixDrawOrderThreshold(mix_draw_order_threshold);
 					entry->setMixBlend((spine::MixBlend) mix_blend);
 					entry->setMixBlend((spine::MixBlend) mix_blend);
 
 
 					if (debug) print_line(String("Setting animation {0} with mix_duration {1} on track {2} on {3}").format(varray(animation_name, mix_duration, track_index, sprite->get_name())).utf8().ptr());
 					if (debug) print_line(String("Setting animation {0} with mix_duration {1} on track {2} on {3}").format(varray(animation_name, mix_duration, track_index, sprite->get_name())).utf8().ptr());
@@ -406,8 +406,8 @@ void SpineAnimationTrack::update_animation_state(const Variant &variant_sprite)
 		entry->setReverse(reverse);
 		entry->setReverse(reverse);
 		entry->setShortestRotation(shortest_rotation);
 		entry->setShortestRotation(shortest_rotation);
 		entry->setAlpha(alpha);
 		entry->setAlpha(alpha);
-		entry->setAttachmentThreshold(attachment_threshold);
-		entry->setDrawOrderThreshold(draw_order_threshold);
+		entry->setMixAttachmentThreshold(mix_attachment_threshold);
+		entry->setMixDrawOrderThreshold(mix_draw_order_threshold);
 		entry->setMixBlend((spine::MixBlend) mix_blend);
 		entry->setMixBlend((spine::MixBlend) mix_blend);
 #endif
 #endif
 	} else {
 	} else {
@@ -426,8 +426,8 @@ void SpineAnimationTrack::update_animation_state(const Variant &variant_sprite)
 					entry->setShortestRotation(shortest_rotation);
 					entry->setShortestRotation(shortest_rotation);
 					entry->setTimeScale(time_scale);
 					entry->setTimeScale(time_scale);
 					entry->setAlpha(alpha);
 					entry->setAlpha(alpha);
-					entry->setAttachmentThreshold(attachment_threshold);
-					entry->setDrawOrderThreshold(draw_order_threshold);
+					entry->setMixAttachmentThreshold(mix_attachment_threshold);
+					entry->setMixDrawOrderThreshold(mix_draw_order_threshold);
 					entry->setMixBlend((spine::MixBlend) mix_blend);
 					entry->setMixBlend((spine::MixBlend) mix_blend);
 
 
 					if (debug) print_line(String("Setting animation {0} with mix_duration {1} on track {2} on {3}").format(varray(animation_name, mix_duration, track_index, sprite->get_name())).utf8().ptr());
 					if (debug) print_line(String("Setting animation {0} with mix_duration {1} on track {2} on {3}").format(varray(animation_name, mix_duration, track_index, sprite->get_name())).utf8().ptr());
@@ -515,20 +515,20 @@ float SpineAnimationTrack::get_alpha() {
 	return alpha;
 	return alpha;
 }
 }
 
 
-void SpineAnimationTrack::set_attachment_threshold(float _attachment_threshold) {
-	attachment_threshold = _attachment_threshold;
+void SpineAnimationTrack::set_mix_attachment_threshold(float _mix_attachment_threshold) {
+	mix_attachment_threshold = _mix_attachment_threshold;
 }
 }
 
 
-float SpineAnimationTrack::get_attachment_threshold() {
-	return attachment_threshold;
+float SpineAnimationTrack::get_mix_attachment_threshold() {
+	return mix_attachment_threshold;
 }
 }
 
 
-void SpineAnimationTrack::set_draw_order_threshold(float _draw_order_threshold) {
-	draw_order_threshold = _draw_order_threshold;
+void SpineAnimationTrack::set_mix_draw_order_threshold(float _mix_draw_order_threshold) {
+	mix_draw_order_threshold = _mix_draw_order_threshold;
 }
 }
 
 
-float SpineAnimationTrack::get_draw_order_threshold() {
-	return draw_order_threshold;
+float SpineAnimationTrack::get_mix_draw_order_threshold() {
+	return mix_draw_order_threshold;
 }
 }
 
 
 void SpineAnimationTrack::set_mix_blend(SpineConstant::MixBlend _blend) {
 void SpineAnimationTrack::set_mix_blend(SpineConstant::MixBlend _blend) {

+ 6 - 6
spine-godot/spine_godot/SpineAnimationTrack.h

@@ -50,8 +50,8 @@ protected:
 	bool shortest_rotation;
 	bool shortest_rotation;
 	float time_scale;
 	float time_scale;
 	float alpha;
 	float alpha;
-	float attachment_threshold;
-	float draw_order_threshold;
+	float mix_attachment_threshold;
+	float mix_draw_order_threshold;
 	SpineConstant::MixBlend mix_blend;
 	SpineConstant::MixBlend mix_blend;
 	bool blend_tree_mode;
 	bool blend_tree_mode;
 	bool debug;
 	bool debug;
@@ -113,13 +113,13 @@ public:
 
 
 	float get_alpha();
 	float get_alpha();
 
 
-	void set_attachment_threshold(float _attachment_threshold);
+	void set_mix_attachment_threshold(float _mix_attachment_threshold);
 
 
-	float get_attachment_threshold();
+	float get_mix_attachment_threshold();
 
 
-	void set_draw_order_threshold(float _draw_order_threshold);
+	void set_mix_draw_order_threshold(float _mix_draw_order_threshold);
 
 
-	float get_draw_order_threshold();
+	float get_mix_draw_order_threshold();
 
 
 	void set_mix_blend(SpineConstant::MixBlend _blend);
 	void set_mix_blend(SpineConstant::MixBlend _blend);
 
 

+ 29 - 0
spine-godot/spine_godot/SpineBone.cpp

@@ -28,6 +28,7 @@
  *****************************************************************************/
  *****************************************************************************/
 
 
 #include "SpineBone.h"
 #include "SpineBone.h"
+#include "SpineConstant.h"
 #include "SpineSprite.h"
 #include "SpineSprite.h"
 #include "SpineSkeleton.h"
 #include "SpineSkeleton.h"
 #include "SpineCommon.h"
 #include "SpineCommon.h"
@@ -36,7 +37,9 @@ void SpineBone::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineBone::update_world_transform);
 	ClassDB::bind_method(D_METHOD("update_world_transform"), &SpineBone::update_world_transform);
 	ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineBone::set_to_setup_pose);
 	ClassDB::bind_method(D_METHOD("set_to_setup_pose"), &SpineBone::set_to_setup_pose);
 	ClassDB::bind_method(D_METHOD("world_to_local", "world_position"), &SpineBone::world_to_local);
 	ClassDB::bind_method(D_METHOD("world_to_local", "world_position"), &SpineBone::world_to_local);
+	ClassDB::bind_method(D_METHOD("world_to_parent", "world_position"), &SpineBone::world_to_parent);
 	ClassDB::bind_method(D_METHOD("local_to_world", "local_position"), &SpineBone::local_to_world);
 	ClassDB::bind_method(D_METHOD("local_to_world", "local_position"), &SpineBone::local_to_world);
+	ClassDB::bind_method(D_METHOD("parent_to_world", "local_position"), &SpineBone::parent_to_world);
 	ClassDB::bind_method(D_METHOD("world_to_local_rotation", "world_rotation"), &SpineBone::world_to_local_rotation);
 	ClassDB::bind_method(D_METHOD("world_to_local_rotation", "world_rotation"), &SpineBone::world_to_local_rotation);
 	ClassDB::bind_method(D_METHOD("local_to_world_rotation", "local_rotation"), &SpineBone::local_to_world_rotation);
 	ClassDB::bind_method(D_METHOD("local_to_world_rotation", "local_rotation"), &SpineBone::local_to_world_rotation);
 	ClassDB::bind_method(D_METHOD("rotate_world"), &SpineBone::rotate_world);
 	ClassDB::bind_method(D_METHOD("rotate_world"), &SpineBone::rotate_world);
@@ -91,6 +94,8 @@ void SpineBone::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_world_scale_y"), &SpineBone::get_world_scale_y);
 	ClassDB::bind_method(D_METHOD("get_world_scale_y"), &SpineBone::get_world_scale_y);
 	ClassDB::bind_method(D_METHOD("is_active"), &SpineBone::is_active);
 	ClassDB::bind_method(D_METHOD("is_active"), &SpineBone::is_active);
 	ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineBone::set_active);
 	ClassDB::bind_method(D_METHOD("set_active", "v"), &SpineBone::set_active);
+	ClassDB::bind_method(D_METHOD("set_inherit", "v"), &SpineBone::set_inherit);
+	ClassDB::bind_method(D_METHOD("get_inherit"), &SpineBone::get_inherit);
 	ClassDB::bind_method(D_METHOD("get_transform"), &SpineBone::get_transform);
 	ClassDB::bind_method(D_METHOD("get_transform"), &SpineBone::get_transform);
 	ClassDB::bind_method(D_METHOD("set_transform", "local_transform"), &SpineBone::set_transform);
 	ClassDB::bind_method(D_METHOD("set_transform", "local_transform"), &SpineBone::set_transform);
 	ClassDB::bind_method(D_METHOD("get_global_transform"), &SpineBone::get_global_transform);
 	ClassDB::bind_method(D_METHOD("get_global_transform"), &SpineBone::get_global_transform);
@@ -114,6 +119,13 @@ Vector2 SpineBone::world_to_local(Vector2 world_position) {
 	return Vector2(x, y);
 	return Vector2(x, y);
 }
 }
 
 
+Vector2 SpineBone::world_to_parent(Vector2 world_position) {
+	SPINE_CHECK(get_spine_object(), Vector2())
+	float x, y;
+	get_spine_object()->worldToParent(world_position.x, world_position.y, x, y);
+	return Vector2(x, y);
+}
+
 Vector2 SpineBone::local_to_world(Vector2 local_position) {
 Vector2 SpineBone::local_to_world(Vector2 local_position) {
 	SPINE_CHECK(get_spine_object(), Vector2())
 	SPINE_CHECK(get_spine_object(), Vector2())
 	float x, y;
 	float x, y;
@@ -121,6 +133,13 @@ Vector2 SpineBone::local_to_world(Vector2 local_position) {
 	return Vector2(x, y);
 	return Vector2(x, y);
 }
 }
 
 
+Vector2 SpineBone::parent_to_world(Vector2 local_position) {
+	SPINE_CHECK(get_spine_object(), Vector2())
+	float x, y;
+	get_spine_object()->parentToWorld(local_position.x, local_position.y, x, y);
+	return Vector2(x, y);
+}
+
 float SpineBone::world_to_local_rotation(float world_rotation) {
 float SpineBone::world_to_local_rotation(float world_rotation) {
 	SPINE_CHECK(get_spine_object(), 0)
 	SPINE_CHECK(get_spine_object(), 0)
 	return get_spine_object()->worldToLocalRotation(world_rotation);
 	return get_spine_object()->worldToLocalRotation(world_rotation);
@@ -407,6 +426,16 @@ void SpineBone::set_active(bool v) {
 	get_spine_object()->setActive(v);
 	get_spine_object()->setActive(v);
 }
 }
 
 
+SpineConstant::Inherit SpineBone::get_inherit() {
+	SPINE_CHECK(get_spine_object(), SpineConstant::Inherit_Normal);
+	return (SpineConstant::Inherit) get_spine_object()->getInherit();
+}
+
+void SpineBone::set_inherit(SpineConstant::Inherit inherit) {
+	SPINE_CHECK(get_spine_object(), );
+	get_spine_object()->setInherit((spine::Inherit) inherit);
+}
+
 Transform2D SpineBone::get_transform() {
 Transform2D SpineBone::get_transform() {
 	SPINE_CHECK(get_spine_object(), Transform2D())
 	SPINE_CHECK(get_spine_object(), Transform2D())
 	Transform2D transform;
 	Transform2D transform;

+ 9 - 0
spine-godot/spine_godot/SpineBone.h

@@ -31,6 +31,7 @@
 
 
 #include "SpineCommon.h"
 #include "SpineCommon.h"
 #include "SpineBoneData.h"
 #include "SpineBoneData.h"
+#include "SpineConstant.h"
 #include "scene/2d/node_2d.h"
 #include "scene/2d/node_2d.h"
 #include <spine/Bone.h>
 #include <spine/Bone.h>
 
 
@@ -50,8 +51,12 @@ public:
 
 
 	Vector2 world_to_local(Vector2 world_position);
 	Vector2 world_to_local(Vector2 world_position);
 
 
+	Vector2 world_to_parent(Vector2 world_position);
+
 	Vector2 local_to_world(Vector2 local_position);
 	Vector2 local_to_world(Vector2 local_position);
 
 
+	Vector2 parent_to_world(Vector2 local_position);
+
 	float world_to_local_rotation(float world_rotation);
 	float world_to_local_rotation(float world_rotation);
 
 
 	float local_to_world_rotation(float local_rotation);
 	float local_to_world_rotation(float local_rotation);
@@ -160,6 +165,10 @@ public:
 
 
 	void set_active(bool v);
 	void set_active(bool v);
 
 
+	SpineConstant::Inherit get_inherit();
+
+	void set_inherit(SpineConstant::Inherit inherit);
+
 	// External feature functions
 	// External feature functions
 	void apply_world_transform_2d(const Variant &o);
 	void apply_world_transform_2d(const Variant &o);
 
 

+ 25 - 7
spine-godot/spine_godot/SpineBoneData.cpp

@@ -50,12 +50,15 @@ void SpineBoneData::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_shear_x", "v"), &SpineBoneData::set_shear_x);
 	ClassDB::bind_method(D_METHOD("set_shear_x", "v"), &SpineBoneData::set_shear_x);
 	ClassDB::bind_method(D_METHOD("get_shear_y"), &SpineBoneData::get_shear_y);
 	ClassDB::bind_method(D_METHOD("get_shear_y"), &SpineBoneData::get_shear_y);
 	ClassDB::bind_method(D_METHOD("set_shear_y", "v"), &SpineBoneData::set_shear_y);
 	ClassDB::bind_method(D_METHOD("set_shear_y", "v"), &SpineBoneData::set_shear_y);
-	ClassDB::bind_method(D_METHOD("get_transform_mode"), &SpineBoneData::get_transform_mode);
-	ClassDB::bind_method(D_METHOD("set_transform_mode", "v"), &SpineBoneData::set_transform_mode);
+	ClassDB::bind_method(D_METHOD("get_inherit"), &SpineBoneData::get_inherit);
+	ClassDB::bind_method(D_METHOD("set_inherit", "v"), &SpineBoneData::set_inherit);
 	ClassDB::bind_method(D_METHOD("is_skin_required"), &SpineBoneData::is_skin_required);
 	ClassDB::bind_method(D_METHOD("is_skin_required"), &SpineBoneData::is_skin_required);
 	ClassDB::bind_method(D_METHOD("set_skin_required", "v"), &SpineBoneData::set_skin_required);
 	ClassDB::bind_method(D_METHOD("set_skin_required", "v"), &SpineBoneData::set_skin_required);
 	ClassDB::bind_method(D_METHOD("get_color"), &SpineBoneData::get_color);
 	ClassDB::bind_method(D_METHOD("get_color"), &SpineBoneData::get_color);
 	ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineBoneData::set_color);
 	ClassDB::bind_method(D_METHOD("set_color", "v"), &SpineBoneData::set_color);
+	ClassDB::bind_method(D_METHOD("get_icon"), &SpineBoneData::get_icon);
+	ClassDB::bind_method(D_METHOD("set_visible", "v"), &SpineBoneData::set_visible);
+	ClassDB::bind_method(D_METHOD("is_visible"), &SpineBoneData::is_visible);
 }
 }
 
 
 int SpineBoneData::get_index() {
 int SpineBoneData::get_index() {
@@ -157,14 +160,14 @@ void SpineBoneData::set_shear_y(float v) {
 	get_spine_object()->setShearY(v);
 	get_spine_object()->setShearY(v);
 }
 }
 
 
-SpineConstant::TransformMode SpineBoneData::get_transform_mode() {
-	SPINE_CHECK(get_spine_object(), SpineConstant::TransformMode::TransformMode_Normal)
-	return (SpineConstant::TransformMode) get_spine_object()->getTransformMode();
+SpineConstant::Inherit SpineBoneData::get_inherit() {
+	SPINE_CHECK(get_spine_object(), SpineConstant::Inherit::Inherit_Normal)
+	return (SpineConstant::Inherit) get_spine_object()->getInherit();
 }
 }
 
 
-void SpineBoneData::set_transform_mode(SpineConstant::TransformMode v) {
+void SpineBoneData::set_inherit(SpineConstant::Inherit v) {
 	SPINE_CHECK(get_spine_object(), )
 	SPINE_CHECK(get_spine_object(), )
-	get_spine_object()->setTransformMode((spine::TransformMode) v);
+	get_spine_object()->setInherit((spine::Inherit) v);
 }
 }
 
 
 bool SpineBoneData::is_skin_required() {
 bool SpineBoneData::is_skin_required() {
@@ -187,3 +190,18 @@ void SpineBoneData::set_color(Color color) {
 	SPINE_CHECK(get_spine_object(), )
 	SPINE_CHECK(get_spine_object(), )
 	get_spine_object()->getColor().set(color.r, color.g, color.b, color.a);
 	get_spine_object()->getColor().set(color.r, color.g, color.b, color.a);
 }
 }
+
+String SpineBoneData::get_icon() {
+	SPINE_CHECK(get_spine_object(), "")
+	return get_spine_object()->getIcon().buffer();
+}
+
+bool SpineBoneData::is_visible() {
+	SPINE_CHECK(get_spine_object(), true)
+	return get_spine_object()->isVisible();
+}
+
+void SpineBoneData::set_visible(bool v) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setVisible(v);
+}

+ 8 - 2
spine-godot/spine_godot/SpineBoneData.h

@@ -80,9 +80,9 @@ public:
 
 
 	void set_shear_y(float v);
 	void set_shear_y(float v);
 
 
-	SpineConstant::TransformMode get_transform_mode();
+	SpineConstant::Inherit get_inherit();
 
 
-	void set_transform_mode(SpineConstant::TransformMode v);
+	void set_inherit(SpineConstant::Inherit v);
 
 
 	bool is_skin_required();
 	bool is_skin_required();
 
 
@@ -91,4 +91,10 @@ public:
 	Color get_color();
 	Color get_color();
 
 
 	void set_color(Color color);
 	void set_color(Color color);
+
+	String get_icon();
+
+	bool is_visible();
+
+	void set_visible(bool v);
 };
 };

+ 2 - 2
spine-godot/spine_godot/SpineBoneNode.cpp

@@ -181,7 +181,7 @@ void SpineBoneNode::init_transform(SpineSprite *sprite) {
 	if (!sprite) return;
 	if (!sprite) return;
 	if (bone_mode == SpineConstant::BoneMode_Drive) return;
 	if (bone_mode == SpineConstant::BoneMode_Drive) return;
 	sprite->get_skeleton()->set_to_setup_pose();
 	sprite->get_skeleton()->set_to_setup_pose();
-	sprite->get_skeleton()->update_world_transform();
+	sprite->get_skeleton()->update_world_transform(SpineConstant::Physics_Update);
 	Transform2D global_transform = sprite->get_global_bone_transform(bone_name);
 	Transform2D global_transform = sprite->get_global_bone_transform(bone_name);
 	set_global_transform(global_transform);
 	set_global_transform(global_transform);
 	update_transform(sprite);
 	update_transform(sprite);
@@ -259,7 +259,7 @@ void SpineBoneNode::set_enabled(bool _enabled) {
 		auto sprite = find_parent_sprite();
 		auto sprite = find_parent_sprite();
 		if (!sprite) return;
 		if (!sprite) return;
 		sprite->get_skeleton()->set_to_setup_pose();
 		sprite->get_skeleton()->set_to_setup_pose();
-		sprite->get_skeleton()->update_world_transform();
+		sprite->get_skeleton()->update_world_transform(SpineConstant::Physics_Update);
 	}
 	}
 }
 }
 
 

+ 10 - 5
spine-godot/spine_godot/SpineConstant.cpp

@@ -59,11 +59,11 @@ void SpineConstant::_bind_methods() {
 	BIND_ENUM_CONSTANT(Property_PathConstraintMix)
 	BIND_ENUM_CONSTANT(Property_PathConstraintMix)
 	BIND_ENUM_CONSTANT(Property_Sequence)
 	BIND_ENUM_CONSTANT(Property_Sequence)
 
 
-	BIND_ENUM_CONSTANT(TransformMode_Normal)
-	BIND_ENUM_CONSTANT(TransformMode_OnlyTranslation)
-	BIND_ENUM_CONSTANT(TransformMode_NoRotationOrReflection)
-	BIND_ENUM_CONSTANT(TransformMode_NoScale)
-	BIND_ENUM_CONSTANT(TransformMode_NoScaleOrReflection)
+	BIND_ENUM_CONSTANT(Inherit_Normal)
+	BIND_ENUM_CONSTANT(Inherit_OnlyTranslation)
+	BIND_ENUM_CONSTANT(Inherit_NoRotationOrReflection)
+	BIND_ENUM_CONSTANT(Inherit_NoScale)
+	BIND_ENUM_CONSTANT(Inherit_NoScaleOrReflection)
 
 
 	BIND_ENUM_CONSTANT(PositionMode_Fixed)
 	BIND_ENUM_CONSTANT(PositionMode_Fixed)
 	BIND_ENUM_CONSTANT(PositionMode_Percent)
 	BIND_ENUM_CONSTANT(PositionMode_Percent)
@@ -87,4 +87,9 @@ void SpineConstant::_bind_methods() {
 
 
 	BIND_ENUM_CONSTANT(BoneMode_Follow)
 	BIND_ENUM_CONSTANT(BoneMode_Follow)
 	BIND_ENUM_CONSTANT(BoneMode_Drive)
 	BIND_ENUM_CONSTANT(BoneMode_Drive)
+
+	BIND_ENUM_CONSTANT(Physics_None);
+	BIND_ENUM_CONSTANT(Physics_Reset);
+	BIND_ENUM_CONSTANT(Physics_Update);
+	BIND_ENUM_CONSTANT(Physics_Pose);
 }
 }

+ 15 - 7
spine-godot/spine_godot/SpineConstant.h

@@ -73,12 +73,12 @@ public:
 		Property_Sequence = 1 << 19
 		Property_Sequence = 1 << 19
 	};
 	};
 
 
-	enum TransformMode {
-		TransformMode_Normal = 0,
-		TransformMode_OnlyTranslation,
-		TransformMode_NoRotationOrReflection,
-		TransformMode_NoScale,
-		TransformMode_NoScaleOrReflection
+	enum Inherit {
+		Inherit_Normal = 0,
+		Inherit_OnlyTranslation,
+		Inherit_NoRotationOrReflection,
+		Inherit_NoScale,
+		Inherit_NoScaleOrReflection
 	};
 	};
 
 
 	enum PositionMode {
 	enum PositionMode {
@@ -115,15 +115,23 @@ public:
 		BoneMode_Follow,
 		BoneMode_Follow,
 		BoneMode_Drive
 		BoneMode_Drive
 	};
 	};
+
+	enum Physics {
+		Physics_None,
+		Physics_Reset,
+		Physics_Update,
+		Physics_Pose
+	};
 };
 };
 
 
 VARIANT_ENUM_CAST(SpineConstant::MixBlend)
 VARIANT_ENUM_CAST(SpineConstant::MixBlend)
 VARIANT_ENUM_CAST(SpineConstant::MixDirection)
 VARIANT_ENUM_CAST(SpineConstant::MixDirection)
 VARIANT_ENUM_CAST(SpineConstant::PropertyId)
 VARIANT_ENUM_CAST(SpineConstant::PropertyId)
-VARIANT_ENUM_CAST(SpineConstant::TransformMode)
+VARIANT_ENUM_CAST(SpineConstant::Inherit)
 VARIANT_ENUM_CAST(SpineConstant::PositionMode)
 VARIANT_ENUM_CAST(SpineConstant::PositionMode)
 VARIANT_ENUM_CAST(SpineConstant::SpacingMode)
 VARIANT_ENUM_CAST(SpineConstant::SpacingMode)
 VARIANT_ENUM_CAST(SpineConstant::RotateMode)
 VARIANT_ENUM_CAST(SpineConstant::RotateMode)
 VARIANT_ENUM_CAST(SpineConstant::BlendMode)
 VARIANT_ENUM_CAST(SpineConstant::BlendMode)
 VARIANT_ENUM_CAST(SpineConstant::UpdateMode)
 VARIANT_ENUM_CAST(SpineConstant::UpdateMode)
 VARIANT_ENUM_CAST(SpineConstant::BoneMode)
 VARIANT_ENUM_CAST(SpineConstant::BoneMode)
+VARIANT_ENUM_CAST(SpineConstant::Physics)

+ 1 - 1
spine-godot/spine_godot/SpineIkConstraint.cpp

@@ -55,7 +55,7 @@ void SpineIkConstraint::_bind_methods() {
 
 
 void SpineIkConstraint::update() {
 void SpineIkConstraint::update() {
 	SPINE_CHECK(get_spine_object(), )
 	SPINE_CHECK(get_spine_object(), )
-	get_spine_object()->update();
+	get_spine_object()->update(spine::Physics_Update);
 }
 }
 
 
 int SpineIkConstraint::get_order() {
 int SpineIkConstraint::get_order() {

+ 1 - 1
spine-godot/spine_godot/SpinePathConstraint.cpp

@@ -55,7 +55,7 @@ void SpinePathConstraint::_bind_methods() {
 
 
 void SpinePathConstraint::update() {
 void SpinePathConstraint::update() {
 	SPINE_CHECK(get_spine_object(), )
 	SPINE_CHECK(get_spine_object(), )
-	get_spine_object()->update();
+	get_spine_object()->update(spine::Physics_Update);
 }
 }
 
 
 int SpinePathConstraint::get_order() {
 int SpinePathConstraint::get_order() {

+ 382 - 0
spine-godot/spine_godot/SpinePhysicsConstraint.cpp

@@ -0,0 +1,382 @@
+/******************************************************************************
+ * Spine Runtimes License Agreement
+ * Last updated July 28, 2023. Replaces all prior versions.
+ *
+ * Copyright (c) 2013-2023, Esoteric Software LLC
+ *
+ * Integration of the Spine Runtimes into software or otherwise creating
+ * derivative works of the Spine Runtimes is permitted under the terms and
+ * conditions of Section 2 of the Spine Editor License Agreement:
+ * http://esotericsoftware.com/spine-editor-license
+ *
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software or
+ * otherwise create derivative works of the Spine Runtimes (collectively,
+ * "Products"), provided that each user of the Products must obtain their own
+ * Spine Editor license and redistribution of the Products in any form must
+ * include this license and copyright notice.
+ *
+ * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+ * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+ * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "SpinePhysicsConstraint.h"
+#include "SpineCommon.h"
+#include "SpineSprite.h"
+
+void SpinePhysicsConstraint::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("update", "physics"), &SpinePhysicsConstraint::update);
+	ClassDB::bind_method(D_METHOD("get_bone"), &SpinePhysicsConstraint::get_bone);
+	ClassDB::bind_method(D_METHOD("set_inertia", "value"), &SpinePhysicsConstraint::set_inertia);
+	ClassDB::bind_method(D_METHOD("get_inertia"), &SpinePhysicsConstraint::get_inertia);
+	ClassDB::bind_method(D_METHOD("set_strength", "value"), &SpinePhysicsConstraint::set_strength);
+	ClassDB::bind_method(D_METHOD("get_strength"), &SpinePhysicsConstraint::get_strength);
+	ClassDB::bind_method(D_METHOD("set_damping", "value"), &SpinePhysicsConstraint::set_damping);
+	ClassDB::bind_method(D_METHOD("get_damping"), &SpinePhysicsConstraint::get_damping);
+	ClassDB::bind_method(D_METHOD("set_mass_inverse", "value"), &SpinePhysicsConstraint::set_mass_inverse);
+	ClassDB::bind_method(D_METHOD("get_mass_inverse"), &SpinePhysicsConstraint::get_mass_inverse);
+	ClassDB::bind_method(D_METHOD("set_wind", "value"), &SpinePhysicsConstraint::set_wind);
+	ClassDB::bind_method(D_METHOD("get_wind"), &SpinePhysicsConstraint::get_wind);
+	ClassDB::bind_method(D_METHOD("set_gravity", "value"), &SpinePhysicsConstraint::set_gravity);
+	ClassDB::bind_method(D_METHOD("get_gravity"), &SpinePhysicsConstraint::get_gravity);
+	ClassDB::bind_method(D_METHOD("set_mix", "value"), &SpinePhysicsConstraint::set_mix);
+	ClassDB::bind_method(D_METHOD("get_mix"), &SpinePhysicsConstraint::get_mix);
+	ClassDB::bind_method(D_METHOD("set_reset", "value"), &SpinePhysicsConstraint::set_reset);
+	ClassDB::bind_method(D_METHOD("get_reset"), &SpinePhysicsConstraint::get_reset);
+	ClassDB::bind_method(D_METHOD("set_ux", "value"), &SpinePhysicsConstraint::set_ux);
+	ClassDB::bind_method(D_METHOD("get_ux"), &SpinePhysicsConstraint::get_ux);
+	ClassDB::bind_method(D_METHOD("set_uy", "value"), &SpinePhysicsConstraint::set_uy);
+	ClassDB::bind_method(D_METHOD("get_uy"), &SpinePhysicsConstraint::get_uy);
+	ClassDB::bind_method(D_METHOD("set_cx", "value"), &SpinePhysicsConstraint::set_cx);
+	ClassDB::bind_method(D_METHOD("get_cx"), &SpinePhysicsConstraint::get_cx);
+	ClassDB::bind_method(D_METHOD("set_cy", "value"), &SpinePhysicsConstraint::set_cy);
+	ClassDB::bind_method(D_METHOD("get_cy"), &SpinePhysicsConstraint::get_cy);
+	ClassDB::bind_method(D_METHOD("set_tx", "value"), &SpinePhysicsConstraint::set_tx);
+	ClassDB::bind_method(D_METHOD("get_tx"), &SpinePhysicsConstraint::get_tx);
+	ClassDB::bind_method(D_METHOD("set_ty", "value"), &SpinePhysicsConstraint::set_ty);
+	ClassDB::bind_method(D_METHOD("get_ty"), &SpinePhysicsConstraint::get_ty);
+	ClassDB::bind_method(D_METHOD("set_x_offset", "value"), &SpinePhysicsConstraint::set_x_offset);
+	ClassDB::bind_method(D_METHOD("get_x_offset"), &SpinePhysicsConstraint::get_x_offset);
+	ClassDB::bind_method(D_METHOD("set_x_velocity", "value"), &SpinePhysicsConstraint::set_x_velocity);
+	ClassDB::bind_method(D_METHOD("get_x_velocity"), &SpinePhysicsConstraint::get_x_velocity);
+	ClassDB::bind_method(D_METHOD("set_y_offset", "value"), &SpinePhysicsConstraint::set_y_offset);
+	ClassDB::bind_method(D_METHOD("get_y_offset"), &SpinePhysicsConstraint::get_y_offset);
+	ClassDB::bind_method(D_METHOD("set_y_velocity", "value"), &SpinePhysicsConstraint::set_y_velocity);
+	ClassDB::bind_method(D_METHOD("get_y_velocity"), &SpinePhysicsConstraint::get_y_velocity);
+	ClassDB::bind_method(D_METHOD("set_rotate_offset", "value"), &SpinePhysicsConstraint::set_rotate_offset);
+	ClassDB::bind_method(D_METHOD("get_rotate_offset"), &SpinePhysicsConstraint::get_rotate_offset);
+	ClassDB::bind_method(D_METHOD("set_rotate_velocity", "value"), &SpinePhysicsConstraint::set_rotate_velocity);
+	ClassDB::bind_method(D_METHOD("get_rotate_velocity"), &SpinePhysicsConstraint::get_rotate_velocity);
+	ClassDB::bind_method(D_METHOD("set_scale_offset", "value"), &SpinePhysicsConstraint::set_scale_offset);
+	ClassDB::bind_method(D_METHOD("get_scale_offset"), &SpinePhysicsConstraint::get_scale_offset);
+	ClassDB::bind_method(D_METHOD("set_scale_velocity", "value"), &SpinePhysicsConstraint::set_scale_velocity);
+	ClassDB::bind_method(D_METHOD("get_scale_velocity"), &SpinePhysicsConstraint::get_scale_velocity);
+	ClassDB::bind_method(D_METHOD("set_active", "value"), &SpinePhysicsConstraint::set_active);
+	ClassDB::bind_method(D_METHOD("is_active"), &SpinePhysicsConstraint::is_active);
+	ClassDB::bind_method(D_METHOD("set_remaining", "value"), &SpinePhysicsConstraint::set_remaining);
+	ClassDB::bind_method(D_METHOD("get_remaining"), &SpinePhysicsConstraint::get_remaining);
+	ClassDB::bind_method(D_METHOD("set_last_Time", "value"), &SpinePhysicsConstraint::set_last_Time);
+	ClassDB::bind_method(D_METHOD("get_last_Time"), &SpinePhysicsConstraint::get_last_Time);
+	ClassDB::bind_method(D_METHOD("reset"), &SpinePhysicsConstraint::reset);
+	ClassDB::bind_method(D_METHOD("translate", "x", "y"), &SpinePhysicsConstraint::translate);
+	ClassDB::bind_method(D_METHOD("rotate", "x", "y", "degrees"), &SpinePhysicsConstraint::rotate);
+}
+
+void SpinePhysicsConstraint::update(SpineConstant::Physics physics) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->update((spine::Physics) physics);
+}
+
+Ref<SpinePhysicsConstraintData> SpinePhysicsConstraint::get_data() {
+	SPINE_CHECK(get_spine_object(), nullptr)
+	auto &data = get_spine_object()->getData();
+	Ref<SpinePhysicsConstraintData> data_ref(memnew(SpinePhysicsConstraintData));
+	data_ref->set_spine_object(*get_spine_owner()->get_skeleton_data_res(), &data);
+	return data_ref;
+}
+
+Ref<SpineBone> SpinePhysicsConstraint::get_bone() {
+	SPINE_CHECK(get_spine_object(), nullptr)
+	auto target = get_spine_object()->getBone();
+	if (!target) return nullptr;
+	Ref<SpineBone> target_ref(memnew(SpineBone));
+	target_ref->set_spine_object(get_spine_owner(), target);
+	return target_ref;
+}
+
+void SpinePhysicsConstraint::set_bone(Ref<SpineBone> v) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setBone(v.is_valid() && v->get_spine_object() ? v->get_spine_object() : nullptr);
+}
+
+void SpinePhysicsConstraint::set_inertia(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setInertia(value);
+}
+
+float SpinePhysicsConstraint::get_inertia() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getInertia();
+}
+
+void SpinePhysicsConstraint::set_strength(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setStrength(value);
+}
+
+float SpinePhysicsConstraint::get_strength() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getStrength();
+}
+
+void SpinePhysicsConstraint::set_damping(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setDamping(value);
+}
+
+float SpinePhysicsConstraint::get_damping() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getDamping();
+}
+
+void SpinePhysicsConstraint::set_mass_inverse(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setMassInverse(value);
+}
+
+float SpinePhysicsConstraint::get_mass_inverse() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getMassInverse();
+}
+
+void SpinePhysicsConstraint::set_wind(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setWind(value);
+}
+
+float SpinePhysicsConstraint::get_wind() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getWind();
+}
+
+void SpinePhysicsConstraint::set_gravity(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setGravity(value);
+}
+
+float SpinePhysicsConstraint::get_gravity() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getGravity();
+}
+
+void SpinePhysicsConstraint::set_mix(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setMix(value);
+}
+
+float SpinePhysicsConstraint::get_mix() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getMix();
+}
+
+void SpinePhysicsConstraint::set_reset(bool value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setReset(value);
+}
+
+bool SpinePhysicsConstraint::get_reset() {
+	SPINE_CHECK(get_spine_object(), false)
+	return get_spine_object()->getReset();
+}
+
+void SpinePhysicsConstraint::set_ux(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setUx(value);
+}
+
+float SpinePhysicsConstraint::get_ux() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getUx();
+}
+
+void SpinePhysicsConstraint::set_uy(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setUy(value);
+}
+
+float SpinePhysicsConstraint::get_uy() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getUy();
+}
+
+void SpinePhysicsConstraint::set_cx(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setCx(value);
+}
+
+float SpinePhysicsConstraint::get_cx() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getCx();
+}
+
+void SpinePhysicsConstraint::set_cy(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setCy(value);
+}
+
+float SpinePhysicsConstraint::get_cy() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getCy();
+}
+
+void SpinePhysicsConstraint::set_tx(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setTx(value);
+}
+
+float SpinePhysicsConstraint::get_tx() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getTx();
+}
+
+void SpinePhysicsConstraint::set_ty(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setTy(value);
+}
+
+float SpinePhysicsConstraint::get_ty() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getTy();
+}
+
+void SpinePhysicsConstraint::set_x_offset(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setXOffset(value);
+}
+
+float SpinePhysicsConstraint::get_x_offset() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getXOffset();
+}
+
+void SpinePhysicsConstraint::set_x_velocity(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setXVelocity(value);
+}
+
+float SpinePhysicsConstraint::get_x_velocity() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getXVelocity();
+}
+
+void SpinePhysicsConstraint::set_y_offset(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setYOffset(value);
+}
+
+float SpinePhysicsConstraint::get_y_offset() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getYOffset();
+}
+
+void SpinePhysicsConstraint::set_y_velocity(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setYVelocity(value);
+}
+
+float SpinePhysicsConstraint::get_y_velocity() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getYVelocity();
+}
+
+void SpinePhysicsConstraint::set_rotate_offset(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setRotateOffset(value);
+}
+
+float SpinePhysicsConstraint::get_rotate_offset() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getRotateOffset();
+}
+
+void SpinePhysicsConstraint::set_rotate_velocity(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setRotateVelocity(value);
+}
+
+float SpinePhysicsConstraint::get_rotate_velocity() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getRotateVelocity();
+}
+
+void SpinePhysicsConstraint::set_scale_offset(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setScaleOffset(value);
+}
+
+float SpinePhysicsConstraint::get_scale_offset() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getScaleOffset();
+}
+
+void SpinePhysicsConstraint::set_scale_velocity(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setScaleVelocity(value);
+}
+
+float SpinePhysicsConstraint::get_scale_velocity() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getScaleVelocity();
+}
+
+void SpinePhysicsConstraint::set_active(bool value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setActive(value);
+}
+
+bool SpinePhysicsConstraint::is_active() {
+	SPINE_CHECK(get_spine_object(), false)
+	return get_spine_object()->isActive();
+}
+
+void SpinePhysicsConstraint::set_remaining(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setRemaining(value);
+}
+
+float SpinePhysicsConstraint::get_remaining() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getRemaining();
+}
+
+void SpinePhysicsConstraint::set_last_Time(float value) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setLastTime(value);
+}
+
+float SpinePhysicsConstraint::get_last_Time() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getLastTime();
+}
+
+void SpinePhysicsConstraint::reset() {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->reset();
+}
+
+void SpinePhysicsConstraint::translate(float x, float y) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->translate(x, y);
+}
+
+void SpinePhysicsConstraint::rotate(float x, float y, float degrees) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->rotate(x, y, degrees);
+}

+ 132 - 0
spine-godot/spine_godot/SpinePhysicsConstraint.h

@@ -0,0 +1,132 @@
+/******************************************************************************
+ * Spine Runtimes License Agreement
+ * Last updated July 28, 2023. Replaces all prior versions.
+ *
+ * Copyright (c) 2013-2023, Esoteric Software LLC
+ *
+ * Integration of the Spine Runtimes into software or otherwise creating
+ * derivative works of the Spine Runtimes is permitted under the terms and
+ * conditions of Section 2 of the Spine Editor License Agreement:
+ * http://esotericsoftware.com/spine-editor-license
+ *
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software or
+ * otherwise create derivative works of the Spine Runtimes (collectively,
+ * "Products"), provided that each user of the Products must obtain their own
+ * Spine Editor license and redistribution of the Products in any form must
+ * include this license and copyright notice.
+ *
+ * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+ * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+ * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#pragma once
+
+#include "SpineCommon.h"
+#include "SpinePhysicsConstraintData.h"
+#include "SpineBone.h"
+#include <spine/PhysicsConstraint.h>
+
+class SpinePhysicsConstraint : public SpineSpriteOwnedObject<spine::PhysicsConstraint> {
+	GDCLASS(SpinePhysicsConstraint, SpineObjectWrapper)
+
+protected:
+	static void _bind_methods();
+
+public:
+	void update(SpineConstant::Physics physics);
+
+	Ref<SpinePhysicsConstraintData> get_data();
+
+	Ref<SpineBone> get_bone();
+
+	void set_bone(Ref<SpineBone> v);
+
+	void set_inertia(float value);
+	float get_inertia();
+
+	void set_strength(float value);
+	float get_strength();
+
+	void set_damping(float value);
+	float get_damping();
+
+	void set_mass_inverse(float value);
+	float get_mass_inverse();
+
+	void set_wind(float value);
+	float get_wind();
+
+	void set_gravity(float value);
+	float get_gravity();
+
+	void set_mix(float value);
+	float get_mix();
+
+	void set_reset(bool value);
+	bool get_reset();
+
+	void set_ux(float value);
+	float get_ux();
+
+	void set_uy(float value);
+	float get_uy();
+
+	void set_cx(float value);
+	float get_cx();
+
+	void set_cy(float value);
+	float get_cy();
+
+	void set_tx(float value);
+	float get_tx();
+
+	void set_ty(float value);
+	float get_ty();
+
+	void set_x_offset(float value);
+	float get_x_offset();
+
+	void set_x_velocity(float value);
+	float get_x_velocity();
+
+	void set_y_offset(float value);
+	float get_y_offset();
+
+	void set_y_velocity(float value);
+	float get_y_velocity();
+
+	void set_rotate_offset(float value);
+	float get_rotate_offset();
+
+	void set_rotate_velocity(float value);
+	float get_rotate_velocity();
+
+	void set_scale_offset(float value);
+	float get_scale_offset();
+
+	void set_scale_velocity(float value);
+	float get_scale_velocity();
+
+	void set_active(bool value);
+	bool is_active();
+
+	void set_remaining(float value);
+	float get_remaining();
+
+	void set_last_Time(float value);
+	float get_last_Time();
+
+	void reset();
+
+	void translate(float x, float y);
+
+	void rotate(float x, float y, float degrees);
+};

+ 153 - 0
spine-godot/spine_godot/SpinePhysicsConstraintData.cpp

@@ -0,0 +1,153 @@
+/******************************************************************************
+ * Spine Runtimes License Agreement
+ * Last updated July 28, 2023. Replaces all prior versions.
+ *
+ * Copyright (c) 2013-2023, Esoteric Software LLC
+ *
+ * Integration of the Spine Runtimes into software or otherwise creating
+ * derivative works of the Spine Runtimes is permitted under the terms and
+ * conditions of Section 2 of the Spine Editor License Agreement:
+ * http://esotericsoftware.com/spine-editor-license
+ *
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software or
+ * otherwise create derivative works of the Spine Runtimes (collectively,
+ * "Products"), provided that each user of the Products must obtain their own
+ * Spine Editor license and redistribution of the Products in any form must
+ * include this license and copyright notice.
+ *
+ * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+ * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+ * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "SpinePhysicsConstraintData.h"
+#include "SpineCommon.h"
+
+void SpinePhysicsConstraintData::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("get_bone"), &SpinePhysicsConstraintData::get_bone);
+	ClassDB::bind_method(D_METHOD("get_scale_x"), &SpinePhysicsConstraintData::get_scale_x);
+	ClassDB::bind_method(D_METHOD("get_shear_x"), &SpinePhysicsConstraintData::get_shear_x);
+	ClassDB::bind_method(D_METHOD("get_limit"), &SpinePhysicsConstraintData::get_limit);
+	ClassDB::bind_method(D_METHOD("get_step"), &SpinePhysicsConstraintData::get_step);
+	ClassDB::bind_method(D_METHOD("get_inertia"), &SpinePhysicsConstraintData::get_inertia);
+	ClassDB::bind_method(D_METHOD("get_strength"), &SpinePhysicsConstraintData::get_strength);
+	ClassDB::bind_method(D_METHOD("get_damping"), &SpinePhysicsConstraintData::get_damping);
+	ClassDB::bind_method(D_METHOD("get_mass_inverse"), &SpinePhysicsConstraintData::get_mass_inverse);
+	ClassDB::bind_method(D_METHOD("get_wind"), &SpinePhysicsConstraintData::get_wind);
+	ClassDB::bind_method(D_METHOD("get_gravity"), &SpinePhysicsConstraintData::get_gravity);
+	ClassDB::bind_method(D_METHOD("get_mix"), &SpinePhysicsConstraintData::get_mix);
+	ClassDB::bind_method(D_METHOD("is_inertia_global"), &SpinePhysicsConstraintData::is_inertia_global);
+	ClassDB::bind_method(D_METHOD("is_strength_global"), &SpinePhysicsConstraintData::is_strength_global);
+	ClassDB::bind_method(D_METHOD("is_damping_global"), &SpinePhysicsConstraintData::is_damping_global);
+	ClassDB::bind_method(D_METHOD("is_mass_global"), &SpinePhysicsConstraintData::is_mass_global);
+	ClassDB::bind_method(D_METHOD("is_wind_global"), &SpinePhysicsConstraintData::is_wind_global);
+	ClassDB::bind_method(D_METHOD("is_gravity_global"), &SpinePhysicsConstraintData::is_gravity_global);
+	ClassDB::bind_method(D_METHOD("is_mix_global"), &SpinePhysicsConstraintData::is_mix_global);
+}
+
+
+Ref<SpineBoneData> SpinePhysicsConstraintData::get_bone() {
+	SPINE_CHECK(get_spine_constraint_data(), nullptr)
+	auto bone = get_spine_constraint_data()->getBone();
+	if (!bone) return nullptr;
+	Ref<SpineBoneData> slot_ref(memnew(SpineBoneData));
+	slot_ref->set_spine_object(get_spine_owner(), bone);
+	return slot_ref;
+}
+
+float SpinePhysicsConstraintData::get_scale_x() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getScaleX();
+}
+
+float SpinePhysicsConstraintData::get_shear_x() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getShearX();
+}
+
+float SpinePhysicsConstraintData::get_limit() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getLimit();
+}
+
+float SpinePhysicsConstraintData::get_step() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getStep();
+}
+
+float SpinePhysicsConstraintData::get_inertia() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getInertia();
+}
+
+float SpinePhysicsConstraintData::get_strength() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getStrength();
+}
+
+float SpinePhysicsConstraintData::get_damping() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getDamping();
+}
+
+float SpinePhysicsConstraintData::get_mass_inverse() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getMassInverse();
+}
+
+float SpinePhysicsConstraintData::get_wind() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getWind();
+}
+
+float SpinePhysicsConstraintData::get_gravity() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getGravity();
+}
+
+float SpinePhysicsConstraintData::get_mix() {
+	SPINE_CHECK(get_spine_constraint_data(), 0)
+	return get_spine_constraint_data()->getMix();
+}
+
+bool SpinePhysicsConstraintData::is_inertia_global() {
+	SPINE_CHECK(get_spine_constraint_data(), false)
+	return get_spine_constraint_data()->isInertiaGlobal();
+}
+
+bool SpinePhysicsConstraintData::is_strength_global() {
+	SPINE_CHECK(get_spine_constraint_data(), false)
+	return get_spine_constraint_data()->isStrengthGlobal();
+}
+
+bool SpinePhysicsConstraintData::is_damping_global() {
+	SPINE_CHECK(get_spine_constraint_data(), false)
+	return get_spine_constraint_data()->isDampingGlobal();
+}
+
+bool SpinePhysicsConstraintData::is_mass_global() {
+	SPINE_CHECK(get_spine_constraint_data(), false)
+	return get_spine_constraint_data()->isMassGlobal();
+}
+
+bool SpinePhysicsConstraintData::is_wind_global() {
+	SPINE_CHECK(get_spine_constraint_data(), false)
+	return get_spine_constraint_data()->isWindGlobal();
+}
+
+bool SpinePhysicsConstraintData::is_gravity_global() {
+	SPINE_CHECK(get_spine_constraint_data(), false)
+	return get_spine_constraint_data()->isGravityGlobal();
+}
+
+bool SpinePhysicsConstraintData::is_mix_global() {
+	SPINE_CHECK(get_spine_constraint_data(), false)
+	return get_spine_constraint_data()->isMixGlobal();
+}

+ 88 - 0
spine-godot/spine_godot/SpinePhysicsConstraintData.h

@@ -0,0 +1,88 @@
+/******************************************************************************
+ * Spine Runtimes License Agreement
+ * Last updated July 28, 2023. Replaces all prior versions.
+ *
+ * Copyright (c) 2013-2023, Esoteric Software LLC
+ *
+ * Integration of the Spine Runtimes into software or otherwise creating
+ * derivative works of the Spine Runtimes is permitted under the terms and
+ * conditions of Section 2 of the Spine Editor License Agreement:
+ * http://esotericsoftware.com/spine-editor-license
+ *
+ * Otherwise, it is permitted to integrate the Spine Runtimes into software or
+ * otherwise create derivative works of the Spine Runtimes (collectively,
+ * "Products"), provided that each user of the Products must obtain their own
+ * Spine Editor license and redistribution of the Products in any form must
+ * include this license and copyright notice.
+ *
+ * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+ * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+ * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#pragma once
+
+#include "SpineConstraintData.h"
+#include "SpineBoneData.h"
+#include <spine/PhysicsConstraintData.h>
+
+class SpinePhysicsConstraintData : public SpineConstraintData {
+	GDCLASS(SpinePhysicsConstraintData, SpineConstraintData)
+
+	spine::PhysicsConstraintData *get_spine_constraint_data() { return (spine::PhysicsConstraintData *) SpineConstraintData::get_spine_object(); }
+
+protected:
+	static void _bind_methods();
+
+public:
+	Ref<SpineBoneData> get_bone();
+
+	float get_x();
+
+	float get_y();
+
+	float get_rotate();
+
+	float get_scale_x();
+
+	float get_shear_x();
+
+	float get_limit();
+
+	float get_step();
+
+	float get_inertia();
+
+	float get_strength();
+
+	float get_damping();
+
+	float get_mass_inverse();
+
+	float get_wind();
+
+	float get_gravity();
+
+	float get_mix();
+
+	bool is_inertia_global();
+
+	bool is_strength_global();
+
+	bool is_damping_global();
+
+	bool is_mass_global();
+
+	bool is_wind_global();
+
+	bool is_gravity_global();
+
+	bool is_mix_global();
+};

+ 61 - 5
spine-godot/spine_godot/SpineSkeleton.cpp

@@ -67,6 +67,11 @@ void SpineSkeleton::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineSkeleton::set_scale_x);
 	ClassDB::bind_method(D_METHOD("set_scale_x", "v"), &SpineSkeleton::set_scale_x);
 	ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineSkeleton::get_scale_y);
 	ClassDB::bind_method(D_METHOD("get_scale_y"), &SpineSkeleton::get_scale_y);
 	ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineSkeleton::set_scale_y);
 	ClassDB::bind_method(D_METHOD("set_scale_y", "v"), &SpineSkeleton::set_scale_y);
+	ClassDB::bind_method(D_METHOD("get_time"), &SpineSkeleton::get_time);
+	ClassDB::bind_method(D_METHOD("set_time", "time"), &SpineSkeleton::set_time);
+	ClassDB::bind_method(D_METHOD("update", "delta"), &SpineSkeleton::update);
+	ClassDB::bind_method(D_METHOD("physics_translate", "x", "y"), &SpineSkeleton::physics_translate);
+	ClassDB::bind_method(D_METHOD("physics_rotate", "x", "y", "degrees"), &SpineSkeleton::physics_rotate);
 }
 }
 
 
 SpineSkeleton::SpineSkeleton() : skeleton(nullptr), sprite(nullptr), last_skin(nullptr) {
 SpineSkeleton::SpineSkeleton() : skeleton(nullptr), sprite(nullptr), last_skin(nullptr) {
@@ -90,9 +95,9 @@ Ref<SpineSkeletonDataResource> SpineSkeleton::get_skeleton_data_res() const {
 	return sprite->get_skeleton_data_res();
 	return sprite->get_skeleton_data_res();
 }
 }
 
 
-void SpineSkeleton::update_world_transform() {
+void SpineSkeleton::update_world_transform(SpineConstant::Physics physics) {
 	SPINE_CHECK(skeleton, )
 	SPINE_CHECK(skeleton, )
-	skeleton->updateWorldTransform();
+	skeleton->updateWorldTransform((spine::Physics) physics);
 }
 }
 
 
 void SpineSkeleton::set_to_setup_pose() {
 void SpineSkeleton::set_to_setup_pose() {
@@ -203,6 +208,17 @@ Ref<SpinePathConstraint> SpineSkeleton::find_path_constraint(const String &const
 	return constraint_ref;
 	return constraint_ref;
 }
 }
 
 
+
+Ref<SpinePhysicsConstraint> SpineSkeleton::find_physics_constraint(const String &constraint_name) {
+	SPINE_CHECK(skeleton, nullptr)
+	if (EMPTY(constraint_name)) return nullptr;
+	auto constraint = skeleton->findPhysicsConstraint(SPINE_STRING_TMP(constraint_name));
+	if (!constraint) return nullptr;
+	Ref<SpinePhysicsConstraint> constraint_ref(memnew(SpinePhysicsConstraint));
+	constraint_ref->set_spine_object(sprite, constraint);
+	return constraint_ref;
+}
+
 Rect2 SpineSkeleton::get_bounds() {
 Rect2 SpineSkeleton::get_bounds() {
 	SPINE_CHECK(skeleton, Rect2(0, 0, 0, 0))
 	SPINE_CHECK(skeleton, Rect2(0, 0, 0, 0))
 	float x, y, w, h;
 	float x, y, w, h;
@@ -275,6 +291,20 @@ Array SpineSkeleton::get_ik_constraints() {
 	return result;
 	return result;
 }
 }
 
 
+Array SpineSkeleton::get_transform_constraints() {
+	Array result;
+	SPINE_CHECK(skeleton, result)
+	auto &constraints = skeleton->getTransformConstraints();
+	result.resize((int) constraints.size());
+	for (int i = 0; i < result.size(); ++i) {
+		auto constraint = constraints[i];
+		Ref<SpineTransformConstraint> constraint_ref(memnew(SpineTransformConstraint));
+		constraint_ref->set_spine_object(sprite, constraint);
+		result[i] = constraint_ref;
+	}
+	return result;
+}
+
 Array SpineSkeleton::get_path_constraints() {
 Array SpineSkeleton::get_path_constraints() {
 	Array result;
 	Array result;
 	SPINE_CHECK(skeleton, result)
 	SPINE_CHECK(skeleton, result)
@@ -288,14 +318,15 @@ Array SpineSkeleton::get_path_constraints() {
 	}
 	}
 	return result;
 	return result;
 }
 }
-Array SpineSkeleton::get_transform_constraints() {
+
+Array SpineSkeleton::get_physics_constraints() {
 	Array result;
 	Array result;
 	SPINE_CHECK(skeleton, result)
 	SPINE_CHECK(skeleton, result)
-	auto &constraints = skeleton->getTransformConstraints();
+	auto &constraints = skeleton->getPhysicsConstraints();
 	result.resize((int) constraints.size());
 	result.resize((int) constraints.size());
 	for (int i = 0; i < result.size(); ++i) {
 	for (int i = 0; i < result.size(); ++i) {
 		auto constraint = constraints[i];
 		auto constraint = constraints[i];
-		Ref<SpineTransformConstraint> constraint_ref(memnew(SpineTransformConstraint));
+		Ref<SpinePhysicsConstraint> constraint_ref(memnew(SpinePhysicsConstraint));
 		constraint_ref->set_spine_object(sprite, constraint);
 		constraint_ref->set_spine_object(sprite, constraint);
 		result[i] = constraint_ref;
 		result[i] = constraint_ref;
 	}
 	}
@@ -367,3 +398,28 @@ void SpineSkeleton::set_scale_y(float v) {
 	SPINE_CHECK(skeleton, )
 	SPINE_CHECK(skeleton, )
 	skeleton->setScaleY(v);
 	skeleton->setScaleY(v);
 }
 }
+
+float SpineSkeleton::get_time() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getTime();
+}
+
+void SpineSkeleton::set_time(float time) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setTime(time);
+}
+
+void SpineSkeleton::update(float delta) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->update(delta);
+}
+
+void SpineSkeleton::physics_translate(float x, float y) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->physicsTranslate(x, y);
+}
+
+void SpineSkeleton::physics_rotate(float x, float y, float degrees) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->physicsRotate(x, y, degrees);
+}

+ 17 - 2
spine-godot/spine_godot/SpineSkeleton.h

@@ -36,6 +36,7 @@
 #include "SpineIkConstraint.h"
 #include "SpineIkConstraint.h"
 #include "SpineTransformConstraint.h"
 #include "SpineTransformConstraint.h"
 #include "SpinePathConstraint.h"
 #include "SpinePathConstraint.h"
+#include "SpinePhysicsConstraint.h"
 
 
 #include <unordered_map>
 #include <unordered_map>
 
 
@@ -75,7 +76,7 @@ public:
 	SpineSkeleton();
 	SpineSkeleton();
 	~SpineSkeleton() override;
 	~SpineSkeleton() override;
 
 
-	void update_world_transform();
+	void update_world_transform(SpineConstant::Physics physics);
 
 
 	void set_to_setup_pose();
 	void set_to_setup_pose();
 
 
@@ -103,6 +104,8 @@ public:
 
 
 	Ref<SpinePathConstraint> find_path_constraint(const String &constraint_name);
 	Ref<SpinePathConstraint> find_path_constraint(const String &constraint_name);
 
 
+	Ref<SpinePhysicsConstraint> find_physics_constraint(const String &constraint_name);
+
 	Rect2 get_bounds();
 	Rect2 get_bounds();
 
 
 	Ref<SpineBone> get_root_bone();
 	Ref<SpineBone> get_root_bone();
@@ -115,9 +118,11 @@ public:
 
 
 	Array get_ik_constraints();
 	Array get_ik_constraints();
 
 
+	Array get_transform_constraints();
+
 	Array get_path_constraints();
 	Array get_path_constraints();
 
 
-	Array get_transform_constraints();
+	Array get_physics_constraints();
 
 
 	Ref<SpineSkin> get_skin();
 	Ref<SpineSkin> get_skin();
 
 
@@ -142,4 +147,14 @@ public:
 	float get_scale_y();
 	float get_scale_y();
 
 
 	void set_scale_y(float v);
 	void set_scale_y(float v);
+
+	float get_time();
+
+	void set_time(float time);
+
+	void update(float delta);
+
+	void physics_translate(float x, float y);
+
+	void physics_rotate(float x, float y, float degrees);
 };
 };

+ 24 - 0
spine-godot/spine_godot/SpineSkeletonDataResource.cpp

@@ -380,6 +380,7 @@ Ref<SpineTransformConstraintData> SpineSkeletonDataResource::find_transform_cons
 	constraint_ref->set_spine_object(this, constraint);
 	constraint_ref->set_spine_object(this, constraint);
 	return constraint_ref;
 	return constraint_ref;
 }
 }
+
 Ref<SpinePathConstraintData> SpineSkeletonDataResource::find_path_constraint(const String &constraint_name) const {
 Ref<SpinePathConstraintData> SpineSkeletonDataResource::find_path_constraint(const String &constraint_name) const {
 	SPINE_CHECK(skeleton_data, nullptr)
 	SPINE_CHECK(skeleton_data, nullptr)
 	if (EMPTY(constraint_name)) return nullptr;
 	if (EMPTY(constraint_name)) return nullptr;
@@ -390,6 +391,16 @@ Ref<SpinePathConstraintData> SpineSkeletonDataResource::find_path_constraint(con
 	return constraint_ref;
 	return constraint_ref;
 }
 }
 
 
+Ref<SpinePhysicsConstraintData> SpineSkeletonDataResource::find_physics_constraint(const String &constraint_name) const {
+	SPINE_CHECK(skeleton_data, nullptr)
+	if (EMPTY(constraint_name)) return nullptr;
+	auto constraint = skeleton_data->findPhysicsConstraint(SPINE_STRING_TMP(constraint_name));
+	if (constraint == nullptr) return nullptr;
+	Ref<SpinePhysicsConstraintData> constraint_ref(memnew(SpinePhysicsConstraintData));
+	constraint_ref->set_spine_object(this, constraint);
+	return constraint_ref;
+}
+
 String SpineSkeletonDataResource::get_skeleton_name() const {
 String SpineSkeletonDataResource::get_skeleton_name() const {
 	SPINE_CHECK(skeleton_data, "")
 	SPINE_CHECK(skeleton_data, "")
 	return skeleton_data->getName().buffer();
 	return skeleton_data->getName().buffer();
@@ -513,6 +524,19 @@ Array SpineSkeletonDataResource::get_path_constraints() const {
 	return result;
 	return result;
 }
 }
 
 
+Array SpineSkeletonDataResource::get_physics_constraints() const {
+	Array result;
+	SPINE_CHECK(skeleton_data, result)
+	auto constraints = skeleton_data->getPhysicsConstraints();
+	result.resize((int) constraints.size());
+	for (int i = 0; i < constraints.size(); ++i) {
+		Ref<SpinePhysicsConstraintData> constraint_ref(memnew(SpinePhysicsConstraintData));
+		constraint_ref->set_spine_object(this, constraints[i]);
+		result[i] = constraint_ref;
+	}
+	return result;
+}
+
 float SpineSkeletonDataResource::get_x() const {
 float SpineSkeletonDataResource::get_x() const {
 	SPINE_CHECK(skeleton_data, 0)
 	SPINE_CHECK(skeleton_data, 0)
 	return skeleton_data->getX();
 	return skeleton_data->getX();

+ 5 - 0
spine-godot/spine_godot/SpineSkeletonDataResource.h

@@ -38,6 +38,7 @@
 #include "SpineIkConstraintData.h"
 #include "SpineIkConstraintData.h"
 #include "SpineTransformConstraintData.h"
 #include "SpineTransformConstraintData.h"
 #include "SpinePathConstraintData.h"
 #include "SpinePathConstraintData.h"
+#include "SpinePhysicsConstraintData.h"
 #include "SpineEventData.h"
 #include "SpineEventData.h"
 
 
 class SpineAnimationMix : public Resource {
 class SpineAnimationMix : public Resource {
@@ -137,6 +138,8 @@ public:
 
 
 	Ref<SpinePathConstraintData> find_path_constraint(const String &constraint_name) const;
 	Ref<SpinePathConstraintData> find_path_constraint(const String &constraint_name) const;
 
 
+	Ref<SpinePhysicsConstraintData> find_physics_constraint(const String &constraint_name) const;
+
 	String get_skeleton_name() const;
 	String get_skeleton_name() const;
 
 
 	Array get_bones() const;
 	Array get_bones() const;
@@ -159,6 +162,8 @@ public:
 
 
 	Array get_path_constraints() const;
 	Array get_path_constraints() const;
 
 
+	Array get_physics_constraints() const;
+
 	float get_x() const;
 	float get_x() const;
 
 
 	float get_y() const;
 	float get_y() const;

+ 4 - 3
spine-godot/spine_godot/SpineSprite.cpp

@@ -441,7 +441,7 @@ void SpineSprite::on_skeleton_data_changed() {
 
 
 		animation_state->update(0);
 		animation_state->update(0);
 		animation_state->apply(skeleton);
 		animation_state->apply(skeleton);
-		skeleton->update_world_transform();
+		skeleton->update_world_transform(SpineConstant::Physics_Update);
 		generate_meshes_for_slots(skeleton);
 		generate_meshes_for_slots(skeleton);
 
 
 		if (update_mode == SpineConstant::UpdateMode_Process) {
 		if (update_mode == SpineConstant::UpdateMode_Process) {
@@ -675,10 +675,11 @@ void SpineSprite::update_skeleton(float delta) {
 	emit_signal(SNAME("before_animation_state_apply"), this);
 	emit_signal(SNAME("before_animation_state_apply"), this);
 	animation_state->apply(skeleton);
 	animation_state->apply(skeleton);
 	emit_signal(SNAME("before_world_transforms_change"), this);
 	emit_signal(SNAME("before_world_transforms_change"), this);
-	skeleton->update_world_transform();
+	skeleton->update(delta);
+	skeleton->update_world_transform(SpineConstant::Physics_Update);
 	modified_bones = false;
 	modified_bones = false;
 	emit_signal(SNAME("world_transforms_changed"), this);
 	emit_signal(SNAME("world_transforms_changed"), this);
-	if (modified_bones) skeleton->update_world_transform();
+	if (modified_bones) skeleton->update_world_transform(SpineConstant::Physics_Update);
 	sort_slot_nodes();
 	sort_slot_nodes();
 	update_meshes(skeleton);
 	update_meshes(skeleton);
 #if VERSION_MAJOR > 3
 #if VERSION_MAJOR > 3

+ 36 - 12
spine-godot/spine_godot/SpineTrackEntry.cpp

@@ -61,22 +61,26 @@ void SpineTrackEntry::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_alpha", "v"), &SpineTrackEntry::set_alpha);
 	ClassDB::bind_method(D_METHOD("set_alpha", "v"), &SpineTrackEntry::set_alpha);
 	ClassDB::bind_method(D_METHOD("get_event_threshold"), &SpineTrackEntry::get_event_threshold);
 	ClassDB::bind_method(D_METHOD("get_event_threshold"), &SpineTrackEntry::get_event_threshold);
 	ClassDB::bind_method(D_METHOD("set_event_threshold", "v"), &SpineTrackEntry::set_event_threshold);
 	ClassDB::bind_method(D_METHOD("set_event_threshold", "v"), &SpineTrackEntry::set_event_threshold);
-	ClassDB::bind_method(D_METHOD("get_attachment_threshold"), &SpineTrackEntry::get_attachment_threshold);
-	ClassDB::bind_method(D_METHOD("set_attachment_threshold", "v"), &SpineTrackEntry::set_attachment_threshold);
-	ClassDB::bind_method(D_METHOD("get_draw_order_threshold"), &SpineTrackEntry::get_draw_order_threshold);
-	ClassDB::bind_method(D_METHOD("set_draw_order_threshold", "v"), &SpineTrackEntry::set_draw_order_threshold);
+	ClassDB::bind_method(D_METHOD("get_mix_attachment_threshold"), &SpineTrackEntry::get_mix_attachment_threshold);
+	ClassDB::bind_method(D_METHOD("set_mix_attachment_threshold", "v"), &SpineTrackEntry::set_mix_attachment_threshold);
+	ClassDB::bind_method(D_METHOD("get_mix_draw_order_threshold"), &SpineTrackEntry::get_mix_draw_order_threshold);
+	ClassDB::bind_method(D_METHOD("set_mix_draw_order_threshold", "v"), &SpineTrackEntry::set_mix_draw_order_threshold);
+	ClassDB::bind_method(D_METHOD("get_alpha_attachment_threshold"), &SpineTrackEntry::get_alpha_attachment_threshold);
+	ClassDB::bind_method(D_METHOD("set_alpha_attachment_threshold", "v"), &SpineTrackEntry::set_alpha_attachment_threshold);
 	ClassDB::bind_method(D_METHOD("get_next"), &SpineTrackEntry::get_next);
 	ClassDB::bind_method(D_METHOD("get_next"), &SpineTrackEntry::get_next);
 	ClassDB::bind_method(D_METHOD("is_complete"), &SpineTrackEntry::is_complete);
 	ClassDB::bind_method(D_METHOD("is_complete"), &SpineTrackEntry::is_complete);
 	ClassDB::bind_method(D_METHOD("get_mix_time"), &SpineTrackEntry::get_mix_time);
 	ClassDB::bind_method(D_METHOD("get_mix_time"), &SpineTrackEntry::get_mix_time);
 	ClassDB::bind_method(D_METHOD("set_mix_time", "v"), &SpineTrackEntry::set_mix_time);
 	ClassDB::bind_method(D_METHOD("set_mix_time", "v"), &SpineTrackEntry::set_mix_time);
 	ClassDB::bind_method(D_METHOD("get_mix_duration"), &SpineTrackEntry::get_mix_duration);
 	ClassDB::bind_method(D_METHOD("get_mix_duration"), &SpineTrackEntry::get_mix_duration);
 	ClassDB::bind_method(D_METHOD("set_mix_duration", "v"), &SpineTrackEntry::set_mix_duration);
 	ClassDB::bind_method(D_METHOD("set_mix_duration", "v"), &SpineTrackEntry::set_mix_duration);
+	ClassDB::bind_method(D_METHOD("set_mix_duration_and_delay", "v", "delay"), &SpineTrackEntry::set_mix_duration_and_delay);
 	ClassDB::bind_method(D_METHOD("get_mix_blend"), &SpineTrackEntry::get_mix_blend);
 	ClassDB::bind_method(D_METHOD("get_mix_blend"), &SpineTrackEntry::get_mix_blend);
 	ClassDB::bind_method(D_METHOD("set_mix_blend", "v"), &SpineTrackEntry::set_mix_blend);
 	ClassDB::bind_method(D_METHOD("set_mix_blend", "v"), &SpineTrackEntry::set_mix_blend);
 	ClassDB::bind_method(D_METHOD("get_mixing_from"), &SpineTrackEntry::get_mixing_from);
 	ClassDB::bind_method(D_METHOD("get_mixing_from"), &SpineTrackEntry::get_mixing_from);
 	ClassDB::bind_method(D_METHOD("get_mixing_to"), &SpineTrackEntry::get_mixing_to);
 	ClassDB::bind_method(D_METHOD("get_mixing_to"), &SpineTrackEntry::get_mixing_to);
 	ClassDB::bind_method(D_METHOD("reset_rotation_directions"), &SpineTrackEntry::reset_rotation_directions);
 	ClassDB::bind_method(D_METHOD("reset_rotation_directions"), &SpineTrackEntry::reset_rotation_directions);
 	ClassDB::bind_method(D_METHOD("get_track_complete"), &SpineTrackEntry::get_track_complete);
 	ClassDB::bind_method(D_METHOD("get_track_complete"), &SpineTrackEntry::get_track_complete);
+	ClassDB::bind_method(D_METHOD("was_applied"), &SpineTrackEntry::was_applied);
 }
 }
 
 
 int SpineTrackEntry::get_track_index() {
 int SpineTrackEntry::get_track_index() {
@@ -237,24 +241,34 @@ void SpineTrackEntry::set_event_threshold(float v) {
 	get_spine_object()->setEventThreshold(v);
 	get_spine_object()->setEventThreshold(v);
 }
 }
 
 
-float SpineTrackEntry::get_attachment_threshold() {
+float SpineTrackEntry::get_mix_attachment_threshold() {
 	SPINE_CHECK(get_spine_object(), 0)
 	SPINE_CHECK(get_spine_object(), 0)
-	return get_spine_object()->getAttachmentThreshold();
+	return get_spine_object()->getMixAttachmentThreshold();
 }
 }
 
 
-void SpineTrackEntry::set_attachment_threshold(float v) {
+void SpineTrackEntry::set_mix_attachment_threshold(float v) {
 	SPINE_CHECK(get_spine_object(), )
 	SPINE_CHECK(get_spine_object(), )
-	get_spine_object()->setAttachmentThreshold(v);
+	get_spine_object()->setMixAttachmentThreshold(v);
 }
 }
 
 
-float SpineTrackEntry::get_draw_order_threshold() {
+float SpineTrackEntry::get_mix_draw_order_threshold() {
 	SPINE_CHECK(get_spine_object(), 0)
 	SPINE_CHECK(get_spine_object(), 0)
-	return get_spine_object()->getDrawOrderThreshold();
+	return get_spine_object()->getMixDrawOrderThreshold();
 }
 }
 
 
-void SpineTrackEntry::set_draw_order_threshold(float v) {
+void SpineTrackEntry::set_mix_draw_order_threshold(float v) {
 	SPINE_CHECK(get_spine_object(), )
 	SPINE_CHECK(get_spine_object(), )
-	get_spine_object()->setDrawOrderThreshold(v);
+	get_spine_object()->setMixDrawOrderThreshold(v);
+}
+
+float SpineTrackEntry::get_alpha_attachment_threshold() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->getAlphaAttachmentThreshold();
+}
+
+void SpineTrackEntry::set_alpha_attachment_threshold(float v) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setAlphaAttachmentThreshold(v);
 }
 }
 
 
 Ref<SpineTrackEntry> SpineTrackEntry::get_next() {
 Ref<SpineTrackEntry> SpineTrackEntry::get_next() {
@@ -291,6 +305,11 @@ void SpineTrackEntry::set_mix_duration(float v) {
 	get_spine_object()->setMixDuration(v);
 	get_spine_object()->setMixDuration(v);
 }
 }
 
 
+void SpineTrackEntry::set_mix_duration_and_delay(float v, float delay) {
+	SPINE_CHECK(get_spine_object(), )
+	get_spine_object()->setMixDuration(v, delay);
+}
+
 SpineConstant::MixBlend SpineTrackEntry::get_mix_blend() {
 SpineConstant::MixBlend SpineTrackEntry::get_mix_blend() {
 	SPINE_CHECK(get_spine_object(), SpineConstant::MixBlend_Setup)
 	SPINE_CHECK(get_spine_object(), SpineConstant::MixBlend_Setup)
 	return (SpineConstant::MixBlend) get_spine_object()->getMixBlend();
 	return (SpineConstant::MixBlend) get_spine_object()->getMixBlend();
@@ -328,3 +347,8 @@ float SpineTrackEntry::get_track_complete() {
 	SPINE_CHECK(get_spine_object(), 0)
 	SPINE_CHECK(get_spine_object(), 0)
 	return get_spine_object()->getTrackComplete();
 	return get_spine_object()->getTrackComplete();
 }
 }
+
+bool SpineTrackEntry::was_applied() {
+	SPINE_CHECK(get_spine_object(), 0)
+	return get_spine_object()->wasApplied();
+}

+ 12 - 4
spine-godot/spine_godot/SpineTrackEntry.h

@@ -103,13 +103,17 @@ public:
 
 
 	void set_event_threshold(float v);
 	void set_event_threshold(float v);
 
 
-	float get_attachment_threshold();
+	float get_mix_attachment_threshold();
 
 
-	void set_attachment_threshold(float v);
+	void set_mix_attachment_threshold(float v);
 
 
-	float get_draw_order_threshold();
+	float get_mix_draw_order_threshold();
 
 
-	void set_draw_order_threshold(float v);
+	void set_mix_draw_order_threshold(float v);
+
+	float get_alpha_attachment_threshold();
+
+	void set_alpha_attachment_threshold(float v);
 
 
 	Ref<SpineTrackEntry> get_next();
 	Ref<SpineTrackEntry> get_next();
 
 
@@ -123,6 +127,8 @@ public:
 
 
 	void set_mix_duration(float v);
 	void set_mix_duration(float v);
 
 
+	void set_mix_duration_and_delay(float v, float delay);
+
 	SpineConstant::MixBlend get_mix_blend();
 	SpineConstant::MixBlend get_mix_blend();
 
 
 	void set_mix_blend(SpineConstant::MixBlend v);
 	void set_mix_blend(SpineConstant::MixBlend v);
@@ -134,4 +140,6 @@ public:
 	void reset_rotation_directions();
 	void reset_rotation_directions();
 
 
 	float get_track_complete();
 	float get_track_complete();
+
+	bool was_applied();
 };
 };

+ 1 - 1
spine-godot/spine_godot/SpineTransformConstraint.cpp

@@ -55,7 +55,7 @@ void SpineTransformConstraint::_bind_methods() {
 
 
 void SpineTransformConstraint::update() {
 void SpineTransformConstraint::update() {
 	SPINE_CHECK(get_spine_object(), )
 	SPINE_CHECK(get_spine_object(), )
-	get_spine_object()->update();
+	get_spine_object()->update(spine::Physics_Update);
 }
 }
 
 
 int SpineTransformConstraint::get_order() {
 int SpineTransformConstraint::get_order() {