| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638 |
- /**
- * The MIT License (MIT)
- *
- * Copyright (c) 2012-2017 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.
- */
- using System;
- using System.Collections.Generic;
- namespace DragonBones
- {
- /// <summary>
- /// - 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.
- /// </summary>
- /// <see cref="DragonBones.BoneData"/>
- /// <see cref="DragonBones.Armature"/>
- /// <see cref="DragonBones.Slot"/>
- /// <version>DragonBones 3.0</version>
- /// <language>en_US</language>
- /// <summary>
- /// - 骨骼在骨骼动画体系中是最重要的逻辑单元之一,负责动画中的平移、旋转、缩放的实现。
- /// 一个骨架中可以包含多个骨骼。
- /// </summary>
- /// <see cref="DragonBones.BoneData"/>
- /// <see cref="DragonBones.Armature"/>
- /// <see cref="DragonBones.Slot"/>
- /// <version>DragonBones 3.0</version>
- /// <language>zh_CN</language>
- public class Bone : TransformObject
- {
- /// <summary>
- /// - The offset mode.
- /// </summary>
- /// <see cref="offset"/>
- /// <version>DragonBones 5.5</version>
- /// <language>en_US</language>
- /// <summary>
- /// - 偏移模式。
- /// </summary>
- /// <see cref="offset"/>
- /// <version>DragonBones 5.5</version>
- /// <language>zh_CN</language>
- internal OffsetMode offsetMode;
- /// <internal/>
- /// <private/>
- internal readonly TransformDB animationPose = new TransformDB();
- /// <internal/>
- /// <private/>
- internal bool _transformDirty;
- /// <internal/>
- /// <private/>
- internal bool _childrenTransformDirty;
- private bool _localDirty;
- /// <internal/>
- /// <private/>
- internal bool _hasConstraint;
- private bool _visible;
- private int _cachedFrameIndex;
- /// <internal/>
- /// <private/>
- internal readonly BlendState _blendState = new BlendState();
- /// <internal/>
- /// <private/>
- internal BoneData _boneData;
- /// <private/>
- protected Bone _parent;
- /// <internal/>
- /// <private/>
- internal List<int> _cachedFrameIndices = new List<int>();
- /// <inheritDoc/>
- protected override void _OnClear()
- {
- base._OnClear();
- this.offsetMode = OffsetMode.Additive;
- this.animationPose.Identity();
- this._transformDirty = false;
- this._childrenTransformDirty = false;
- this._localDirty = true;
- this._hasConstraint = false;
- this._visible = true;
- this._cachedFrameIndex = -1;
- this._blendState.Clear();
- this._boneData = null; //
- this._parent = null;
- this._cachedFrameIndices = null;
- }
- /// <private/>
- private void _UpdateGlobalTransformMatrix(bool isCache)
- {
- var boneData = this._boneData;
- var parent = this._parent;
- var flipX = this._armature.flipX;
- var flipY = this._armature.flipY == DragonBones.yDown;
- var rotation = 0.0f;
- var global = this.global;
- var inherit = parent != null;
- var globalTransformMatrix = this.globalTransformMatrix;
- if (this.offsetMode == OffsetMode.Additive)
- {
- if (this.origin != null)
- {
- //global.CopyFrom(this.origin).Add(this.offset).Add(this.animationPose);
- global.x = this.origin.x + this.offset.x + this.animationPose.x;
- global.y = this.origin.y + this.offset.y + this.animationPose.y;
- global.skew = this.origin.skew + this.offset.skew + this.animationPose.skew;
- global.rotation = this.origin.rotation + this.offset.rotation + this.animationPose.rotation;
- global.scaleX = this.origin.scaleX * this.offset.scaleX * this.animationPose.scaleX;
- global.scaleY = this.origin.scaleY * this.offset.scaleY * this.animationPose.scaleY;
- }
- else
- {
- global.CopyFrom(this.offset).Add(this.animationPose);
- }
- }
- else if (this.offsetMode == OffsetMode.None)
- {
- if (this.origin != null)
- {
- global.CopyFrom(this.origin).Add(this.animationPose);
- }
- else
- {
- global.CopyFrom(this.animationPose);
- }
- }
- else
- {
- inherit = false;
- global.CopyFrom(this.offset);
- }
- if (inherit)
- {
- var parentMatrix = parent.globalTransformMatrix;
- if (boneData.inheritScale)
- {
- if (!boneData.inheritRotation)
- {
- parent.UpdateGlobalTransform();
- if (flipX && flipY)
- {
- rotation = global.rotation - (parent.global.rotation + TransformDB.PI);
- }
- else if (flipX)
- {
- rotation = global.rotation + parent.global.rotation + TransformDB.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 (this._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
- {
- this._globalDirty = true;
- }
- }
- else
- {
- if (boneData.inheritTranslation)
- {
- var x = global.x;
- var 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.0)
- {
- rotation = global.rotation + parent.global.rotation + TransformDB.PI;
- }
- else
- {
- rotation = global.rotation + parent.global.rotation;
- }
- if (parentMatrix.a * parentMatrix.d - parentMatrix.b * parentMatrix.c < 0.0)
- {
- rotation -= global.rotation * 2.0f;
- if (flipX != flipY || boneData.inheritReflection)
- {
- global.skew += TransformDB.PI;
- }
- }
- global.rotation = rotation;
- }
- else if (flipX || flipY)
- {
- if (flipX && flipY)
- {
- rotation = global.rotation + TransformDB.PI;
- }
- else
- {
- if (flipX)
- {
- rotation = TransformDB.PI - global.rotation;
- }
- else
- {
- rotation = -global.rotation;
- }
- global.skew += TransformDB.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 + TransformDB.PI;
- }
- else
- {
- if (flipX)
- {
- rotation = TransformDB.PI - global.rotation;
- }
- else
- {
- rotation = -global.rotation;
- }
- global.skew += TransformDB.PI;
- }
- global.rotation = rotation;
- }
- global.ToMatrix(globalTransformMatrix);
- }
- }
- /// <internal/>
- /// <private/>
- internal void Init(BoneData boneData, Armature armatureValue)
- {
- if (this._boneData != null)
- {
- return;
- }
- this._boneData = boneData;
- this._armature = armatureValue;
- if (this._boneData.parent != null)
- {
- this._parent = this._armature.GetBone(this._boneData.parent.name);
- }
- this._armature._AddBone(this);
- //
- this.origin = this._boneData.transform;
- }
- /// <internal/>
- /// <private/>
- internal void Update(int cacheFrameIndex)
- {
- this._blendState.dirty = false;
- if (cacheFrameIndex >= 0 && this._cachedFrameIndices != null)
- {
- var cachedFrameIndex = this._cachedFrameIndices[cacheFrameIndex];
- if (cachedFrameIndex >= 0 && this._cachedFrameIndex == cachedFrameIndex)
- {
- // Same cache.
- this._transformDirty = false;
- }
- else if (cachedFrameIndex >= 0)
- {
- // Has been Cached.
- this._transformDirty = true;
- this._cachedFrameIndex = cachedFrameIndex;
- }
- else
- {
- if (this._hasConstraint)
- {
- // Update constraints.
- foreach (var constraint in this._armature._constraints)
- {
- if (constraint._root == this)
- {
- constraint.Update();
- }
- }
- }
- if (this._transformDirty || (this._parent != null && this._parent._childrenTransformDirty))
- {
- // Dirty.
- this._transformDirty = true;
- this._cachedFrameIndex = -1;
- }
- else if (this._cachedFrameIndex >= 0)
- {
- // Same cache, but not set index yet.
- this._transformDirty = false;
- this._cachedFrameIndices[cacheFrameIndex] = this._cachedFrameIndex;
- }
- else
- {
- // Dirty.
- this._transformDirty = true;
- this._cachedFrameIndex = -1;
- }
- }
- }
- else
- {
- if (this._hasConstraint)
- {
- // Update constraints.
- foreach (var constraint in this._armature._constraints)
- {
- if (constraint._root == this)
- {
- constraint.Update();
- }
- }
- }
- if (this._transformDirty || (this._parent != null && this._parent._childrenTransformDirty))
- {
- // Dirty.
- cacheFrameIndex = -1;
- this._transformDirty = true;
- this._cachedFrameIndex = -1;
- }
- }
- if (this._transformDirty)
- {
- this._transformDirty = false;
- this._childrenTransformDirty = true;
- if (this._cachedFrameIndex < 0)
- {
- var isCache = cacheFrameIndex >= 0;
- if (this._localDirty)
- {
- this._UpdateGlobalTransformMatrix(isCache);
- }
- if (isCache && this._cachedFrameIndices != null)
- {
- this._cachedFrameIndex = this._cachedFrameIndices[cacheFrameIndex] = this._armature._armatureData.SetCacheFrame(this.globalTransformMatrix, this.global);
- }
- }
- else
- {
- this._armature._armatureData.GetCacheFrame(this.globalTransformMatrix, this.global, this._cachedFrameIndex);
- }
- }
- else if (this._childrenTransformDirty)
- {
- this._childrenTransformDirty = false;
- }
- this._localDirty = true;
- }
- /// <internal/>
- /// <private/>
- internal void UpdateByConstraint()
- {
- if (this._localDirty)
- {
- this._localDirty = false;
- if (this._transformDirty || (this._parent != null && this._parent._childrenTransformDirty))
- {
- this._UpdateGlobalTransformMatrix(true);
- }
- this._transformDirty = true;
- }
- }
- /// <summary>
- /// - 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.
- /// </summary>
- /// <example>
- /// TypeScript style, for reference only.
- /// <pre>
- /// let bone = armature.getBone("arm");
- /// bone.offset.scaleX = 2.0;
- /// bone.invalidUpdate();
- /// </pre>
- /// </example>
- /// <version>DragonBones 3.0</version>
- /// <language>en_US</language>
- /// <summary>
- /// - 强制骨骼在下一帧更新变换。
- /// 当该骨骼没有动画状态或其动画状态播放完成时,骨骼将不在继续更新,而此时由于某些原因必须更新骨骼时,则需要显式调用该方法。
- /// </summary>
- /// <example>
- /// TypeScript 风格,仅供参考。
- /// <pre>
- /// let bone = armature.getBone("arm");
- /// bone.offset.scaleX = 2.0;
- /// bone.invalidUpdate();
- /// </pre>
- /// </example>
- /// <version>DragonBones 3.0</version>
- /// <language>zh_CN</language>
- public void InvalidUpdate()
- {
- this._transformDirty = true;
- }
- /// <summary>
- /// - Check whether the bone contains a specific bone or slot.
- /// </summary>
- /// <see cref="DragonBones.Bone"/>
- /// <see cref="DragonBones.Slot"/>
- /// <version>DragonBones 3.0</version>
- /// <language>en_US</language>
- /// <summary>
- /// - 检查该骨骼是否包含特定的骨骼或插槽。
- /// </summary>
- /// <see cref="DragonBones.Bone"/>
- /// <see cref="DragonBones.Slot"/>
- /// <version>DragonBones 3.0</version>
- /// <language>zh_CN</language>
- public bool Contains(Bone value)
- {
- if (value == this)
- {
- return false;
- }
- Bone ancestor = value;
- while (ancestor != this && ancestor != null)
- {
- ancestor = ancestor.parent;
- }
- return ancestor == this;
- }
- /// <summary>
- /// - The bone data.
- /// </summary>
- /// <version>DragonBones 4.5</version>
- /// <language>en_US</language>
- /// <summary>
- /// - 骨骼数据。
- /// </summary>
- /// <version>DragonBones 4.5</version>
- /// <language>zh_CN</language>
- public BoneData boneData
- {
- get { return this._boneData; }
- }
- /// <summary>
- /// - The visible of all slots in the bone.
- /// </summary>
- /// <default>true</default>
- /// <see cref="DragonBones.Slot.visible"/>
- /// <version>DragonBones 3.0</version>
- /// <language>en_US</language>
- /// <summary>
- /// - 此骨骼所有插槽的可见。
- /// </summary>
- /// <default>true</default>
- /// <see cref="DragonBones.Slot.visible"/>
- /// <version>DragonBones 3.0</version>
- /// <language>zh_CN</language>
- public bool visible
- {
- get { return this._visible; }
- set
- {
- if (this._visible == value)
- {
- return;
- }
- this._visible = value;
- foreach (var slot in this._armature.GetSlots())
- {
- if (slot.parent == this)
- {
- slot._UpdateVisible();
- }
- }
- }
- }
- /// <summary>
- /// - The bone name.
- /// </summary>
- /// <version>DragonBones 3.0</version>
- /// <language>en_US</language>
- /// <summary>
- /// - 骨骼名称。
- /// </summary>
- /// <version>DragonBones 3.0</version>
- /// <language>zh_CN</language>
- public string name
- {
- get { return this._boneData.name; }
- }
- /// <summary>
- /// - The parent bone to which it belongs.
- /// </summary>
- /// <version>DragonBones 3.0</version>
- /// <language>en_US</language>
- /// <summary>
- /// - 所属的父骨骼。
- /// </summary>
- /// <version>DragonBones 3.0</version>
- /// <language>zh_CN</language>
- public Bone parent
- {
- get { return this._parent; }
- }
- /// <summary>
- /// - Deprecated, please refer to {@link dragonBones.Armature#getSlot()}.
- /// </summary>
- /// <language>en_US</language>
- /// <summary>
- /// - 已废弃,请参考 {@link dragonBones.Armature#getSlot()}。
- /// </summary>
- /// <language>zh_CN</language>
- [System.Obsolete("")]
- public Slot slot
- {
- get
- {
- foreach (var slot in this._armature.GetSlots())
- {
- if (slot.parent == this)
- {
- return slot;
- }
- }
- return null;
- }
- }
- }
- }
|