12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016 |
- using System.Collections.Generic;
- namespace DragonBones
- {
- /**
- * @language zh_CN
- * 骨架,是骨骼动画系统的核心,由显示容器、骨骼、插槽、动画、事件系统构成。
- * @see DragonBones.ArmatureData
- * @see DragonBones.Bone
- * @see DragonBones.Slot
- * @see DragonBones.Animation
- * @see DragonBones.IArmatureDisplay
- * @version DragonBones 3.0
- */
- public class Armature : BaseObject, IAnimateble
- {
- private static int _onSortSlots(Slot a, Slot b)
- {
- return a._zOrder > b._zOrder ? 1 : -1;
- }
- /**
- * @language zh_CN
- * 子骨架是否继承父骨架的动画。 [true: 继承, false: 不继承]
- * @default true
- * @version DragonBones 4.5
- */
- public bool inheritAnimation;
- /**
- * @language zh_CN
- * 可以用于存储临时数据。
- * @version DragonBones 3.0
- */
- public object userData;
-
- private bool _delayDispose;
- private bool _lockDispose;
- /**
- * @private
- */
- internal bool _bonesDirty;
- private bool _slotsDirty;
- private bool _zOrderDirty;
- /**
- * @private
- */
- internal bool _flipX;
- /**
- * @private
- */
- internal bool _flipY;
- private readonly List<Bone> _bones = new List<Bone>();
- private readonly List<Slot> _slots = new List<Slot>();
- private readonly List<ActionData> _actions = new List<ActionData>();
- private readonly List<EventObject> _events = new List<EventObject>();
- /**
- * @private
- */
- internal ArmatureData _armatureData;
- /**
- * @private
- */
- internal SkinData _skinData;
- private Animation _animation;
- private IArmatureProxy _proxy;
- private object _display;
- private IEventDispatcher<EventObject> _eventManager;
- /**
- * @private
- */
- internal Slot _parent;
- private WorldClock _clock;
- /**
- * @private
- */
- internal TextureAtlasData _replaceTextureAtlasData;
- private object _replacedTexture;
- /**
- * @private
- */
- public Armature()
- {
- }
- /**
- * @private
- */
- protected override void _onClear()
- {
- foreach (var bone in _bones)
- {
- bone.ReturnToPool();
- }
- foreach (var slot in _slots)
- {
- slot.ReturnToPool();
- }
- foreach (var evt in _events)
- {
- evt.ReturnToPool();
- }
- if (_clock != null)
- {
- _clock.Remove(this);
- }
- if (_proxy != null)
- {
- _proxy._onClear();
- }
- if (_replaceTextureAtlasData != null)
- {
- _replaceTextureAtlasData.ReturnToPool();
- }
- if (_animation != null)
- {
- _animation.ReturnToPool();
- }
- inheritAnimation = true;
- userData = null;
- _delayDispose = false;
- _lockDispose = false;
- _bonesDirty = false;
- _slotsDirty = false;
- _zOrderDirty = false;
- _flipX = false;
- _flipY = false;
- _bones.Clear();
- _slots.Clear();
- _actions.Clear();
- _events.Clear();
- _armatureData = null;
- _skinData = null;
- _animation = null;
- _proxy = null;
- _display = null;
- _eventManager = null;
- _parent = null;
- _clock = null;
- _replaceTextureAtlasData = null;
- _replacedTexture = null;
- }
-
- private void _sortBones()
- {
- var total = _bones.Count;
- if (total <= 0)
- {
- return;
- }
- var sortHelper = _bones.ToArray();
- int index = 0;
- int count = 0;
- _bones.Clear();
- while (count < total)
- {
- var bone = sortHelper[index++];
- if (index >= total)
- {
- index = 0;
- }
- if (_bones.Contains(bone))
- {
- continue;
- }
- if (bone.parent != null && !_bones.Contains(bone.parent))
- {
- continue;
- }
- if (bone.ik != null && !_bones.Contains(bone.ik))
- {
- continue;
- }
- if (bone.ik != null && bone.ikChain > 0 && bone.ikChainIndex == bone.ikChain)
- {
- _bones.Insert(_bones.IndexOf(bone.parent) + 1, bone); // ik, parent, bone, children
- }
- else
- {
- _bones.Add(bone);
- }
- count++;
- }
- }
-
- private void _sortSlots()
- {
- _slots.Sort(_onSortSlots);
- }
- private void _doAction(ActionData value)
- {
- switch (value.type)
- {
- case ActionType.Play:
- _animation.PlayConfig(value.animationConfig);
- break;
- default:
- break;
- }
- }
- /**
- * @private
- */
- internal void _init(
- ArmatureData armatureData, SkinData skinData,
- object display, IArmatureProxy proxy, IEventDispatcher<EventObject> eventManager
- )
- {
- if (_armatureData != null)
- {
- return;
- }
- _armatureData = armatureData;
- _skinData = skinData;
- _animation = BaseObject.BorrowObject<Animation>();
- _display = display;
- _proxy = proxy;
- _eventManager = eventManager;
- _animation._init(this);
- _animation.animations = _armatureData.animations;
- }
- /**
- * @private
- */
- internal void _addBoneToBoneList(Bone value)
- {
- if (!_bones.Contains(value))
- {
- _bonesDirty = true;
- _bones.Add(value);
- _animation._timelineStateDirty = true;
- }
- }
- /**
- * @private
- */
- internal void _removeBoneFromBoneList(Bone value)
- {
- if (_bones.Contains(value))
- {
- _bones.Remove(value);
- _animation._timelineStateDirty = true;
- }
- }
- /**
- * @private
- */
- internal void _addSlotToSlotList(Slot value)
- {
- if (!_slots.Contains(value))
- {
- _slotsDirty = true;
- _slots.Add(value);
- _animation._timelineStateDirty = true;
- }
- }
- /**
- * @private
- */
- internal void _removeSlotFromSlotList(Slot value)
- {
- if (_slots.Contains(value))
- {
- _slots.Remove(value);
- _animation._timelineStateDirty = true;
- }
- }
- /**
- * @private
- */
- public void _sortZOrder(List<int> slotIndices)
- {
- var sortedSlots = _armatureData.sortedSlots;
- var isOriginal = slotIndices == null || slotIndices.Count < 1;
- if (_zOrderDirty || !isOriginal)
- {
- for (int i = 0, l = sortedSlots.Count; i < l; ++i)
- {
- var slotIndex = isOriginal ? i : slotIndices[i];
- var slotData = sortedSlots[slotIndex];
- if (slotData != null)
- {
- var slot = GetSlot(slotData.name);
- if (slot != null)
- {
- slot._setZorder(i);
- }
- }
- }
- _slotsDirty = true;
- _zOrderDirty = !isOriginal;
- }
- }
- /**
- * @private
- */
- internal void _bufferAction(ActionData value)
- {
- _actions.Add(value);
- }
- /**
- * @private
- */
- internal void _bufferEvent(EventObject value, string type)
- {
- value.type = type;
- value.armature = this;
- _events.Add(value);
- }
- /**
- * @language zh_CN
- * 释放骨架。 (回收到对象池)
- * @version DragonBones 3.0
- */
- public void Dispose()
- {
- if (_armatureData != null)
- {
- if (_lockDispose)
- {
- _delayDispose = true;
- }
- else
- {
- ReturnToPool();
- }
- }
- }
- /**
- * @language zh_CN
- * 更新骨架和动画。
- * @param passedTime 两帧之间的时间间隔。 (以秒为单位)
- * @see DragonBones.IAnimateble
- * @see DragonBones.WorldClock
- * @version DragonBones 3.0
- */
- public void AdvanceTime(float passedTime)
- {
- if (_armatureData == null)
- {
- DragonBones.Assert(false, "The armature has been disposed.");
- return;
- }
- else if (_armatureData.parent == null)
- {
- DragonBones.Assert(false, "The armature data has been disposed.");
- return;
- }
- // Bones and slots.
- if (_bonesDirty)
- {
- _bonesDirty = false;
- _sortBones();
- }
- if (_slotsDirty)
- {
- _slotsDirty = false;
- _sortSlots();
- }
- var prevCacheFrameIndex = _animation._cacheFrameIndex;
- // Update animations.
- _animation._advanceTime(passedTime);
- var currentCacheFrameIndex = _animation._cacheFrameIndex;
-
- int i = 0, l = 0;
- if (currentCacheFrameIndex < 0 || currentCacheFrameIndex != prevCacheFrameIndex)
- {
- // Update bones.
- for (i = 0, l = _bones.Count; i < l; ++i)
- {
- var bone = _bones[i];
- bone._update(currentCacheFrameIndex);
- }
- // Update slots.
- for (i = 0, l = _slots.Count; i < l; ++i)
- {
- _slots[i]._update(currentCacheFrameIndex);
- }
- }
- //
- if (!_lockDispose)
- {
- _lockDispose = true;
- // Events. (Dispatch event before action.)
- l = _events.Count;
- if (l > 0)
- {
- for (i = 0; i < l; ++i)
- {
- var eventObject = _events[i];
- _proxy.DispatchEvent(eventObject.type, eventObject);
- if (eventObject.type == EventObject.SOUND_EVENT)
- {
- _eventManager.DispatchEvent(eventObject.type, eventObject);
- }
- eventObject.ReturnToPool();
- }
- _events.Clear();
- }
- // Actions.
- l = _actions.Count;
- if (l > 0)
- {
- for (i = 0; i < l; ++i)
- {
- var action = _actions[i];
- if (action.slot != null)
- {
- var slot = GetSlot(action.slot.name);
- if (slot != null)
- {
- var childArmature = slot.childArmature;
- if (childArmature != null)
- {
- childArmature._doAction(action);
- }
- }
- }
- else if (action.bone != null)
- {
- for (int iA = 0, lA = _slots.Count; iA < lA; ++iA)
- {
- var childArmature = _slots[iA].childArmature;
- if (childArmature != null)
- {
- childArmature._doAction(action);
- }
- }
- }
- else
- {
- _doAction(action);
- }
- }
- _actions.Clear();
- }
- _lockDispose = false;
- }
- if (_delayDispose)
- {
- ReturnToPool();
- }
- }
- /**
- * @language zh_CN
- * 更新骨骼和插槽。 (当骨骼没有动画状态或动画状态播放完成时,骨骼将不在更新)
- * @param boneName 指定的骨骼名称,如果未设置,将更新所有骨骼。
- * @param updateSlotDisplay 是否更新插槽的显示对象。
- * @see DragonBones.Bone
- * @see DragonBones.Slot
- * @version DragonBones 3.0
- */
- public void InvalidUpdate(string boneName = null, bool updateSlotDisplay = false)
- {
- if (!string.IsNullOrEmpty(boneName))
- {
- var bone = GetBone(boneName);
- if (bone != null)
- {
- bone.InvalidUpdate();
- if (updateSlotDisplay)
- {
- for (int i = 0, l = _slots.Count; i < l; ++i)
- {
- var slot = _slots[i];
- if (slot.parent == bone)
- {
- slot.InvalidUpdate();
- }
- }
- }
- }
- }
- else
- {
- for (int i = 0, l = _bones.Count; i < l; ++i)
- {
- _bones[i].InvalidUpdate();
- }
- if (updateSlotDisplay)
- {
- for (int i = 0, l = _slots.Count; i < l; ++i)
- {
- _slots[i].InvalidUpdate();
- }
- }
- }
- }
- /**
- * @language zh_CN
- * 判断点是否在所有插槽的自定义包围盒内。
- * @param x 点的水平坐标。(骨架内坐标系)
- * @param y 点的垂直坐标。(骨架内坐标系)
- * @version DragonBones 5.0
- */
- public Slot ContainsPoint(float x, float y)
- {
- for (int i = 0, l = _slots.Count; i < l; ++i)
- {
- var slot = _slots[i];
- if (slot.ContainsPoint(x, y))
- {
- return slot;
- }
- }
- return null;
- }
- /**
- * @language zh_CN
- * 判断线段是否与骨架的所有插槽的自定义包围盒相交。
- * @param xA 线段起点的水平坐标。(骨架内坐标系)
- * @param yA 线段起点的垂直坐标。(骨架内坐标系)
- * @param xB 线段终点的水平坐标。(骨架内坐标系)
- * @param yB 线段终点的垂直坐标。(骨架内坐标系)
- * @param intersectionPointA 线段从起点到终点与包围盒相交的第一个交点。(骨架内坐标系)
- * @param intersectionPointB 线段从终点到起点与包围盒相交的第一个交点。(骨架内坐标系)
- * @param normalRadians 碰撞点处包围盒切线的法线弧度。 [x: 第一个碰撞点处切线的法线弧度, y: 第二个碰撞点处切线的法线弧度]
- * @returns 线段从起点到终点相交的第一个自定义包围盒的插槽。
- * @version DragonBones 5.0
- */
- public Slot intersectsSegment(
- float xA, float yA, float xB, float yB,
- Point intersectionPointA = null,
- Point intersectionPointB = null,
- Point normalRadians = null
- )
- {
- var isV = xA == xB;
- var dMin = 0.0f;
- var dMax = 0.0f;
- var intXA = 0.0f;
- var intYA = 0.0f;
- var intXB = 0.0f;
- var intYB = 0.0f;
- var intAN = 0.0f;
- var intBN = 0.0f;
- Slot intSlotA = null;
- Slot intSlotB = null;
- for (int i = 0, l = _slots.Count; i < l; ++i)
- {
- var slot = _slots[i];
- var intersectionCount = slot.IntersectsSegment(xA, yA, xB, yB, intersectionPointA, intersectionPointB, normalRadians);
- if (intersectionCount > 0)
- {
- if (intersectionPointA != null || intersectionPointB != null)
- {
- if (intersectionPointA != null)
- {
- var d = isV ? intersectionPointA.y - yA : intersectionPointA.x - xA;
- if (d < 0.0f)
- {
- d = -d;
- }
- if (intSlotA == null || d < dMin)
- {
- dMin = d;
- intXA = intersectionPointA.x;
- intYA = intersectionPointA.y;
- intSlotA = slot;
- if (normalRadians != null)
- {
- intAN = normalRadians.x;
- }
- }
- }
- if (intersectionPointB != null)
- {
- var d = intersectionPointB.x - xA;
- if (d < 0.0f)
- {
- d = -d;
- }
- if (intSlotB == null || d > dMax)
- {
- dMax = d;
- intXB = intersectionPointB.x;
- intYB = intersectionPointB.y;
- intSlotB = slot;
- if (normalRadians != null)
- {
- intBN = normalRadians.y;
- }
- }
- }
- }
- else
- {
- intSlotA = slot;
- break;
- }
- }
- }
- if (intSlotA != null && intersectionPointA != null)
- {
- intersectionPointA.x = intXA;
- intersectionPointA.y = intYA;
- if (normalRadians != null)
- {
- normalRadians.x = intAN;
- }
- }
- if (intSlotB != null && intersectionPointB != null)
- {
- intersectionPointB.x = intXB;
- intersectionPointB.y = intYB;
- if (normalRadians != null)
- {
- normalRadians.y = intBN;
- }
- }
- return intSlotA;
- }
- /**
- * @language zh_CN
- * 获取骨骼。
- * @param name 骨骼的名称。
- * @returns 骨骼。
- * @see DragonBones.Bone
- * @version DragonBones 3.0
- */
- public Bone GetBone(string name)
- {
- foreach (var bone in _bones)
- {
- if (bone.name == name)
- {
- return bone;
- }
- }
- return null;
- }
- /**
- * @language zh_CN
- * 通过显示对象获取骨骼。
- * @param display 显示对象。
- * @returns 包含这个显示对象的骨骼。
- * @see DragonBones.Bone
- * @version DragonBones 3.0
- */
- public Bone GetBoneByDisplay(object display)
- {
- var slot = GetSlotByDisplay(display);
- return slot != null ? slot.parent : null;
- }
- /**
- * @language zh_CN
- * 获取插槽。
- * @param name 插槽的名称。
- * @returns 插槽。
- * @see DragonBones.Slot
- * @version DragonBones 3.0
- */
- public Slot GetSlot(string name)
- {
- foreach (var slot in _slots)
- {
- if (slot.name == name)
- {
- return slot;
- }
- }
- return null;
- }
- /**
- * @language zh_CN
- * 通过显示对象获取插槽。
- * @param display 显示对象。
- * @returns 包含这个显示对象的插槽。
- * @see DragonBones.Slot
- * @version DragonBones 3.0
- */
- public Slot GetSlotByDisplay(object display)
- {
- if (display != null)
- {
- foreach (var slot in _slots)
- {
- if (slot.display == display)
- {
- return slot;
- }
- }
- }
- return null;
- }
- /**
- * @deprecated
- */
- public void AddBone(Bone value, string parentName = null)
- {
- if (value != null)
- {
- value._setArmature(this);
- value._setParent(!string.IsNullOrEmpty(parentName) ? GetBone(parentName) : null);
- }
- else
- {
- DragonBones.Assert(false, DragonBones.ARGUMENT_ERROR);
- }
- }
- /**
- * @deprecated
- */
- public void AddSlot(Slot value, string parentName)
- {
- var bone = GetBone(parentName);
- if (bone != null)
- {
- value._setArmature(this);
- value._setParent(bone);
- }
- else
- {
- DragonBones.Assert(false, DragonBones.ARGUMENT_ERROR);
- }
- }
- /**
- * @language zh_CN
- * 替换骨架的主贴图,根据渲染引擎的不同,提供不同的贴图类型。
- * @param texture 贴图。
- * @version DragonBones 4.5
- */
- public void ReplaceTexture(object texture)
- {
- replacedTexture = texture;
- }
- /**
- * @language zh_CN
- * 获取所有骨骼。
- * @see DragonBones.Bone
- * @version DragonBones 3.0
- */
- public List<Bone> GetBones()
- {
- return _bones;
- }
- /**
- * @language zh_CN
- * 获取所有插槽。
- * @see DragonBones.Slot
- * @version DragonBones 3.0
- */
- public List<Slot> GetSlots()
- {
- return _slots;
- }
- /**
- * @language zh_CN
- * 骨架名称。
- * @see DragonBones.ArmatureData#name
- * @version DragonBones 3.0
- */
- public string name
- {
- get { return _armatureData != null ? _armatureData.name : null; }
- }
- /**
- * @language zh_CN
- * 获取骨架数据。
- * @see DragonBones.ArmatureData
- * @version DragonBones 4.5
- */
- public ArmatureData armatureData
- {
- get { return _armatureData; }
- }
- /**
- * @language zh_CN
- * 获得动画控制器。
- * @see DragonBones.Animation
- * @version DragonBones 3.0
- */
- public Animation animation
- {
- get { return _animation; }
- }
- /**
- * @language zh_CN
- * 获取事件监听器。
- * @version DragonBones 3.0
- */
- public IEventDispatcher<EventObject> eventDispatcher
- {
- get { return _proxy; }
- }
- /**
- * @language zh_CN
- * 获取显示容器,插槽的显示对象都会以此显示容器为父级,根据渲染平台的不同,类型会不同,通常是 DisplayObjectContainer 类型。
- * @version DragonBones 3.0
- */
- public object display
- {
- get { return _display; }
- }
- /**
- * @language zh_CN
- * 获取父插槽。 (当此骨架是某个骨架的子骨架时,可以通过此属性向上查找从属关系)
- * @see DragonBones.Slot
- * @version DragonBones 4.5
- */
- public Slot parent
- {
- get { return _parent; }
- }
- /**
- * @language zh_CN
- * 动画缓存帧率,当设置的值大于 0 的时,将会开启动画缓存。
- * 通过将动画数据缓存在内存中来提高运行性能,会有一定的内存开销。
- * 帧率不宜设置的过高,通常跟动画的帧率相当且低于程序运行的帧率。
- * 开启动画缓存后,某些功能将会失效,比如 Bone 和 Slot 的 offset 属性等。
- * @see DragonBones.DragonBonesData#frameRate
- * @see DragonBones.ArmatureData#frameRate
- * @version DragonBones 4.5
- */
- public uint cacheFrameRate
- {
- get { return _armatureData.cacheFrameRate; }
- set
- {
- if (_armatureData.cacheFrameRate != value)
- {
- _armatureData.CacheFrames(value);
- // Set child armature frameRate.
- foreach (var slot in _slots)
- {
- var childArmature = slot.childArmature;
- if (childArmature != null && childArmature.cacheFrameRate == 0)
- {
- childArmature.cacheFrameRate = value;
- }
- }
- }
- }
- }
- /**
- * @inheritDoc
- */
- public WorldClock clock
- {
- get { return _clock; }
- set
- {
- if (_clock == value)
- {
- return;
- }
- var prevClock = _clock;
- _clock = value;
- if (prevClock != null)
- {
- prevClock.Remove(this);
- }
- if (_clock != null)
- {
- _clock.Add(this);
- }
- // Update childArmature clock.
- for (int i = 0, l = _slots.Count; i < l; ++i)
- {
- var childArmature = _slots[i].childArmature;
- if (childArmature != null)
- {
- childArmature.clock = _clock;
- }
- }
- }
- }
- /**
- * @language zh_CN
- * 替换骨架的主贴图,根据渲染引擎的不同,提供不同的贴图数据。
- * @version DragonBones 4.5
- */
- public object replacedTexture
- {
- get { return _replacedTexture; }
- set
- {
- if (_replacedTexture == value)
- {
- return;
- }
- if (_replaceTextureAtlasData != null)
- {
- _replaceTextureAtlasData.ReturnToPool();
- _replaceTextureAtlasData = null;
- }
- _replacedTexture = value;
- for (int i = 0, l = _slots.Count; i < l; ++i)
- {
- var slot = _slots[i];
- slot.InvalidUpdate();
- slot._update(-1);
- }
- }
- }
- public bool flipX
- {
- get { return _flipX; }
- set
- {
- if (_flipX == value)
- {
- return;
- }
- _flipX = value;
-
- // Flipping child armature.
- foreach (var slot in _slots)
- {
- var childArmature = slot.childArmature;
- if (childArmature != null)
- {
- childArmature.flipX = _flipX;
- }
- }
- InvalidUpdate();
- }
- }
- public bool flipY
- {
- get { return _flipY; }
- set
- {
- if (_flipY == value)
- {
- return;
- }
- _flipY = value;
- // Flipping child armature.
- foreach (var slot in _slots)
- {
- var childArmature = slot.childArmature;
- if (childArmature != null)
- {
- childArmature.flipY = _flipY;
- }
- }
- InvalidUpdate();
- }
- }
- }
- }
|