This commit is contained in:
Stephen Gowen 2017-10-03 18:47:25 -04:00
parent d173aa7e7d
commit 08af18e86e
2 changed files with 153 additions and 72 deletions

View File

@ -31,97 +31,78 @@
#ifndef Spine_Skin_h #ifndef Spine_Skin_h
#define Spine_Skin_h #define Spine_Skin_h
#include <string>
#include <vector>
#include <unordered_map>
namespace Spine namespace Spine
{ {
class Attachment;
class Skeleton;
class AttachmentKey;
/// Stores attachments by slot index and attachment name. /// Stores attachments by slot index and attachment name.
/// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and /// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and
/// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide. /// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide.
class Skin class Skin
{ {
public: public:
public std::string Name { get { return name; } } Skin(std::string name);
public Dictionary<AttachmentKeyTuple, Attachment> Attachments { get { return attachments; } }
public Skin (std::string name) { /// Adds an attachment to the skin for the specified slot index and name.
if (name == null) throw new ArgumentNullException("name", "name cannot be null."); /// If the name already exists for the slot, the previous value is replaced.
this.name = name; void addAttachment(int slotIndex, std::string name, Attachment* attachment);
}
/// Adds an attachment to the skin for the specified slot index and name. If the name already exists for the slot, the previous value is replaced.
public void AddAttachment (int slotIndex, std::string name, Attachment attachment) {
if (attachment == null) throw new ArgumentNullException("attachment", "attachment cannot be null.");
attachments[new AttachmentKeyTuple(slotIndex, name)] = attachment;
}
/// Returns the attachment for the specified slot index and name, or null. /// Returns the attachment for the specified slot index and name, or null.
/// <returns>May be null.</returns> Attachment* getAttachment(int slotIndex, std::string name);
public Attachment GetAttachment (int slotIndex, std::string name) {
Attachment attachment;
attachments.TryGetValue(new AttachmentKeyTuple(slotIndex, name), out attachment);
return attachment;
}
/// Finds the skin keys for a given slot. The results are added to the passed List(names). /// Finds the skin keys for a given slot. The results are added to the passed vector names.
/// <param name="slotIndex">The target slotIndex. To find the slot index, use <see cref="Spine.Skeleton.FindSlotIndex"/> or <see cref="Spine.SkeletonData.FindSlotIndex"/> /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex
/// <param name="names">Found skin key names will be added to this list.</param> /// @param names Found skin key names will be added to this vector.
public void FindNamesForSlot (int slotIndex, List<std::string> names) { void findNamesForSlot(int slotIndex, std::vector<std::string>& names);
if (names == null) throw new ArgumentNullException("names", "names cannot be null.");
foreach (AttachmentKeyTuple key in attachments.Keys)
if (key.slotIndex == slotIndex) names.Add(key.name);
}
/// Finds the attachments for a given slot. The results are added to the passed List(Attachment). /// Finds the attachments for a given slot. The results are added to the passed List(Attachment).
/// <param name="slotIndex">The target slotIndex. To find the slot index, use <see cref="Spine.Skeleton.FindSlotIndex"/> or <see cref="Spine.SkeletonData.FindSlotIndex"/> /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex
/// <param name="attachments">Found Attachments will be added to this list.</param> /// @param attachments Found Attachments will be added to this vector.
public void FindAttachmentsForSlot (int slotIndex, List<Attachment> attachments) { void findAttachmentsForSlot(int slotIndex, std::vector<Attachment*>& attachments);
if (attachments == null) throw new ArgumentNullException("attachments", "attachments cannot be null.");
foreach (KeyValuePair<AttachmentKeyTuple, Attachment> entry in this.attachments)
if (entry.Key.slotIndex == slotIndex) attachments.Add(entry.Value);
}
override public std::string ToString () { const std::string& getName();
return name; std::unordered_map<AttachmentKey, Attachment*>& getAttachments();
}
private: private:
internal std::string name; const std::string _name;
Dictionary<AttachmentKeyTuple, Attachment> attachments = new Dictionary<AttachmentKeyTuple, Attachment>(AttachmentKeyTupleComparer.Instance); std::unordered_map<AttachmentKey, Attachment*> _attachments;
/// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached.
internal void AttachAll (Skeleton skeleton, Skin oldSkin) { void attachAll(Skeleton& skeleton, Skin& oldSkin);
foreach (KeyValuePair<AttachmentKeyTuple, Attachment> entry in oldSkin.attachments) {
int slotIndex = entry.Key.slotIndex; class AttachmentKey
Slot slot = skeleton.slots.Items[slotIndex]; {
if (slot.Attachment == entry.Value) { public:
Attachment attachment = GetAttachment(slotIndex, entry.Key.name); const int _slotIndex;
if (attachment != null) slot.Attachment = attachment; const std::string _name;
AttachmentKey(int slotIndex, std::string name);
bool operator==(const AttachmentKey &other) const;
};
friend std::ostream& operator <<(std::ostream& os, const Skin& ref);
namespace std
{
template <>
struct hash<AttachmentKey>
{
size_t operator()(const AttachmentKey& val) const
{
size_t h1 = hash<int>{}(val._slotIndex);
size_t h2 = hash<string>{}(val._name);
return h1 ^ (h2 << 1);
} }
} };
}
public struct AttachmentKeyTuple {
public readonly int slotIndex;
public readonly std::string name;
internal readonly int nameHashCode;
public AttachmentKeyTuple (int slotIndex, std::string name) {
this.slotIndex = slotIndex;
this.name = name;
nameHashCode = this.name.GetHashCode();
}
}
// Avoids boxing in the dictionary.
class AttachmentKeyTupleComparer : IEqualityComparer<AttachmentKeyTuple> {
internal static readonly AttachmentKeyTupleComparer Instance = new AttachmentKeyTupleComparer();
bool IEqualityComparer<AttachmentKeyTuple>.Equals (AttachmentKeyTuple o1, AttachmentKeyTuple o2) {
return o1.slotIndex == o2.slotIndex && o1.nameHashCode == o2.nameHashCode && o1.name == o2.name;
}
int IEqualityComparer<AttachmentKeyTuple>.GetHashCode (AttachmentKeyTuple o) {
return o.slotIndex;
}
} }
}; };
} }

View File

@ -28,7 +28,107 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#include <spine/Skin.h>
#include <assert.h>
namespace Spine namespace Spine
{ {
// TODO Skin::Skin(std::string name) : _name(name)
{
assert(_name.length() > 0);
}
void Skin::addAttachment(int slotIndex, std::string name, Attachment* attachment)
{
assert(attachment);
_attachments[AttachmentKey(slotIndex, name)] = attachment;
}
/// Returns the attachment for the specified slot index and name, or null.
Attachment* Skin::getAttachment(int slotIndex, std::string name)
{
std::iterator<AttachmentKey, Attachment*> q = _attachments.find(AttachmentKey(slotIndex, name));
Attachment* ret = nullptr;
if (q != _attachments.end())
{
ret = q->second;
}
return ret;
}
struct sum
{
sum(int * t):total(t){};
int * total;
void operator()(AttachmentKey key)
{
*total+=element;
}
};
/// Finds the skin keys for a given slot. The results are added to the passed vector names.
/// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex
/// @param names Found skin key names will be added to this vector.
void Skin::findNamesForSlot(int slotIndex, std::vector<std::string>& names)
{
foreach (AttachmentKey key in attachments.Keys)
if (key.slotIndex == slotIndex) names.Add(key.name);
}
/// Finds the attachments for a given slot. The results are added to the passed List(Attachment).
/// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex
/// @param attachments Found Attachments will be added to this vector.
void Skin::findAttachmentsForSlot(int slotIndex, std::vector<Attachment*>& attachments)
{
foreach (KeyValuePair<AttachmentKey, Attachment> entry in this.attachments)
if (entry.Key.slotIndex == slotIndex) attachments.Add(entry.Value);
}
const std::string& Skin::getName()
{
//
}
std::unordered_map<AttachmentKey, Attachment*>& Skin::getAttachments()
{
//
}
void Skin::attachAll(Skeleton& skeleton, Skin& oldSkin)
{
foreach (KeyValuePair<AttachmentKey, Attachment> entry in oldSkin.attachments)
{
int slotIndex = entry.Key.slotIndex;
Slot slot = skeleton.slots.Items[slotIndex];
if (slot.Attachment == entry.Value) {
Attachment attachment = GetAttachment(slotIndex, entry.Key.name);
if (attachment != null) slot.Attachment = attachment;
}
}
}
AttachmentKey::AttachmentKey(int slotIndex, std::string name) :
_slotIndex(slotIndex),
_name(name)
{
// Empty
}
bool AttachmentKey::operator==(const AttachmentKey &other) const
{
return _slotIndex == other._slotIndex && _name == other._name;
}
std::ostream& operator <<(std::ostream& os, const Skin& ref)
{
os << ref.getName();
return os;
}
} }