初始化

This commit is contained in:
SmallMain
2022-06-25 00:23:03 +08:00
commit ef0589e8e5
2264 changed files with 617829 additions and 0 deletions

View File

@@ -0,0 +1,563 @@
#include "Armature.h"
#include "../model/TextureAtlasData.h"
#include "../model/UserData.h"
#include "../animation/WorldClock.h"
#include "../animation/Animation.h"
#include "../event/EventObject.h"
#include "IArmatureProxy.h"
#include "Bone.h"
#include "Slot.h"
#include "Constraint.h"
DRAGONBONES_NAMESPACE_BEGIN
bool Armature::_onSortSlots(Slot* a, Slot* b)
{
return a->_zOrder < b->_zOrder ? true : false;
}
void Armature::_onClear()
{
if (_clock != nullptr) // Remove clock before slots clear.
{
_clock->remove(this);
}
for (const auto bone : _bones)
{
bone->returnToPool();
}
for (const auto slot : _slots)
{
slot->returnToPool();
}
for (const auto constraint : _constraints)
{
constraint->returnToPool();
}
for (const auto action : _actions)
{
action->returnToPool();
}
if(_animation != nullptr)
{
_animation->returnToPool();
}
if (_proxy != nullptr)
{
_proxy->dbClear();
}
if (_replaceTextureAtlasData != nullptr)
{
_replaceTextureAtlasData->returnToPool();
}
inheritAnimation = true;
userData = nullptr;
_debugDraw = false;
_lockUpdate = false;
_slotsDirty = false;
_zOrderDirty = false;
_flipX = false;
_flipY = false;
_cacheFrameIndex = -1;
_bones.clear();
_slots.clear();
_constraints.clear();
_actions.clear();
_armatureData = nullptr;
_animation = nullptr;
_proxy = nullptr;
_display = nullptr;
_replaceTextureAtlasData = nullptr;
_replacedTexture = nullptr;
_dragonBones = nullptr;
_clock = nullptr;
_parent = nullptr;
}
void Armature::_sortZOrder(const int16_t* slotIndices, unsigned offset)
{
const auto& slotDatas = _armatureData->sortedSlots;
const auto isOriginal = slotIndices == nullptr;
if (_zOrderDirty || !isOriginal)
{
for (std::size_t i = 0, l = slotDatas.size(); i < l; ++i)
{
const auto slotIndex = isOriginal ? i : (std::size_t)slotIndices[offset + i];
if (slotIndex < 0 || slotIndex >= l)
{
continue;
}
const auto slotData = slotDatas[slotIndex];
const auto slot = getSlot(slotData->name);
if (slot != nullptr)
{
slot->_setZorder(i);
}
}
_slotsDirty = true;
_zOrderDirty = !isOriginal;
}
}
void Armature::_addBone(Bone* value)
{
if (std::find(_bones.begin(), _bones.end(), value) == _bones.end())
{
_bones.push_back(value);
}
}
void Armature::_addSlot(Slot* value)
{
if (std::find(_slots.begin(), _slots.end(), value) == _slots.end())
{
_slots.push_back(value);
}
}
void Armature::_addConstraint(Constraint* value)
{
if (std::find(_constraints.cbegin(), _constraints.cend(), value) == _constraints.cend())
{
_constraints.push_back(value);
}
}
void Armature::_bufferAction(EventObject* action, bool append)
{
if (std::find(_actions.cbegin(), _actions.cend(), action) == _actions.cend())
{
if (append)
{
_actions.push_back(action);
}
else
{
_actions.insert(_actions.begin(), action);
}
}
}
void Armature::dispose()
{
if (_armatureData != nullptr)
{
_lockUpdate = true;
_dragonBones->bufferObject(this);
}
}
void Armature::init(ArmatureData *armatureData, IArmatureProxy* proxy, void* display, DragonBones* dragonBones)
{
if (_armatureData != nullptr)
{
return;
}
_armatureData = armatureData;
_animation = BaseObject::borrowObject<Animation>();
_proxy = proxy;
_display = display;
_dragonBones = dragonBones;
_proxy->dbInit(this);
_animation->init(this);
_animation->setAnimations(_armatureData->animations);
}
void Armature::advanceTime(float passedTime)
{
if (_lockUpdate)
{
return;
}
if (_armatureData == nullptr)
{
DRAGONBONES_ASSERT(false, "The armature has been disposed.");
return;
}
else if(_armatureData->parent == nullptr)
{
DRAGONBONES_ASSERT(false, "The armature data has been disposed.\nPlease make sure dispose armature before call factory.clear().");
return;
}
const auto prevCacheFrameIndex = _cacheFrameIndex;
// Update animation.
_animation->advanceTime(passedTime);
// Sort slots.
if (_slotsDirty)
{
_slotsDirty = false;
std::sort(_slots.begin(), _slots.end(), Armature::_onSortSlots);
}
// Update bones and slots.
if (_cacheFrameIndex < 0 || _cacheFrameIndex != prevCacheFrameIndex)
{
for (const auto bone : _bones)
{
bone->update(_cacheFrameIndex);
}
for (const auto slot : _slots)
{
slot->update(_cacheFrameIndex);
}
}
// Do actions.
if (!_actions.empty())
{
_lockUpdate = true;
for (const auto action : _actions)
{
const auto actionData = action->actionData;
if (actionData != nullptr)
{
if (actionData->type == ActionType::Play)
{
if (action->slot != nullptr)
{
const auto childArmature = action->slot->getChildArmature();
if (childArmature != nullptr)
{
childArmature->getAnimation()->fadeIn(actionData->name);
}
}
else if (action->bone != nullptr)
{
for (const auto slot : getSlots())
{
if (slot->getParent() == action->bone)
{
const auto childArmature = slot->getChildArmature();
if (childArmature != nullptr)
{
childArmature->getAnimation()->fadeIn(actionData->name);
}
}
}
}
else
{
_animation->fadeIn(actionData->name);
}
}
}
action->returnToPool();
}
_actions.clear();
_lockUpdate = false;
}
_proxy->dbUpdate();
}
void Armature::render()
{
if (_proxy)
{
_proxy->dbRender();
}
}
uint32_t Armature::getRenderOrder() const
{
if (_proxy)
{
return _proxy->getRenderOrder();
}
return 0;
}
void Armature::invalidUpdate(const std::string& boneName, bool updateSlot)
{
if (!boneName.empty())
{
const auto bone = getBone(boneName);
if (bone != nullptr)
{
bone->invalidUpdate();
if (updateSlot)
{
for (const auto slot : _slots)
{
if (slot->getParent() == bone)
{
slot->invalidUpdate();
}
}
}
}
}
else
{
for (const auto bone : _bones)
{
bone->invalidUpdate();
}
if (updateSlot)
{
for (const auto slot : _slots)
{
slot->invalidUpdate();
}
}
}
}
Slot* Armature::containsPoint(float x, float y) const
{
for(const auto slot : _slots)
{
if(slot->containsPoint(x,y)) {
return slot;
}
}
return nullptr;
}
Slot* Armature::intersectsSegment(
float xA, float yA, float xB, float yB,
Point* intersectionPointA,
Point* intersectionPointB,
Point* normalRadians
) const
{
const auto isV = xA == xB;
auto dMin = 0.0f;
auto dMax = 0.0f;
auto intXA = 0.0f;
auto intYA = 0.0f;
auto intXB = 0.0f;
auto intYB = 0.0f;
auto intAN = 0.0f;
auto intBN = 0.0f;
Slot* intSlotA = nullptr;
Slot* intSlotB = nullptr;
for (const auto & slot : _slots)
{
auto intersectionCount = slot->intersectsSegment(xA, yA, xB, yB, intersectionPointA, intersectionPointB, normalRadians);
if (intersectionCount > 0)
{
if (intersectionPointA != nullptr || intersectionPointB != nullptr)
{
if (intersectionPointA != nullptr)
{
float d = isV ? intersectionPointA->y - yA : intersectionPointA->x - xA;
if (d < 0.0f)
{
d = -d;
}
if (intSlotA == nullptr || d < dMin)
{
dMin = d;
intXA = intersectionPointA->x;
intYA = intersectionPointA->y;
intSlotA = slot;
if (normalRadians) {
intAN = normalRadians->x;
}
}
}
if (intersectionPointB != nullptr)
{
float d = intersectionPointB->x - xA;
if (d < 0.0f)
{
d = -d;
}
if (intSlotB == nullptr || d > dMax)
{
dMax = d;
intXB = intersectionPointB->x;
intYB = intersectionPointB->y;
intSlotB = slot;
if (normalRadians != nullptr)
{
intBN = normalRadians->y;
}
}
}
}
else
{
intSlotA = slot;
break;
}
}
}
if (intSlotA != nullptr && intersectionPointA != nullptr)
{
intersectionPointA->x = intXA;
intersectionPointA->y = intYA;
if (normalRadians != nullptr)
{
normalRadians->x = intAN;
}
}
if (intSlotB != nullptr && intersectionPointB != nullptr)
{
intersectionPointB->x = intXB;
intersectionPointB->y = intYB;
if (normalRadians != nullptr)
{
normalRadians->y = intBN;
}
}
return intSlotA;
}
Bone* Armature::getBone(const std::string& name) const
{
for (const auto& bone : _bones)
{
if (bone->getName() == name)
{
return bone;
}
}
return nullptr;
}
Bone* Armature::getBoneByDisplay(void* display) const
{
const auto slot = getSlotByDisplay(display);
return slot != nullptr ? slot->getParent() : nullptr;
}
Slot* Armature::getSlot(const std::string& name) const
{
for (const auto slot : _slots)
{
if (slot->getName() == name)
{
return slot;
}
}
return nullptr;
}
Slot* Armature::getSlotByDisplay(void* display) const
{
if (display != nullptr)
{
for (const auto slot : _slots)
{
if (slot->getDisplay() == display)
{
return slot;
}
}
}
return nullptr;
}
void Armature::setCacheFrameRate(unsigned value)
{
if (_armatureData->cacheFrameRate != value)
{
_armatureData->cacheFrames(value);
for (const auto & slot : _slots)
{
const auto childArmature = slot->getChildArmature();
if (childArmature != nullptr && childArmature->getCacheFrameRate() == 0)
{
childArmature->setCacheFrameRate(value);
}
}
}
}
void Armature::setClock(WorldClock* value)
{
if(_clock == value)
{
return;
}
if(_clock)
{
_clock->remove(this);
}
_clock = value;
if(_clock)
{
_clock->add(this);
}
// Update childArmature clock.
for (const auto& slot : _slots)
{
const auto childArmature = slot->getChildArmature();
if (childArmature != nullptr)
{
childArmature->setClock(_clock);
}
}
}
void Armature::setReplacedTexture(void* value)
{
if (_replacedTexture == value)
{
return;
}
if (_replaceTextureAtlasData != nullptr)
{
_replaceTextureAtlasData->returnToPool();
_replaceTextureAtlasData = nullptr;
}
_replacedTexture = value;
for (const auto &slot : _slots)
{
slot->invalidUpdate();
slot->update(-1);
}
}
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,563 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2012-2018 DragonBones team and other contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef DRAGONBONES_ARMATURE_H
#define DRAGONBONES_ARMATURE_H
#include "../core/BaseObject.h"
#include "../animation/IAnimatable.h"
#include "../model/ArmatureData.h"
#include "IArmatureProxy.h"
DRAGONBONES_NAMESPACE_BEGIN
/**
* - Armature is the core of the skeleton animation system.
* @see dragonBones.ArmatureData
* @see dragonBones.Bone
* @see dragonBones.Slot
* @see dragonBones.Animation
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 骨架是骨骼动画系统的核心。
* @see dragonBones.ArmatureData
* @see dragonBones.Bone
* @see dragonBones.Slot
* @see dragonBones.Animation
* @version DragonBones 3.0
* @language zh_CN
*/
class Armature : public virtual IAnimatable, public BaseObject
{
BIND_CLASS_TYPE_B(Armature);
private:
static bool _onSortSlots(Slot* a, Slot* b);
public:
/**
* - Whether to inherit the animation control of the parent armature.
* True to try to have the child armature play an animation with the same name when the parent armature play the animation.
* @default true
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 是否继承父骨架的动画控制。
* 如果该值为 true当父骨架播放动画时会尝试让子骨架播放同名动画。
* @default true
* @version DragonBones 4.5
* @language zh_CN
*/
bool inheritAnimation;
/**
* @private
*/
void* userData;
public:
/**
* @internal
*/
int _cacheFrameIndex;
/**
* @internal
*/
ArmatureData* _armatureData;
/**
* @internal
*/
DragonBones* _dragonBones;
/**
* @internal
*/
Slot* _parent;
/**
* @internal
*/
TextureAtlasData* _replaceTextureAtlasData;
/**
* @internal
*/
std::vector<Constraint*> _constraints;
protected:
bool _debugDraw;
bool _lockUpdate;
bool _slotsDirty;
bool _zOrderDirty;
bool _flipX;
bool _flipY;
std::vector<Bone*> _bones;
std::vector<Slot*> _slots;
std::vector<EventObject*> _actions;
Animation* _animation;
IArmatureProxy* _proxy;
void* _display;
WorldClock* _clock;
void* _replacedTexture;
public:
Armature() :
_animation(nullptr),
_proxy(nullptr),
_clock(nullptr),
_replaceTextureAtlasData(nullptr)
{
_onClear();
}
virtual ~Armature()
{
_onClear();
}
protected:
virtual void _onClear() override;
private:
void _sortSlots();
public:
/**
* @internal
*/
void _sortZOrder(const int16_t* slotIndices, unsigned offset);
/**
* @internal
*/
void _addBone(Bone* value);
/**
* @internal
*/
void _addSlot(Slot* value);
/**
* @internal
*/
void _addConstraint(Constraint* value);
/**
* @internal
*/
void _bufferAction(EventObject* action, bool append);
/**
* - Dispose the armature. (Return to the object pool)
* @example
* TypeScript style, for reference only.
* <pre>
* removeChild(armature.display);
* armature.dispose();
* </pre>
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 释放骨架。 (回收到对象池)
* @example
* TypeScript 风格,仅供参考。
* <pre>
* removeChild(armature.display);
* armature.dispose();
* </pre>
* @version DragonBones 3.0
* @language zh_CN
*/
void dispose();
/**
* @internal
*/
void init(ArmatureData *armatureData, IArmatureProxy* proxy, void* display, DragonBones* dragonBones);
/**
* @inheritDoc
*/
void advanceTime(float passedTime) override;
/**
* @inheritDoc
*/
void render() override;
/**
* @inheritDoc
*/
uint32_t getRenderOrder() const override;
/**
* - Forces a specific bone or its owning slot to update the transform or display property in the next frame.
* @param boneName - The bone name. (If not set, all bones will be update)
* @param updateSlot - Whether to update the bone's slots. (Default: false)
* @see dragonBones.Bone#invalidUpdate()
* @see dragonBones.Slot#invalidUpdate()
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 强制特定骨骼或其拥有的插槽在下一帧更新变换或显示属性。
* @param boneName - 骨骼名称。 (如果未设置,将更新所有骨骼)
* @param updateSlot - 是否更新骨骼的插槽。 (默认: false
* @see dragonBones.Bone#invalidUpdate()
* @see dragonBones.Slot#invalidUpdate()
* @version DragonBones 3.0
* @language zh_CN
*/
void invalidUpdate(const std::string& boneName = "", bool updateSlot = false);
/**
* - Check whether a specific point is inside a custom bounding box in a slot.
* The coordinate system of the point is the inner coordinate system of the armature.
* Custom bounding boxes need to be customized in Dragonbones Pro.
* @param x - The horizontal coordinate of the point.
* @param y - The vertical coordinate of the point.
* @version DragonBones 5.0
* @language en_US
*/
/**
* - 检查特定点是否在某个插槽的自定义边界框内。
* 点的坐标系为骨架内坐标系。
* 自定义边界框需要在 DragonBones Pro 中自定义。
* @param x - 点的水平坐标。
* @param y - 点的垂直坐标。
* @version DragonBones 5.0
* @language zh_CN
*/
Slot* containsPoint(float x, float y) const;
/**
* - Check whether a specific segment intersects a custom bounding box for a slot in the armature.
* The coordinate system of the segment and intersection is the inner coordinate system of the armature.
* Custom bounding boxes need to be customized in Dragonbones Pro.
* @param xA - The horizontal coordinate of the beginning of the segment.
* @param yA - The vertical coordinate of the beginning of the segment.
* @param xB - The horizontal coordinate of the end point of the segment.
* @param yB - The vertical coordinate of the end point of the segment.
* @param intersectionPointA - The first intersection at which a line segment intersects the bounding box from the beginning to the end. (If not set, the intersection point will not calculated)
* @param intersectionPointB - The first intersection at which a line segment intersects the bounding box from the end to the beginning. (If not set, the intersection point will not calculated)
* @param normalRadians - The normal radians of the tangent of the intersection boundary box. [x: Normal radian of the first intersection tangent, y: Normal radian of the second intersection tangent] (If not set, the normal will not calculated)
* @returns The slot of the first custom bounding box where the segment intersects from the start point to the end point.
* @version DragonBones 5.0
* @language en_US
*/
/**
* - 检查特定线段是否与骨架的某个插槽的自定义边界框相交。
* 线段和交点的坐标系均为骨架内坐标系。
* 自定义边界框需要在 DragonBones Pro 中自定义。
* @param xA - 线段起点的水平坐标。
* @param yA - 线段起点的垂直坐标。
* @param xB - 线段终点的水平坐标。
* @param yB - 线段终点的垂直坐标。
* @param intersectionPointA - 线段从起点到终点与边界框相交的第一个交点。 (如果未设置,则不计算交点)
* @param intersectionPointB - 线段从终点到起点与边界框相交的第一个交点。 (如果未设置,则不计算交点)
* @param normalRadians - 交点边界框切线的法线弧度。 [x: 第一个交点切线的法线弧度, y: 第二个交点切线的法线弧度] (如果未设置,则不计算法线)
* @returns 线段从起点到终点相交的第一个自定义边界框的插槽。
* @version DragonBones 5.0
* @language zh_CN
*/
Slot* intersectsSegment(
float xA, float yA, float xB, float yB,
Point* intersectionPointA = nullptr,
Point* intersectionPointB = nullptr,
Point* normalRadians = nullptr
) const;
/**
* - Get a specific bone.
* @param name - The bone name.
* @see dragonBones.Bone
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 获取特定的骨骼。
* @param name - 骨骼名称。
* @see dragonBones.Bone
* @version DragonBones 3.0
* @language zh_CN
*/
Bone* getBone(const std::string& name) const;
/**
* - Get a specific bone by the display.
* @param display - The display object.
* @see dragonBones.Bone
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 通过显示对象获取特定的骨骼。
* @param display - 显示对象。
* @see dragonBones.Bone
* @version DragonBones 3.0
* @language zh_CN
*/
Bone* getBoneByDisplay(void* display) const;
/**
* - Get a specific slot.
* @param name - The slot name.
* @see dragonBones.Slot
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 获取特定的插槽。
* @param name - 插槽名称。
* @see dragonBones.Slot
* @version DragonBones 3.0
* @language zh_CN
*/
Slot* getSlot(const std::string& name) const;
/**
* - Get a specific slot by the display.
* @param display - The display object.
* @see dragonBones.Slot
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 通过显示对象获取特定的插槽。
* @param display - 显示对象。
* @see dragonBones.Slot
* @version DragonBones 3.0
* @language zh_CN
*/
Slot* getSlotByDisplay(void* display) const;
/**
* - Get all bones.
* @see dragonBones.Bone
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 获取所有的骨骼。
* @see dragonBones.Bone
* @version DragonBones 3.0
* @language zh_CN
*/
inline const std::vector<Bone*>& getBones() const
{
return _bones;
}
/**
* - Get all slots.
* @see dragonBones.Slot
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 获取所有的插槽。
* @see dragonBones.Slot
* @version DragonBones 3.0
* @language zh_CN
*/
inline const std::vector<Slot*>& getSlots() const
{
return _slots;
}
/**
* - Whether to flip the armature horizontally.
* @version DragonBones 5.5
* @language en_US
*/
/**
* - 是否将骨架水平翻转。
* @version DragonBones 5.5
* @language zh_CN
*/
bool getFlipX() const
{
return _flipX;
}
void setFlipX(bool value)
{
_flipX = value;
invalidUpdate("");
}
/**
* - Whether to flip the armature vertically.
* @version DragonBones 5.5
* @language en_US
*/
/**
* - 是否将骨架垂直翻转。
* @version DragonBones 5.5
* @language zh_CN
*/
bool getFlipY() const
{
return _flipY;
}
void setFlipY(bool value)
{
_flipY = value;
invalidUpdate("");
}
/**
* - The animation cache frame rate, which turns on the animation cache when the set value is greater than 0.
* There is a certain amount of memory overhead to improve performance by caching animation data in memory.
* The frame rate should not be set too high, usually with the frame rate of the animation is similar and lower than the program running frame rate.
* When the animation cache is turned on, some features will fail, such as the offset property of bone.
* @example
* TypeScript style, for reference only.
* <pre>
* armature.cacheFrameRate = 24;
* </pre>
* @see dragonBones.DragonBonesData#frameRate
* @see dragonBones.ArmatureData#frameRate
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 动画缓存帧率,当设置的值大于 0 的时,将会开启动画缓存。
* 通过将动画数据缓存在内存中来提高运行性能,会有一定的内存开销。
* 帧率不宜设置的过高,通常跟动画的帧率相当且低于程序运行的帧率。
* 开启动画缓存后,某些功能将会失效,比如骨骼的 offset 属性等。
* @example
* TypeScript 风格,仅供参考。
* <pre>
* armature.cacheFrameRate = 24;
* </pre>
* @see dragonBones.DragonBonesData#frameRate
* @see dragonBones.ArmatureData#frameRate
* @version DragonBones 4.5
* @language zh_CN
*/
inline unsigned getCacheFrameRate() const
{
return _armatureData->cacheFrameRate;
}
void setCacheFrameRate(unsigned value);
/**
* - The armature name.
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 骨架名称。
* @version DragonBones 3.0
* @language zh_CN
*/
inline const std::string& getName() const
{
return _armatureData->name;
}
/**
* - The armature data.
* @see dragonBones.ArmatureData
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 骨架数据。
* @see dragonBones.ArmatureData
* @version DragonBones 4.5
* @language zh_CN
*/
inline const ArmatureData* getArmatureData() const
{
return _armatureData;
}
/**
* - The animation player.
* @see dragonBones.Animation
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 动画播放器。
* @see dragonBones.Animation
* @version DragonBones 3.0
* @language zh_CN
*/
inline Animation* getAnimation() const
{
return _animation;
}
/**
* @pivate
*/
inline IArmatureProxy* getProxy() const
{
return _proxy;
}
/**
* - The EventDispatcher instance of the armature.
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 该骨架的 EventDispatcher 实例。
* @version DragonBones 4.5
* @language zh_CN
*/
inline IEventDispatcher* getEventDispatcher() const
{
return _proxy;
}
/**
* - The display container.
* The display of the slot is displayed as the parent.
* Depending on the rendering engine, the type will be different, usually the DisplayObjectContainer type.
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 显示容器实例。
* 插槽的显示对象都会以此显示容器为父级。
* 根据渲染引擎的不同,类型会不同,通常是 DisplayObjectContainer 类型。
* @version DragonBones 3.0
* @language zh_CN
*/
inline void* getDisplay() const
{
return _display;
}
/**
* @private
*/
inline void* getReplacedTexture() const
{
return _replacedTexture;
}
void setReplacedTexture(void* value);
/**
* @inheritDoc
*/
inline WorldClock* getClock() const override
{
return _clock;
}
void setClock(WorldClock* value) override;
/**
* - Get the parent slot which the armature belongs to.
* @see dragonBones.Slot
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 该骨架所属的父插槽。
* @see dragonBones.Slot
* @version DragonBones 4.5
* @language zh_CN
*/
inline Slot* getParent() const
{
return _parent;
}
public: // For WebAssembly.
IAnimatable* getAnimatable() const { return (IAnimatable*)this; }
};
DRAGONBONES_NAMESPACE_END
#endif // DRAGONBONES_ARMATURE_H

View File

@@ -0,0 +1,432 @@
#include "Bone.h"
#include "../geom/Matrix.h"
#include "../geom/Transform.h"
#include "Armature.h"
#include "Slot.h"
#include "Constraint.h"
#include "../animation/AnimationState.h"
DRAGONBONES_NAMESPACE_BEGIN
void Bone::_onClear()
{
TransformObject::_onClear();
offsetMode = OffsetMode::Additive;
animationPose.identity();
_transformDirty = false;
_childrenTransformDirty = false;
_localDirty = true;
_hasConstraint = false;
_visible = true;
_cachedFrameIndex = -1;
_blendState.clear();
_boneData = nullptr;
_parent = nullptr;
_cachedFrameIndices = nullptr;
}
void Bone::_updateGlobalTransformMatrix(bool isCache)
{
const auto flipX = _armature->getFlipX();
const auto flipY = _armature->getFlipY() == DragonBones::yDown;
auto inherit = _parent != nullptr;
auto rotation = 0.0f;
if (offsetMode == OffsetMode::Additive)
{
if (origin != nullptr)
{
// global = *origin; // Copy.
// global.add(offset).add(animationPose);
global.x = origin->x + offset.x + animationPose.x;
global.scaleX = origin->scaleX * offset.scaleX * animationPose.scaleX;
global.scaleY = origin->scaleY * offset.scaleY * animationPose.scaleY;
if (DragonBones::yDown)
{
global.y = origin->y + offset.y + animationPose.y;
global.skew = origin->skew + offset.skew + animationPose.skew;
global.rotation = origin->rotation + offset.rotation + animationPose.rotation;
}
else
{
global.y = origin->y - offset.y + animationPose.y;
global.skew = origin->skew - offset.skew + animationPose.skew;
global.rotation = origin->rotation - offset.rotation + animationPose.rotation;
}
}
else
{
global = offset; // Copy.
if (!DragonBones::yDown)
{
global.y = -global.y;
global.skew = -global.skew;
global.rotation = -global.rotation;
}
global.add(animationPose);
}
}
else if (offsetMode == OffsetMode::None)
{
if (origin != nullptr)
{
global = *origin;
global.add(animationPose);
}
else
{
global = animationPose;
}
}
else
{
inherit = false;
global = offset;
if (!DragonBones::yDown)
{
global.y = -global.y;
global.skew = -global.skew;
global.rotation = -global.rotation;
}
}
if (inherit)
{
const auto& parentMatrix = _parent->globalTransformMatrix;
if (_boneData->inheritScale)
{
if (!_boneData->inheritRotation)
{
_parent->updateGlobalTransform();
if (flipX && flipY)
{
rotation = global.rotation - (_parent->global.rotation + Transform::PI);
}
else if (flipX)
{
rotation = global.rotation + _parent->global.rotation + Transform::PI;
}
else if (flipY)
{
rotation = global.rotation + _parent->global.rotation;
}
else
{
rotation = global.rotation - _parent->global.rotation;
}
global.rotation = rotation;
}
global.toMatrix(globalTransformMatrix);
globalTransformMatrix.concat(parentMatrix);
if (_boneData->inheritTranslation)
{
global.x = globalTransformMatrix.tx;
global.y = globalTransformMatrix.ty;
}
else
{
globalTransformMatrix.tx = global.x;
globalTransformMatrix.ty = global.y;
}
if (isCache)
{
global.fromMatrix(globalTransformMatrix);
}
else
{
_globalDirty = true;
}
}
else
{
if (_boneData->inheritTranslation)
{
const auto x = global.x;
const auto y = global.y;
global.x = parentMatrix.a * x + parentMatrix.c * y + parentMatrix.tx;
global.y = parentMatrix.b * x + parentMatrix.d * y + parentMatrix.ty;
}
else
{
if (flipX)
{
global.x = -global.x;
}
if (flipY)
{
global.y = -global.y;
}
}
if (_boneData->inheritRotation)
{
_parent->updateGlobalTransform();
if (_parent->global.scaleX < 0.0f)
{
rotation = global.rotation + _parent->global.rotation + Transform::PI;
}
else
{
rotation = global.rotation + _parent->global.rotation;
}
if (parentMatrix.a * parentMatrix.d - parentMatrix.b * parentMatrix.c < 0.0f)
{
rotation -= global.rotation * 2.0f;
if (flipX != flipY || _boneData->inheritReflection)
{
global.skew += Transform::PI;
}
if (!DragonBones::yDown)
{
global.skew = -global.skew;
}
}
global.rotation = rotation;
}
else if (flipX || flipY)
{
if (flipX && flipY)
{
rotation = global.rotation + Transform::PI;
}
else
{
if (flipX)
{
rotation = Transform::PI - global.rotation;
}
else
{
rotation = -global.rotation;
}
global.skew += Transform::PI;
}
global.rotation = rotation;
}
global.toMatrix(globalTransformMatrix);
}
}
else
{
if (flipX || flipY)
{
if (flipX)
{
global.x = -global.x;
}
if (flipY)
{
global.y = -global.y;
}
if (flipX && flipY)
{
rotation = global.rotation + Transform::PI;
}
else
{
if (flipX)
{
rotation = Transform::PI - global.rotation;
}
else
{
rotation = -global.rotation;
}
global.skew += Transform::PI;
}
global.rotation = rotation;
}
global.toMatrix(globalTransformMatrix);
}
}
void Bone::init(const BoneData* boneData, Armature* armatureValue)
{
if (_boneData != nullptr)
{
return;
}
_boneData = boneData;
_armature = armatureValue;
if (_boneData->parent != nullptr)
{
_parent = _armature->getBone(_boneData->parent->name);
}
_armature->_addBone(this);
//
origin = &(_boneData->transform);
}
void Bone::update(int cacheFrameIndex)
{
_blendState.dirty = false;
if (cacheFrameIndex >= 0 && _cachedFrameIndices != nullptr)
{
const auto cachedFrameIndex = (*_cachedFrameIndices)[cacheFrameIndex];
if (cachedFrameIndex >= 0 && _cachedFrameIndex == cachedFrameIndex) // Same cache.
{
_transformDirty = false;
}
else if (cachedFrameIndex >= 0) // Has been Cached.
{
_transformDirty = true;
_cachedFrameIndex = cachedFrameIndex;
}
else
{
if (_hasConstraint) // Update constraints.
{
for (const auto constraint : _armature->_constraints)
{
if (constraint->_root == this)
{
constraint->update();
}
}
}
if ( _transformDirty || (_parent != nullptr && _parent->_childrenTransformDirty)) // Dirty.
{
_transformDirty = true;
_cachedFrameIndex = -1;
}
else if (_cachedFrameIndex >= 0) // Same cache, but not set index yet.
{
_transformDirty = false;
(*_cachedFrameIndices)[cacheFrameIndex] = _cachedFrameIndex;
}
else // Dirty.
{
_transformDirty = true;
_cachedFrameIndex = -1;
}
}
}
else
{
if (_hasConstraint) // Update constraints.
{
for (const auto constraint : _armature->_constraints)
{
if (constraint->_root == this)
{
constraint->update();
}
}
}
if ( _transformDirty || (_parent != nullptr && _parent->_childrenTransformDirty)) // Dirty.
{
cacheFrameIndex = -1;
_transformDirty = true;
_cachedFrameIndex = -1;
}
}
if (_transformDirty)
{
_transformDirty = false;
_childrenTransformDirty = true;
//
if (_cachedFrameIndex < 0)
{
const auto isCache = cacheFrameIndex >= 0;
if (_localDirty)
{
_updateGlobalTransformMatrix(isCache);
}
if (isCache && _cachedFrameIndices != nullptr)
{
_cachedFrameIndex = (*_cachedFrameIndices)[cacheFrameIndex] = _armature->_armatureData->setCacheFrame(globalTransformMatrix, global);
}
}
else
{
_armature->_armatureData->getCacheFrame(globalTransformMatrix, global, _cachedFrameIndex);
}
//
}
else if (_childrenTransformDirty)
{
_childrenTransformDirty = false;
}
_localDirty = true;
}
void Bone::updateByConstraint()
{
if (_localDirty)
{
_localDirty = false;
if (_transformDirty || (_parent != nullptr && _parent->_childrenTransformDirty))
{
_updateGlobalTransformMatrix(true);
}
_transformDirty = true;
}
}
bool Bone::contains(const Bone* value) const
{
if (value == this)
{
return false;
}
auto ancestor = value;
while (ancestor != this && ancestor != nullptr)
{
ancestor = ancestor->getParent();
}
return ancestor == this;
}
void Bone::setVisible(bool value)
{
if (_visible == value)
{
return;
}
_visible = value;
for (const auto & slot : _armature->getSlots())
{
if (slot->getParent() == this)
{
slot->_updateVisible();
}
}
}
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,235 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2012-2018 DragonBones team and other contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef DRAGONBONES_BONE_H
#define DRAGONBONES_BONE_H
#include "TransformObject.h"
#include "../model/ArmatureData.h"
#include "../animation/AnimationState.h"
DRAGONBONES_NAMESPACE_BEGIN
/**
* - Bone is one of the most important logical units in the armature animation system,
* and is responsible for the realization of translate, rotation, scaling in the animations.
* A armature can contain multiple bones.
* @see dragonBones.BoneData
* @see dragonBones.Armature
* @see dragonBones.Slot
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 骨骼在骨骼动画体系中是最重要的逻辑单元之一,负责动画中的平移、旋转、缩放的实现。
* 一个骨架中可以包含多个骨骼。
* @see dragonBones.BoneData
* @see dragonBones.Armature
* @see dragonBones.Slot
* @version DragonBones 3.0
* @language zh_CN
*/
class Bone final : public TransformObject
{
BIND_CLASS_TYPE_A(Bone);
public:
/**
* - The offset mode.
* @see #offset
* @version DragonBones 5.5
* @language en_US
*/
/**
* - 偏移模式。
* @see #offset
* @version DragonBones 5.5
* @language zh_CN
*/
OffsetMode offsetMode;
/**
* @internal
*/
Transform animationPose;
/**
* @internal
*/
bool _transformDirty;
/**
* @internal
*/
bool _childrenTransformDirty;
/**
* @internal
*/
bool _hasConstraint;
/**
* @internal
*/
BlendState _blendState;
/**
* @internal
*/
const BoneData* _boneData;
/**
* @internal
*/
std::vector<int>* _cachedFrameIndices;
protected:
bool _localDirty;
bool _visible;
int _cachedFrameIndex;
/**
* @private
*/
Bone* _parent;
protected:
void _onClear() override;
void _updateGlobalTransformMatrix(bool isCache);
public:
/**
* @internal
*/
void init(const BoneData* boneData, Armature* armatureValue);
/**
* @internal
*/
void update(int cacheFrameIndex);
/**
* @internal
*/
void updateByConstraint();
/**
* - Forces the bone to update the transform in the next frame.
* When the bone is not animated or its animation state is finished, the bone will not continue to update,
* and when the skeleton must be updated for some reason, the method needs to be called explicitly.
* @example
* TypeScript style, for reference only.
* <pre>
* let bone = armature.getBone("arm");
* bone.offset.scaleX = 2.0;
* bone.invalidUpdate();
* </pre>
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 强制骨骼在下一帧更新变换。
* 当该骨骼没有动画状态或其动画状态播放完成时,骨骼将不在继续更新,而此时由于某些原因必须更新骨骼时,则需要显式调用该方法。
* @example
* TypeScript 风格,仅供参考。
* <pre>
* let bone = armature.getBone("arm");
* bone.offset.scaleX = 2.0;
* bone.invalidUpdate();
* </pre>
* @version DragonBones 3.0
* @language zh_CN
*/
inline void invalidUpdate()
{
_transformDirty = true;
}
/**
* - Check whether the bone contains a specific bone.
* @see dragonBones.Bone
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 检查该骨骼是否包含特定的骨骼。
* @see dragonBones.Bone
* @version DragonBones 3.0
* @language zh_CN
*/
bool contains(const Bone* value) const;
/**
* - The bone data.
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 骨骼数据。
* @version DragonBones 4.5
* @language zh_CN
*/
inline const BoneData* getBoneData() const
{
return _boneData;
}
/**
* - The visible of all slots in the bone.
* @default true
* @see dragonBones.Slot#visible
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 此骨骼所有插槽的可见。
* @default true
* @see dragonBones.Slot#visible
* @version DragonBones 3.0
* @language zh_CN
*/
inline bool getVisible() const
{
return _visible;
}
void setVisible(bool value);
/**
* - The bone name.
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 骨骼名称。
* @version DragonBones 3.0
* @language zh_CN
*/
inline const std::string& getName() const
{
return _boneData->name;
}
/**
* - The parent bone to which it belongs.
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 所属的父骨骼。
* @version DragonBones 3.0
* @language zh_CN
*/
inline Bone* getParent() const
{
return _parent;
}
public: // For WebAssembly.
inline int getOffsetMode() const { return (int)offsetMode; }
inline void setOffsetMode(int value) { offsetMode = (OffsetMode)value; }
};
DRAGONBONES_NAMESPACE_END
#endif // DRAGONBONES_BONE_H

View File

@@ -0,0 +1,183 @@
//
// Created by liangshuochen on 12/06/2017.
//
#include "Constraint.h"
#include "Armature.h"
#include "Bone.h"
DRAGONBONES_NAMESPACE_BEGIN
Matrix Constraint::_helpMatrix;
Transform Constraint::_helpTransform;
Point Constraint::_helpPoint;
void Constraint::_onClear()
{
_constraintData = nullptr;
_armature = nullptr;
_target = nullptr;
_root = nullptr;
_bone = nullptr;
}
void IKConstraint::_onClear()
{
Constraint::_onClear();
_scaleEnabled = false;
_bendPositive = false;
_weight = 1.0f;
}
void IKConstraint::_computeA()
{
const auto& ikGlobal = _target->global;
auto& global = _root->global;
auto& globalTransformMatrix = _root->globalTransformMatrix;
auto radian = std::atan2(ikGlobal.y - global.y, ikGlobal.x - global.x);
if (global.scaleX < 0.0f)
{
radian += Transform::PI;
}
global.rotation += Transform::normalizeRadian(radian - global.rotation) * _weight;
global.toMatrix(globalTransformMatrix);
}
void IKConstraint::_computeB()
{
const auto boneLength = _bone->_boneData->length;
const auto parent = _root;
const auto& ikGlobal = _target->global;
auto& parentGlobal = parent->global;
auto& global = _bone->global;
auto& globalTransformMatrix = _bone->globalTransformMatrix;
const auto x = globalTransformMatrix.a * boneLength;
const auto y = globalTransformMatrix.b * boneLength;
const auto lLL = x * x + y * y;
const auto lL = sqrt(lLL);
auto dX = global.x - parentGlobal.x;
auto dY = global.y - parentGlobal.y;
const auto lPP = dX * dX + dY * dY;
const auto lP = sqrt(lPP);
const auto rawRadian = global.rotation;
const auto rawParentRadian = parentGlobal.rotation;
const auto rawRadianA = std::atan2(dY, dX);
dX = ikGlobal.x - parentGlobal.x;
dY = ikGlobal.y - parentGlobal.y;
const auto lTT = dX * dX + dY * dY;
const auto lT = sqrt(lTT);
auto radianA = 0.0f;
if (lL + lP <= lT || lT + lL <= lP || lT + lP <= lL)
{
radianA = std::atan2(ikGlobal.y - parentGlobal.y, ikGlobal.x - parentGlobal.x);
if (lL + lP <= lT)
{
}
else if (lP < lL)
{
radianA += Transform::PI;
}
}
else
{
const auto h = (lPP - lLL + lTT) / (2.0f * lTT);
const auto r = sqrt(lPP - h * h * lTT) / lT;
const auto hX = parentGlobal.x + (dX * h);
const auto hY = parentGlobal.y + (dY * h);
const auto rX = -dY * r;
const auto rY = dX * r;
auto isPPR = false;
const auto parentParent = parent->getParent();
if (parentParent != nullptr)
{
auto parentParentMatrix = parentParent->globalTransformMatrix;
isPPR = parentParentMatrix.a * parentParentMatrix.d - parentParentMatrix.b * parentParentMatrix.c < 0.0f;
}
if (isPPR != _bendPositive)
{
global.x = hX - rX;
global.y = hY - rY;
}
else
{
global.x = hX + rX;
global.y = hY + rY;
}
radianA = std::atan2(global.y - parentGlobal.y, global.x - parentGlobal.x);
}
const auto dR = Transform::normalizeRadian(radianA - rawRadianA);
parentGlobal.rotation = rawParentRadian + dR * _weight;
parentGlobal.toMatrix(parent->globalTransformMatrix);
//
const auto currentRadianA = rawRadianA + dR * _weight;
global.x = parentGlobal.x + cos(currentRadianA) * lP;
global.y = parentGlobal.y + sin(currentRadianA) * lP;
//
auto radianB = std::atan2(ikGlobal.y - global.y, ikGlobal.x - global.x);
if (global.scaleX < 0.0f) {
radianB += Transform::PI;
}
global.rotation = parentGlobal.rotation + rawRadian - rawParentRadian + Transform::normalizeRadian(radianB - dR - rawRadian) * _weight;
global.toMatrix(globalTransformMatrix);
}
void IKConstraint::init(ConstraintData* constraintData, Armature* armature)
{
if (_constraintData != nullptr)
{
return;
}
_constraintData = constraintData;
_armature = armature;
_target = _armature->getBone(_constraintData->target->name);
_root = _armature->getBone(_constraintData->root->name);
_bone = _constraintData->bone != nullptr ? _armature->getBone(_constraintData->bone->name) : nullptr;
{
const auto ikConstraintData = static_cast<IKConstraintData*>(_constraintData);
_bendPositive = ikConstraintData->bendPositive;
_scaleEnabled = ikConstraintData->scaleEnabled;
_weight = ikConstraintData->weight;
}
_root->_hasConstraint = true;
}
void IKConstraint::update()
{
_root->updateByConstraint();
if (_bone != nullptr)
{
_bone->updateByConstraint();
_computeB();
}
else
{
_computeA();
}
}
void IKConstraint::invalidUpdate()
{
_root->invalidUpdate();
if (_bone != nullptr)
{
_bone->invalidUpdate();
}
}
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,119 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2012-2018 DragonBones team and other contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
//
// Created by liangshuochen on 12/06/2017.
//
#ifndef DRAGONBONESCPP_CONSTRAINTS_H
#define DRAGONBONESCPP_CONSTRAINTS_H
#include "../core/BaseObject.h"
#include "../geom/Matrix.h"
#include "../geom/Transform.h"
#include "../geom/Point.h"
#include "../model/ArmatureData.h"
#include "../model/ConstraintData.h"
DRAGONBONES_NAMESPACE_BEGIN
/**
* @internal
*/
class Constraint : public BaseObject
{
ABSTRACT_CLASS(Constraint)
protected:
static Matrix _helpMatrix;
static Transform _helpTransform;
static Point _helpPoint;
public:
/**
* - For timeline state.
* @internal
*/
ConstraintData* _constraintData;
/**
* - For sort bones.
* @internal
*/
Bone* _target;
/**
* - For sort bones.
* @internal
*/
Bone* _root;
protected:
Armature* _armature;
Bone* _bone;
virtual void _onClear() override;
public:
virtual void init(ConstraintData* constraintData, Armature* armature) = 0;
virtual void update() = 0;
virtual void invalidUpdate() = 0;
inline const std::string& getName()
{
return _constraintData->name;
}
};
/**
* @internal
*/
class IKConstraint : public Constraint
{
BIND_CLASS_TYPE_A(IKConstraint);
public:
/**
* - For timeline state.
* @internal
*/
bool _bendPositive;
/**
* - For timeline state.
* @internal
*/
float _weight;
private:
bool _scaleEnabled;
protected:
virtual void _onClear() override;
private:
void _computeA();
void _computeB();
public:
virtual void init(ConstraintData* constraintData, Armature* armature) override;
virtual void update() override;
virtual void invalidUpdate() override;
};
DRAGONBONES_NAMESPACE_END
#endif //DRAGONBONESCPP_CONSTRAINTS_H

View File

@@ -0,0 +1,75 @@
#include "DeformVertices.h"
#include "../model/DragonBonesData.h"
#include "../model/DisplayData.h"
#include "../armature/Armature.h"
#include "../armature/Bone.h"
DRAGONBONES_NAMESPACE_BEGIN
void DeformVertices::_onClear()
{
verticesDirty = false;
vertices.clear();
bones.clear();
verticesData = nullptr;
}
void DeformVertices::init(const VerticesData* verticesDataValue, Armature* armature)
{
verticesData = verticesDataValue;
if (verticesData != nullptr)
{
unsigned vertexCount = 0;
if (verticesData->weight != nullptr)
{
vertexCount = verticesData->weight->count * 2;
}
else {
vertexCount = verticesData->data->intArray[verticesData->offset + (unsigned)BinaryOffset::MeshVertexCount] * 2;
}
verticesDirty = true;
vertices.resize(vertexCount);
bones.clear();
//
for (std::size_t i = 0, l = vertices.size(); i < l; ++i)
{
vertices[i] = 0.0f;
}
if (verticesData->weight != nullptr)
{
for (std::size_t i = 0, l = verticesData->weight->bones.size(); i < l; ++i)
{
const auto bone = armature->getBone(verticesData->weight->bones[i]->name);
if (bone != nullptr)
{
bones.push_back(bone);
}
}
}
}
else
{
verticesDirty = false;
vertices.clear();
bones.clear();
verticesData = nullptr;
}
}
bool DeformVertices::isBonesUpdate() const
{
for (const auto bone : bones)
{
if (bone != nullptr && bone->_childrenTransformDirty)
{
return true;
}
}
return false;
}
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,52 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2012-2018 DragonBones team and other contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef DRAGONBONES_DEFORMVERTICES_H
#define DRAGONBONES_DEFORMVERTICES_H
#include "../core/BaseObject.h"
DRAGONBONES_NAMESPACE_BEGIN
/**
* @internal
*/
class DeformVertices : public BaseObject
{
BIND_CLASS_TYPE_A(DeformVertices);
public:
bool verticesDirty;
std::vector<float> vertices;
std::vector<Bone*> bones;
const VerticesData* verticesData;
protected:
virtual void _onClear() override;
public:
void init(const VerticesData* weightData, Armature* armature);
bool isBonesUpdate() const;
};
DRAGONBONES_NAMESPACE_END
#endif // DRAGONBONES_DEFORMVERTICES_H

View File

@@ -0,0 +1,124 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2012-2018 DragonBones team and other contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef DRAGONBONES_IARMATURE_PROXY_H
#define DRAGONBONES_IARMATURE_PROXY_H
#include "../core/DragonBones.h"
#include "../event/IEventDispatcher.h"
#include "MiddlewareManager.h"
DRAGONBONES_NAMESPACE_BEGIN
/**
* - The armature proxy interface, the docking engine needs to implement it concretely.
* @see dragonBones.Armature
* @version DragonBones 5.0
* @language en_US
*/
/**
* - 骨架代理接口,对接的引擎需要对其进行具体实现。
* @see dragonBones.Armature
* @version DragonBones 5.0
* @language zh_CN
*/
class IArmatureProxy : public IEventDispatcher
{
ABSTRACT_CLASS(IArmatureProxy);
public:
/**
* @internal
*/
virtual void dbInit(Armature* armature) = 0;
/**
* @internal
*/
virtual void dbClear() = 0;
/**
* @internal
*/
virtual void dbUpdate() = 0;
/**
* @internal
*/
virtual void dbRender() = 0;
/**
* - Dispose the instance and the Armature instance. (The Armature instance will return to the object pool)
* @example
* TypeScript style, for reference only.
* <pre>
* removeChild(armatureDisplay);
* armatureDisplay.dispose();
* </pre>
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 释放该实例和骨架。 (骨架会回收到对象池)
* @example
* TypeScript 风格,仅供参考。
* <pre>
* removeChild(armatureDisplay);
* armatureDisplay.dispose();
* </pre>
* @version DragonBones 4.5
* @language zh_CN
*/
virtual void dispose(bool disposeProxy) = 0;
/**
* - The armature.
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 骨架。
* @version DragonBones 4.5
* @language zh_CN
*/
virtual Armature* getArmature() const = 0;
/**
* - The animation player.
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 动画播放器。
* @version DragonBones 3.0
* @language zh_CN
*/
virtual Animation* getAnimation() const = 0;
/**
* - Gets render order
* @version Cocos Creator 2.3
* @language en_US
*/
/**
* - 获得渲染顺序。
* @version Cocos Creator 2.3
* @language zh_CN
*/
virtual uint32_t getRenderOrder() const = 0;
};
DRAGONBONES_NAMESPACE_END
#endif // DRAGONBONES_IARMATURE_PROXY_H

View File

@@ -0,0 +1,919 @@
#include "Slot.h"
#include "../model/DragonBonesData.h"
#include "../model/UserData.h"
#include "../model/SkinData.h"
#include "../model/DisplayData.h"
#include "../model/BoundingBoxData.h"
#include "../model/TextureAtlasData.h"
#include "Armature.h"
#include "Bone.h"
#include "DeformVertices.h"
#include "../animation/Animation.h"
#include "../event/EventObject.h"
DRAGONBONES_NAMESPACE_BEGIN
void Slot::_onClear()
{
TransformObject::_onClear();
std::vector<std::pair<void*, DisplayType>> disposeDisplayList;
for (const auto& pair : this->_displayList)
{
if (
pair.first != nullptr && pair.first != _rawDisplay && pair.first != _meshDisplay &&
std::find(disposeDisplayList.cbegin(), disposeDisplayList.cend(), pair) == disposeDisplayList.cend()
)
{
disposeDisplayList.push_back(pair);
}
}
for (const auto& pair : disposeDisplayList)
{
if (pair.second == DisplayType::Armature)
{
static_cast<Armature*>(pair.first)->returnToPool();
}
else
{
_disposeDisplay(pair.first, true);
}
}
if (_deformVertices != nullptr)
{
_deformVertices->returnToPool();
}
if (_meshDisplay && _meshDisplay != _rawDisplay)
{
_disposeDisplay(_meshDisplay, false);
}
if (_rawDisplay) {
_disposeDisplay(_rawDisplay, false);
}
displayController = "";
_displayDirty = false;
_zOrderDirty = false;
_blendModeDirty = false;
_colorDirty = false;
_transformDirty = false;
_visible = true;
_blendMode = BlendMode::Normal;
_displayIndex = -1;
_animationDisplayIndex = -1;
_zOrder = 0;
_cachedFrameIndex = -1;
_pivotX = 0.0f;
_pivotY = 0.0f;
_localMatrix.identity();
_colorTransform.identity();
_displayList.clear();
_displayDatas.clear();
_slotData = nullptr;
_rawDisplayDatas = nullptr; //
_displayData = nullptr;
_boundingBoxData = nullptr;
_textureData = nullptr;
_deformVertices = nullptr;
_rawDisplay = nullptr;
_meshDisplay = nullptr;
_display = nullptr;
_childArmature = nullptr;
_parent = nullptr;
_cachedFrameIndices = nullptr;
}
DisplayData* Slot::_getDefaultRawDisplayData(unsigned displayIndex) const
{
const auto defaultSkin = _armature->_armatureData->defaultSkin;
if (defaultSkin != nullptr)
{
const auto defaultRawDisplayDatas = defaultSkin->getDisplays(_slotData->name);
if (defaultRawDisplayDatas != nullptr)
{
return displayIndex < defaultRawDisplayDatas->size() ? (*defaultRawDisplayDatas)[displayIndex] : nullptr;
}
}
return nullptr;
}
void Slot::_updateDisplayData()
{
const auto prevDisplayData = _displayData;
const auto prevVerticesData = _deformVertices != nullptr ? _deformVertices->verticesData : nullptr;
const auto prevTextureData = _textureData;
DisplayData* rawDisplayData = nullptr;
VerticesData* currentVerticesData = nullptr;
_displayData = nullptr;
_boundingBoxData = nullptr;
_textureData = nullptr;
if (_displayIndex >= 0)
{
if (_rawDisplayDatas != nullptr)
{
rawDisplayData = (unsigned)_displayIndex < _rawDisplayDatas->size() ? (*_rawDisplayDatas)[_displayIndex] : nullptr;
}
if (rawDisplayData == nullptr)
{
rawDisplayData = _getDefaultRawDisplayData(_displayIndex);
}
if ((unsigned)_displayIndex < _displayDatas.size())
{
_displayData = _displayDatas[_displayIndex];
}
}
// Update texture and mesh data.
if (_displayData != nullptr)
{
if (_displayData->type == DisplayType::Mesh)
{
currentVerticesData = &static_cast<MeshDisplayData*>(_displayData)->vertices;
}
else if (_displayData->type == DisplayType::Path)
{
// TODO
}
else if (rawDisplayData != nullptr)
{
if (rawDisplayData->type == DisplayType::Mesh)
{
currentVerticesData = &static_cast<MeshDisplayData*>(rawDisplayData)->vertices;
}
else if (rawDisplayData->type == DisplayType::Path)
{
// TODO
}
}
if (_displayData->type == DisplayType::BoundingBox)
{
_boundingBoxData = static_cast<BoundingBoxDisplayData*>(_displayData)->boundingBox;
}
else if (rawDisplayData != nullptr)
{
if (rawDisplayData->type == DisplayType::BoundingBox)
{
_boundingBoxData = static_cast<BoundingBoxDisplayData*>(rawDisplayData)->boundingBox;
}
}
if (_displayData->type == DisplayType::Image)
{
_textureData = static_cast<ImageDisplayData*>(_displayData)->texture;
}
else if (_displayData->type == DisplayType::Mesh)
{
_textureData = static_cast<MeshDisplayData*>(_displayData)->texture;
}
}
// Update bounding box data.
if (_displayData != nullptr && _displayData->type == DisplayType::BoundingBox)
{
_boundingBoxData = static_cast<BoundingBoxDisplayData*>(_displayData)->boundingBox;
}
else if (rawDisplayData != nullptr && rawDisplayData->type == DisplayType::BoundingBox)
{
_boundingBoxData = static_cast<BoundingBoxDisplayData*>(rawDisplayData)->boundingBox;
}
else
{
_boundingBoxData = nullptr;
}
if (_displayData != prevDisplayData || currentVerticesData != prevVerticesData || _textureData != prevTextureData)
{
if (currentVerticesData == nullptr && _textureData != nullptr)
{
const auto imageDisplayData = static_cast<ImageDisplayData*>(_displayData);
const auto scale = _textureData->parent->scale * _armature->_armatureData->scale;
const auto frame = _textureData->frame;
_pivotX = imageDisplayData->pivot.x;
_pivotY = imageDisplayData->pivot.y;
const auto& rect = frame != nullptr ? *frame : _textureData->region;
float width = rect.width;
float height = rect.height;
if (_textureData->rotated && frame == nullptr)
{
width = rect.height;
height = rect.width;
}
_pivotX *= width * scale;
_pivotY *= height * scale;
if (frame != nullptr)
{
_pivotX += frame->x * scale;
_pivotY += frame->y * scale;
}
// Update replace pivot.
if (_displayData != nullptr && rawDisplayData != nullptr && _displayData != rawDisplayData)
{
rawDisplayData->transform.toMatrix(_helpMatrix);
_helpMatrix.invert();
_helpMatrix.transformPoint(0.0f, 0.0f, _helpPoint);
_pivotX -= _helpPoint.x;
_pivotY -= _helpPoint.y;
_displayData->transform.toMatrix(_helpMatrix);
_helpMatrix.invert();
_helpMatrix.transformPoint(0.0f, 0.0f, _helpPoint);
_pivotX += _helpPoint.x;
_pivotY += _helpPoint.y;
}
if (!DragonBones::yDown)
{
_pivotY = (_textureData->rotated ? _textureData->region.width : _textureData->region.height) * scale - _pivotY;
}
}
else
{
_pivotX = 0.0f;
_pivotY = 0.0f;
}
// Update original transform.
if (rawDisplayData != nullptr)
{
origin = &rawDisplayData->transform;
}
else if (_displayData != nullptr)
{
origin = &_displayData->transform;
}
else
{
origin = nullptr;
}
// Update vertices.
if (currentVerticesData != prevVerticesData)
{
if (_deformVertices == nullptr)
{
_deformVertices = BaseObject::borrowObject<DeformVertices>();
}
_deformVertices->init(currentVerticesData, _armature);
}
else if (_deformVertices != nullptr && _textureData != prevTextureData) // Update mesh after update frame.
{
_deformVertices->verticesDirty = true;
}
_displayDirty = true;
_transformDirty = true;
}
}
void Slot::_updateDisplay()
{
const auto prevDisplay = _display != nullptr ? _display : _rawDisplay;
const auto prevChildArmature = _childArmature;
// Update display and child armature.
if (_displayIndex >= 0 && (std::size_t)_displayIndex < _displayList.size())
{
const auto& displayPair = _displayList[_displayIndex];
_display = displayPair.first;
if (_display != nullptr && displayPair.second == DisplayType::Armature)
{
_childArmature = static_cast<Armature*>(displayPair.first);
_display = _childArmature->getDisplay();
}
else
{
_childArmature = nullptr;
}
}
else
{
_display = nullptr;
_childArmature = nullptr;
}
const auto currentDisplay = _display != nullptr ? _display : _rawDisplay;
if (currentDisplay != prevDisplay)
{
_onUpdateDisplay();
_replaceDisplay(prevDisplay, prevChildArmature != nullptr);
_transformDirty = true;
_visibleDirty = true;
_blendModeDirty = true;
_colorDirty = true;
}
// Update frame.
if (currentDisplay == _rawDisplay || currentDisplay == _meshDisplay)
{
_updateFrame();
}
// Update child armature.
if (_childArmature != prevChildArmature)
{
if (prevChildArmature != nullptr)
{
prevChildArmature->_parent = nullptr; // Update child armature parent.
prevChildArmature->setClock(nullptr);
if (prevChildArmature->inheritAnimation)
{
prevChildArmature->getAnimation()->reset();
}
}
if (_childArmature != nullptr)
{
_childArmature->_parent = this; // Update child armature parent.
_childArmature->setClock(_armature->getClock());
if (_childArmature->inheritAnimation) // Set child armature cache frameRate.
{
if (_childArmature->getCacheFrameRate() == 0)
{
const auto chacheFrameRate = this->_armature->getCacheFrameRate();
if (chacheFrameRate != 0)
{
_childArmature->setCacheFrameRate(chacheFrameRate);
}
}
// Child armature action.
std::vector<ActionData*>* actions = nullptr;
if (_displayData != nullptr && _displayData->type == DisplayType::Armature)
{
actions = &(static_cast<ArmatureDisplayData*>(_displayData)->actions);
}
else if(_displayIndex >= 0 && _rawDisplayDatas != nullptr)
{
auto rawDisplayData = (unsigned)_displayIndex < _rawDisplayDatas->size() ? (*_rawDisplayDatas)[_displayIndex] : nullptr;
if (rawDisplayData == nullptr)
{
rawDisplayData = _getDefaultRawDisplayData(_displayIndex);
}
if (rawDisplayData != nullptr && rawDisplayData->type == DisplayType::Armature)
{
actions = &(static_cast<ArmatureDisplayData*>(rawDisplayData)->actions);
}
}
if (actions != nullptr && !actions->empty())
{
for (const auto action : *actions)
{
const auto eventObject = BaseObject::borrowObject<EventObject>();
EventObject::actionDataToInstance(action, eventObject, _armature);
eventObject->slot = this;
_armature->_bufferAction(eventObject, false);
}
}
else
{
_childArmature->getAnimation()->play();
}
}
}
}
}
void Slot::_updateGlobalTransformMatrix(bool isCache)
{
const auto& parentMatrix = _parent->globalTransformMatrix;
globalTransformMatrix = _localMatrix; // Copy.
globalTransformMatrix.concat(parentMatrix);
if (isCache)
{
global.fromMatrix(globalTransformMatrix);
}
else
{
_globalDirty = true;
}
}
bool Slot::_setDisplayIndex(int value, bool isAnimation)
{
if (isAnimation)
{
if (_animationDisplayIndex == value)
{
return false;
}
_animationDisplayIndex = value;
}
if (_displayIndex == value)
{
return false;
}
_displayIndex = value;
_displayDirty = true;
_updateDisplayData();
return _displayDirty;
}
bool Slot::_setZorder(int value)
{
if (_zOrder == value)
{
//return false;
}
_zOrder = value;
_zOrderDirty = true;
return _zOrderDirty;
}
bool Slot::_setColor(const ColorTransform& value)
{
_colorTransform = value; // copy
_colorDirty = true;
return true;
}
bool Slot::_setDisplayList(const std::vector<std::pair<void*, DisplayType>>& value)
{
if (!value.empty())
{
if (_displayList.size() != value.size())
{
_displayList.resize(value.size());
}
for (std::size_t i = 0, l = value.size(); i < l; ++i)
{
const auto& eachPair = value[i];
if (
eachPair.first != nullptr && eachPair.first != _rawDisplay && eachPair.first != _meshDisplay &&
eachPair.second != DisplayType::Armature &&
std::find(_displayList.cbegin(), _displayList.cend(), eachPair) == _displayList.cend()
)
{
_initDisplay(eachPair.first, true);
}
_displayList[i].first = eachPair.first;
_displayList[i].second = eachPair.second;
}
}
else if (!_displayList.empty())
{
_displayList.clear();
}
if (_displayIndex >= 0 && (std::size_t)_displayIndex < _displayList.size())
{
_displayDirty = _display != _displayList[_displayIndex].first;
}
else
{
_displayDirty = _display != nullptr;
}
_updateDisplayData();
return _displayDirty;
}
void Slot::init(const SlotData* slotData, Armature* armatureValue, void* rawDisplay, void* meshDisplay)
{
if (_slotData != nullptr)
{
return;
}
_slotData = slotData;
//
_visibleDirty = true;
_blendModeDirty = true;
_colorDirty = true;
_blendMode = _slotData->blendMode;
_zOrder = _slotData->zOrder;
_colorTransform = *(_slotData->color);
_rawDisplay = rawDisplay;
_meshDisplay = meshDisplay;
//
_armature = armatureValue;
//
const auto slotParent = _armature->getBone(_slotData->parent->name);
if (slotParent != nullptr)
{
_parent = slotParent;
}
else
{
// Never;
}
_armature->_addSlot(this);
//
_initDisplay(_rawDisplay, false);
if (_rawDisplay != _meshDisplay)
{
_initDisplay(_meshDisplay, false);
}
_onUpdateDisplay();
_addDisplay();
}
void Slot::update(int cacheFrameIndex)
{
if (_displayDirty)
{
_displayDirty = false;
_updateDisplay();
// TODO remove slot offset.
if (_transformDirty) // Update local matrix. (Only updated when both display and transform are dirty.)
{
if (origin != nullptr)
{
global = *origin; // Copy.
global.add(offset).toMatrix(_localMatrix);
}
else
{
global = offset; // Copy.
global.toMatrix(_localMatrix);
}
}
}
if (_zOrderDirty)
{
_zOrderDirty = false;
_updateZOrder();
}
if (cacheFrameIndex >= 0 && _cachedFrameIndices != nullptr)
{
const auto cachedFrameIndex = (*_cachedFrameIndices)[cacheFrameIndex];
if (cachedFrameIndex >= 0 && _cachedFrameIndex == cachedFrameIndex) // Same cache.
{
_transformDirty = false;
}
else if (cachedFrameIndex >= 0) // Has been Cached.
{
_transformDirty = true;
_cachedFrameIndex = cachedFrameIndex;
}
else if (_transformDirty || _parent->_childrenTransformDirty) // Dirty.
{
_transformDirty = true;
_cachedFrameIndex = -1;
}
else if (_cachedFrameIndex >= 0) // Same cache, but not set index yet.
{
_transformDirty = false;
(*_cachedFrameIndices)[cacheFrameIndex] = _cachedFrameIndex;
}
else // Dirty.
{
_transformDirty = true;
_cachedFrameIndex = -1;
}
}
else if (_transformDirty || this->_parent->_childrenTransformDirty)
{
cacheFrameIndex = -1;
_transformDirty = true;
_cachedFrameIndex = -1;
}
if (_display == nullptr)
{
return;
}
if (_visibleDirty)
{
_visibleDirty = false;
_updateVisible();
}
if (_blendModeDirty)
{
_blendModeDirty = false;
_updateBlendMode();
}
if (_colorDirty)
{
_colorDirty = false;
_updateColor();
}
if (_deformVertices != nullptr && _deformVertices->verticesData != nullptr && _display == _meshDisplay)
{
const auto isSkinned = _deformVertices->verticesData->weight != nullptr;
if (
_deformVertices->verticesDirty ||
(isSkinned && _deformVertices->isBonesUpdate())
)
{
_deformVertices->verticesDirty = false;
_updateMesh();
}
if (isSkinned) // Compatible.
{
return;
}
}
if (_transformDirty)
{
_transformDirty = false;
if (_cachedFrameIndex < 0)
{
const auto isCache = cacheFrameIndex >= 0;
_updateGlobalTransformMatrix(isCache);
if (isCache && _cachedFrameIndices != nullptr)
{
_cachedFrameIndex = (*_cachedFrameIndices)[cacheFrameIndex] = _armature->_armatureData->setCacheFrame(globalTransformMatrix, global);
}
}
else
{
_armature->_armatureData->getCacheFrame(globalTransformMatrix, global, _cachedFrameIndex);
}
_updateTransform();
}
}
void Slot::updateTransformAndMatrix()
{
if (_transformDirty)
{
_transformDirty = false;
_updateGlobalTransformMatrix(false);
}
}
void Slot::replaceDisplayData(DisplayData *displayData, int displayIndex)
{
if (displayIndex < 0)
{
if (_displayIndex < 0)
{
displayIndex = 0;
}
else
{
displayIndex = _displayIndex;
}
}
if (_displayDatas.size() <= (unsigned)displayIndex) {
_displayDatas.resize(displayIndex + 1, nullptr);
}
_displayDatas[displayIndex] = displayData;
}
bool Slot::containsPoint(float x, float y)
{
if (_boundingBoxData == nullptr)
{
return false;
}
updateTransformAndMatrix();
_helpMatrix = globalTransformMatrix; // Copy.
_helpMatrix.invert();
_helpMatrix.transformPoint(x, y, _helpPoint);
return _boundingBoxData->containsPoint(_helpPoint.x, _helpPoint.y);
}
int Slot::intersectsSegment(
float xA, float yA, float xB, float yB,
Point* intersectionPointA,
Point* intersectionPointB,
Point* normalRadians
)
{
if (_boundingBoxData == nullptr)
{
return 0;
}
updateTransformAndMatrix();
_helpMatrix = globalTransformMatrix;
_helpMatrix.invert();
_helpMatrix.transformPoint(xA, yA, _helpPoint);
xA = _helpPoint.x;
yA = _helpPoint.y;
_helpMatrix.transformPoint(xB, yB, _helpPoint);
xB = _helpPoint.x;
yB = _helpPoint.y;
const auto intersectionCount = _boundingBoxData->intersectsSegment(xA, yA, xB, yB, intersectionPointA, intersectionPointB, normalRadians);
if (intersectionCount > 0)
{
if (intersectionCount == 1 || intersectionCount == 2)
{
if (intersectionPointA != nullptr)
{
globalTransformMatrix.transformPoint(intersectionPointA->x, intersectionPointA->y, *intersectionPointA);
if (intersectionPointB != nullptr)
{
intersectionPointB->x = intersectionPointA->x;
intersectionPointB->y = intersectionPointA->y;
}
}
else if (intersectionPointB != nullptr)
{
globalTransformMatrix.transformPoint(intersectionPointB->x, intersectionPointB->y, *intersectionPointB);
}
}
else
{
if (intersectionPointA != nullptr)
{
globalTransformMatrix.transformPoint(intersectionPointA->x, intersectionPointA->y, *intersectionPointA);
}
if (intersectionPointB != nullptr)
{
globalTransformMatrix.transformPoint(intersectionPointB->x, intersectionPointB->y, *intersectionPointB);
}
}
if (normalRadians != nullptr)
{
globalTransformMatrix.transformPoint(cos(normalRadians->x), sin(normalRadians->x), _helpPoint, true);
normalRadians->x = atan2(_helpPoint.y, _helpPoint.x);
globalTransformMatrix.transformPoint(cos(normalRadians->y), sin(normalRadians->y), _helpPoint, true);
normalRadians->y = atan2(_helpPoint.y, _helpPoint.x);
}
}
return intersectionCount;
}
void Slot::setVisible(bool value)
{
if (_visible == value)
{
return;
}
_visible = value;
_updateVisible();
}
void Slot::setDisplayIndex(int value)
{
if (_setDisplayIndex(value))
{
update(-1);
}
}
//TODO lsc check
void Slot::setDisplayList(const std::vector<std::pair<void*, DisplayType>>& value)
{
const auto backupDisplayList = _displayList; // copy
auto disposeDisplayList = backupDisplayList; // copy
disposeDisplayList.clear();
if (_setDisplayList(value))
{
update(-1);
}
for (const auto& pair : backupDisplayList)
{
if (
pair.first != nullptr && pair.first != _rawDisplay && pair.first != _meshDisplay &&
std::find(_displayList.cbegin(), _displayList.cend(), pair) == _displayList.cend() &&
std::find(disposeDisplayList.cbegin(), disposeDisplayList.cend(), pair) == disposeDisplayList.cend()
)
{
disposeDisplayList.push_back(pair);
}
}
for (const auto& pair : disposeDisplayList)
{
if (pair.second == DisplayType::Armature)
{
static_cast<Armature*>(pair.first)->returnToPool();
}
else
{
_disposeDisplay(pair.first, true);
}
}
}
void Slot::setRawDisplayDatas(const std::vector<DisplayData*>* value)
{
if (_rawDisplayDatas == value)
{
return;
}
_displayDirty = true;
_rawDisplayDatas = value;
if (_rawDisplayDatas != nullptr)
{
_displayDatas.resize(_rawDisplayDatas->size());
for (std::size_t i = 0, l = _displayDatas.size(); i < l; ++i)
{
auto rawDisplayData = (*_rawDisplayDatas)[i];
if (rawDisplayData == nullptr)
{
rawDisplayData = _getDefaultRawDisplayData(i);
}
_displayDatas[i] = rawDisplayData;
}
}
else
{
_displayDatas.clear();
}
}
void Slot::setDisplay(void* value, DisplayType displayType)
{
if (_display == value)
{
return;
}
const auto displayListLength = _displayList.size();
if (_displayIndex < 0 && displayListLength == 0) // Emprty
{
_displayIndex = 0;
}
if (_displayIndex < 0)
{
return;
}
else
{
auto relpaceDisplayList = _displayList; // copy
if (displayListLength <= (std::size_t)_displayIndex)
{
relpaceDisplayList.resize(_displayIndex + 1);
}
relpaceDisplayList[_displayIndex].first = value;
relpaceDisplayList[_displayIndex].second = displayType;
setDisplayList(relpaceDisplayList);
}
}
void Slot::setChildArmature(Armature* value)
{
if (_childArmature == value)
{
return;
}
setDisplay(value, DisplayType::Armature);
}
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,507 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2012-2018 DragonBones team and other contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef DRAGONBONES_SLOT_H
#define DRAGONBONES_SLOT_H
#include "TransformObject.h"
#include "../geom/ColorTransform.h"
#include "../model/ArmatureData.h"
DRAGONBONES_NAMESPACE_BEGIN
/**
* - The slot attached to the armature, controls the display status and properties of the display object.
* A bone can contain multiple slots.
* A slot can contain multiple display objects, displaying only one of the display objects at a time,
* but you can toggle the display object into frame animation while the animation is playing.
* The display object can be a normal texture, or it can be a display of a child armature, a grid display object,
* and a custom other display object.
* @see dragonBones.Armature
* @see dragonBones.Bone
* @see dragonBones.SlotData
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 插槽附着在骨骼上,控制显示对象的显示状态和属性。
* 一个骨骼上可以包含多个插槽。
* 一个插槽中可以包含多个显示对象,同一时间只能显示其中的一个显示对象,但可以在动画播放的过程中切换显示对象实现帧动画。
* 显示对象可以是普通的图片纹理,也可以是子骨架的显示容器,网格显示对象,还可以是自定义的其他显示对象。
* @see dragonBones.Armature
* @see dragonBones.Bone
* @see dragonBones.SlotData
* @version DragonBones 3.0
* @language zh_CN
*/
class Slot : public TransformObject
{
public:
/**
* - Displays the animated state or mixed group name controlled by the object, set to null to be controlled by all animation states.
* @default null
* @see dragonBones.AnimationState#displayControl
* @see dragonBones.AnimationState#name
* @see dragonBones.AnimationState#group
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 显示对象受到控制的动画状态或混合组名称,设置为 null 则表示受所有的动画状态控制。
* @default null
* @see dragonBones.AnimationState#displayControl
* @see dragonBones.AnimationState#name
* @see dragonBones.AnimationState#group
* @version DragonBones 4.5
* @language zh_CN
*/
std::string displayController;
public:
/**
* @internal
*/
bool _colorDirty;
BlendMode _blendMode;
/**
* @internal
*/
int _zOrder;
/**
* @internal
*/
float _pivotX;
/**
* @internal
*/
float _pivotY;
/**
* @internal
*/
ColorTransform _colorTransform;
/**
* @internal
*/
const SlotData* _slotData;
/**
* @internal
*/
DisplayData* _displayData;
/**
* @internal
*/
DeformVertices* _deformVertices;
void* _rawDisplay;
void* _meshDisplay;
/**
* @internal
*/
std::vector<int>* _cachedFrameIndices;
protected:
bool _displayDirty;
bool _zOrderDirty;
bool _visibleDirty;
bool _blendModeDirty;
bool _transformDirty;
bool _visible;
int _displayIndex;
int _animationDisplayIndex;
int _cachedFrameIndex;
Matrix _localMatrix;
std::vector<DisplayData*> _displayDatas;
std::vector<std::pair<void*, DisplayType>> _displayList;
const std::vector<DisplayData*>* _rawDisplayDatas;
BoundingBoxData* _boundingBoxData;
TextureData* _textureData;
void* _display;
Armature* _childArmature;
/**
* @private
*/
Bone* _parent;
public:
Slot() :
_deformVertices(nullptr),
_rawDisplay(nullptr),
_meshDisplay(nullptr)
{}
virtual ~Slot() {};
protected:
virtual void _onClear() override;
virtual void _initDisplay(void* value, bool isRetain) = 0;
virtual void _disposeDisplay(void* value, bool isRelease) = 0;
virtual void _onUpdateDisplay() = 0;
virtual void _addDisplay() = 0;
virtual void _replaceDisplay(void* value, bool isArmatureDisplay) = 0;
virtual void _removeDisplay() = 0;
virtual void _updateZOrder() = 0;
virtual void _updateFrame() = 0;
virtual void _updateMesh() = 0;
virtual void _updateTransform() = 0;
virtual void _identityTransform() = 0;
/**
* - Support default skin data.
*/
DisplayData* _getDefaultRawDisplayData(unsigned displayIndex) const;
void _updateDisplay();
void _updateDisplayData();
void _updateGlobalTransformMatrix(bool isCache);
public:
/**
* @internal
*/
virtual void _updateVisible() = 0;
virtual void _updateBlendMode() = 0;
virtual void _updateColor() = 0;
public:
/**
* @internal
*/
bool _setDisplayIndex(int value, bool isAnimation = false);
/**
* @internal
*/
bool _setZorder(int value);
/**
* @internal
*/
bool _setColor(const ColorTransform& value);
/**
* @internal
*/
bool _setDisplayList(const std::vector<std::pair<void*, DisplayType>>& value);
public:
/**
* @internal
*/
void init(const SlotData* slotData, Armature* armatureValue, void* rawDisplay, void* meshDisplay);
/**
* @internal
*/
void update(int cacheFrameIndex);
/**
* @private
*/
void updateTransformAndMatrix();
/**
* @private
*/
void replaceDisplayData(DisplayData* displayData, int displayIndex);
/**
* - Check whether a specific point is inside a custom bounding box in the slot.
* The coordinate system of the point is the inner coordinate system of the armature.
* Custom bounding boxes need to be customized in Dragonbones Pro.
* @param x - The horizontal coordinate of the point.
* @param y - The vertical coordinate of the point.
* @version DragonBones 5.0
* @language en_US
*/
/**
* - 检查特定点是否在插槽的自定义边界框内。
* 点的坐标系为骨架内坐标系。
* 自定义边界框需要在 DragonBones Pro 中自定义。
* @param x - 点的水平坐标。
* @param y - 点的垂直坐标。
* @version DragonBones 5.0
* @language zh_CN
*/
bool containsPoint(float x, float y);
/**
* - Check whether a specific segment intersects a custom bounding box for the slot.
* The coordinate system of the segment and intersection is the inner coordinate system of the armature.
* Custom bounding boxes need to be customized in Dragonbones Pro.
* @param xA - The horizontal coordinate of the beginning of the segment.
* @param yA - The vertical coordinate of the beginning of the segment.
* @param xB - The horizontal coordinate of the end point of the segment.
* @param yB - The vertical coordinate of the end point of the segment.
* @param intersectionPointA - The first intersection at which a line segment intersects the bounding box from the beginning to the end. (If not set, the intersection point will not calculated)
* @param intersectionPointB - The first intersection at which a line segment intersects the bounding box from the end to the beginning. (If not set, the intersection point will not calculated)
* @param normalRadians - The normal radians of the tangent of the intersection boundary box. [x: Normal radian of the first intersection tangent, y: Normal radian of the second intersection tangent] (If not set, the normal will not calculated)
* @returns Intersection situation. [1: Disjoint and segments within the bounding box, 0: Disjoint, 1: Intersecting and having a nodal point and ending in the bounding box, 2: Intersecting and having a nodal point and starting at the bounding box, 3: Intersecting and having two intersections, N: Intersecting and having N intersections]
* @version DragonBones 5.0
* @language en_US
*/
/**
* - 检查特定线段是否与插槽的自定义边界框相交。
* 线段和交点的坐标系均为骨架内坐标系。
* 自定义边界框需要在 DragonBones Pro 中自定义。
* @param xA - 线段起点的水平坐标。
* @param yA - 线段起点的垂直坐标。
* @param xB - 线段终点的水平坐标。
* @param yB - 线段终点的垂直坐标。
* @param intersectionPointA - 线段从起点到终点与边界框相交的第一个交点。 (如果未设置,则不计算交点)
* @param intersectionPointB - 线段从终点到起点与边界框相交的第一个交点。 (如果未设置,则不计算交点)
* @param normalRadians - 交点边界框切线的法线弧度。 [x: 第一个交点切线的法线弧度, y: 第二个交点切线的法线弧度] (如果未设置,则不计算法线)
* @returns 相交的情况。 [-1: 不相交且线段在包围盒内, 0: 不相交, 1: 相交且有一个交点且终点在包围盒内, 2: 相交且有一个交点且起点在包围盒内, 3: 相交且有两个交点, N: 相交且有 N 个交点]
* @version DragonBones 5.0
* @language zh_CN
*/
int intersectsSegment(
float xA, float yA, float xB, float yB,
Point* intersectionPointA = nullptr,
Point* intersectionPointB = nullptr,
Point* normalRadians = nullptr
);
/**
* - Forces the slot to update the state of the display object in the next frame.
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 强制插槽在下一帧更新显示对象的状态。
* @version DragonBones 4.5
* @language zh_CN
*/
inline void invalidUpdate()
{
_displayDirty = true;
_transformDirty = true;
}
/**
* - The visible of slot's display object.
* @default true
* @version DragonBones 5.6
* @language en_US
*/
/**
* - 插槽的显示对象的可见。
* @default true
* @version DragonBones 5.6
* @language zh_CN
*/
inline bool getVisible() const
{
return _visible;
}
void setVisible(bool value);
/**
* - The index of the display object displayed in the display list.
* @example
* TypeScript style, for reference only.
* <pre>
* let slot = armature.getSlot("weapon");
* slot.displayIndex = 3;
* slot.displayController = "none";
* </pre>
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 此时显示的显示对象在显示列表中的索引。
* @example
* TypeScript 风格,仅供参考。
* <pre>
* let slot = armature.getSlot("weapon");
* slot.displayIndex = 3;
* slot.displayController = "none";
* </pre>
* @version DragonBones 4.5
* @language zh_CN
*/
inline int getDisplayIndex() const
{
return _displayIndex;
}
void setDisplayIndex(int value);
/**
* - The slot name.
* @see dragonBones.SlotData#name
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 插槽名称。
* @see dragonBones.SlotData#name
* @version DragonBones 3.0
* @language zh_CN
*/
inline const std::string& getName() const
{
return _slotData->name;
}
/**
* - Contains a display list of display objects or child armatures.
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 包含显示对象或子骨架的显示列表。
* @version DragonBones 3.0
* @language zh_CN
*/
inline std::vector<std::pair<void*, DisplayType>> getDisplayList() const
{
return _displayList;
}
void setDisplayList(const std::vector<std::pair<void*, DisplayType>>& value);
/**
* @private
*/
inline const std::vector<DisplayData*>* getRawDisplayDatas() const
{
return _rawDisplayDatas;
}
void setRawDisplayDatas(const std::vector<DisplayData*>* value);
/**
* - The slot data.
* @see dragonBones.SlotData
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 插槽数据。
* @see dragonBones.SlotData
* @version DragonBones 4.5
* @language zh_CN
*/
const SlotData* getSlotData() const
{
return _slotData;
}
/**
* - The custom bounding box data for the slot at current time.
* @version DragonBones 5.0
* @language en_US
*/
/**
* - 插槽此时的自定义包围盒数据。
* @version DragonBones 5.0
* @language zh_CN
*/
inline BoundingBoxData* getBoundingBoxData() const
{
return _boundingBoxData;
}
/**
* @private
*/
inline void* getRawDisplay() const
{
return _rawDisplay;
}
/**
* @private
*/
inline void* getMeshDisplay() const
{
return _meshDisplay;
}
/**
* - The display object that the slot displays at this time.
* @example
* TypeScript style, for reference only.
* <pre>
* let slot = armature.getSlot("text");
* slot.display = new yourEngine.TextField();
* </pre>
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 插槽此时显示的显示对象。
* @example
* TypeScript 风格,仅供参考。
* <pre>
* let slot = armature.getSlot("text");
* slot.display = new yourEngine.TextField();
* </pre>
* @version DragonBones 3.0
* @language zh_CN
*/
inline void* getDisplay() const
{
return _display;
}
/**
* - Deprecated, please refer to {@link #display}.
* @deprecated
* @language en_US
*/
/**
* - 已废弃,请参考 {@link #display}。
* @deprecated
* @language zh_CN
*/
void setDisplay(void* value, DisplayType displayType);
/**
* - The child armature that the slot displayed at current time.
* @example
* TypeScript style, for reference only.
* <pre>
* let slot = armature.getSlot("weapon");
* let prevChildArmature = slot.childArmature;
* if (prevChildArmature) {
* prevChildArmature.dispose();
* }
* slot.childArmature = factory.buildArmature("weapon_blabla", "weapon_blabla_project");
* </pre>
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 插槽此时显示的子骨架。
* 注意,被替换的对象或子骨架并不会被回收,根据语言和引擎的不同,需要额外处理。
* @example
* TypeScript 风格,仅供参考。
* <pre>
* let slot = armature.getSlot("weapon");
* let prevChildArmature = slot.childArmature;
* if (prevChildArmature) {
* prevChildArmature.dispose();
* }
* slot.childArmature = factory.buildArmature("weapon_blabla", "weapon_blabla_project");
* </pre>
* @version DragonBones 3.0
* @language zh_CN
*/
inline Armature* getChildArmature() const
{
return _childArmature;
}
void setChildArmature(Armature* value);
/**
* - The parent bone to which it belongs.
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 所属的父骨骼。
* @version DragonBones 3.0
* @language zh_CN
*/
inline Bone* getParent() const
{
return _parent;
}
};
DRAGONBONES_NAMESPACE_END
#endif // DRAGONBONES_SLOT_H

View File

@@ -0,0 +1,34 @@
//
// Created by liangshuochen on 12/06/2017.
//
#include "TransformObject.h"
DRAGONBONES_NAMESPACE_BEGIN
Matrix TransformObject::_helpMatrix;
Transform TransformObject::_helpTransform;
Point TransformObject::_helpPoint;
void TransformObject::_onClear()
{
globalTransformMatrix.identity();
global.identity();
offset.identity();
origin = nullptr;
userData = nullptr;
_globalDirty = false;
_armature = nullptr;
}
void TransformObject::updateGlobalTransform()
{
if (_globalDirty)
{
_globalDirty = false;
global.fromMatrix(globalTransformMatrix);
}
}
DRAGONBONES_NAMESPACE_END

View File

@@ -0,0 +1,161 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2012-2018 DragonBones team and other contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef DRAGONBONES_TRANSFORM_OBJECT_H
#define DRAGONBONES_TRANSFORM_OBJECT_H
#include "../core/BaseObject.h"
#include "../geom/Matrix.h"
#include "../geom/Transform.h"
DRAGONBONES_NAMESPACE_BEGIN
/**
* - The base class of the transform object.
* @see dragonBones.Transform
* @version DragonBones 4.5
* @language en_US
*/
/**
* - 变换对象的基类。
* @see dragonBones.Transform
* @version DragonBones 4.5
* @language zh_CN
*/
class TransformObject : public BaseObject
{
ABSTRACT_CLASS(TransformObject);
protected:
static Matrix _helpMatrix;
static Transform _helpTransform;
static Point _helpPoint;
public:
/**
* - A matrix relative to the armature coordinate system.
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 相对于骨架坐标系的矩阵。
* @version DragonBones 3.0
* @language zh_CN
*/
Matrix globalTransformMatrix;
/**
* - A transform relative to the armature coordinate system.
* @see #updateGlobalTransform()
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 相对于骨架坐标系的变换。
* @see #updateGlobalTransform()
* @version DragonBones 3.0
* @language zh_CN
*/
Transform global;
/**
* - The offset transform relative to the armature or the parent bone coordinate system.
* @see #dragonBones.Bone#invalidUpdate()
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 相对于骨架或父骨骼坐标系的偏移变换。
* @see #dragonBones.Bone#invalidUpdate()
* @version DragonBones 3.0
* @language zh_CN
*/
Transform offset;
/**
* @private
*/
const Transform* origin;
/**
* @private
*/
void* userData;
public:
/**
* @internal
*/
Armature* _armature;
protected:
bool _globalDirty;
protected:
virtual void _onClear() override;
public:
/**
* - For performance considerations, rotation or scale in the {@link #global} attribute of the bone or slot is not always properly accessible,
* some engines do not rely on these attributes to update rendering, such as Egret.
* The use of this method ensures that the access to the {@link #global} property is correctly rotation or scale.
* @example
* TypeScript style, for reference only.
* <pre>
* bone.updateGlobalTransform();
* let rotation = bone.global.rotation;
* </pre>
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 出于性能的考虑,骨骼或插槽的 {@link #global} 属性中的旋转或缩放并不总是正确可访问的,有些引擎并不依赖这些属性更新渲染,比如 Egret。
* 使用此方法可以保证访问到 {@link #global} 属性中正确的旋转或缩放。
* @example
* TypeScript 风格,仅供参考。
* <pre>
* bone.updateGlobalTransform();
* let rotation = bone.global.rotation;
* </pre>
* @version DragonBones 3.0
* @language zh_CN
*/
void updateGlobalTransform();
/**
* - The armature to which it belongs.
* @version DragonBones 3.0
* @language en_US
*/
/**
* - 所属的骨架。
* @version DragonBones 3.0
* @language zh_CN
*/
inline Armature* getArmature() const
{
return _armature;
}
public: // For WebAssembly.
Matrix* getGlobalTransformMatrix() { return &globalTransformMatrix; }
Transform* getGlobal() { return &global; }
Transform* getOffset() { return &offset; }
const Transform* getOrigin() const { return origin; }
};
DRAGONBONES_NAMESPACE_END
#endif // DRAGONBONES_TRANSFORM_OBJECT_H