diff --git a/spine-c/src/spine/SkeletonBinary.c b/spine-c/src/spine/SkeletonBinary.c index 5a0485ac0..06eb15fa6 100644 --- a/spine-c/src/spine/SkeletonBinary.c +++ b/spine-c/src/spine/SkeletonBinary.c @@ -656,7 +656,11 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput int i; spAttachmentType type; const char* name = readString(input); - if (!name) MALLOC_STR(name, attachmentName); + int freeName = name != 0; + if (!name) { + freeName = 0; + MALLOC_STR(name, attachmentName); + } type = (spAttachmentType)readByte(input); @@ -680,6 +684,7 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput readColor(input, ®ion->r, ®ion->g, ®ion->b, ®ion->a); spRegionAttachment_updateOffset(region); spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); + if (freeName) FREE(name); return attachment; } case SP_ATTACHMENT_BOUNDING_BOX: { @@ -689,6 +694,7 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput _readVertices(self, input, SUB_CAST(spVertexAttachment, attachment), vertexCount); if (nonessential) readInt(input); /* Skip color. */ spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); + if (freeName) FREE(name); return attachment; } case SP_ATTACHMENT_MESH: { @@ -717,6 +723,7 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput mesh->height = 0; } spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); + if (freeName) FREE(name); return attachment; } case SP_ATTACHMENT_LINKED_MESH: { @@ -738,6 +745,7 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput mesh->height = readFloat(input) * self->scale; } _spSkeletonBinary_addLinkedMesh(self, mesh, skinName, slotIndex, parent); + if (freeName) FREE(name); return attachment; } case SP_ATTACHMENT_PATH: { @@ -755,10 +763,12 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput path->lengths[i] = readFloat(input) * self->scale; } if (nonessential) readInt(input); /* Skip color. */ + if (freeName) FREE(name); return attachment; } } + if (freeName) FREE(name); return 0; } diff --git a/spine-cocos2dx/example/Classes/BatchingExample.cpp b/spine-cocos2dx/example/Classes/BatchingExample.cpp index fe919fa25..0577fd077 100644 --- a/spine-cocos2dx/example/Classes/BatchingExample.cpp +++ b/spine-cocos2dx/example/Classes/BatchingExample.cpp @@ -44,10 +44,6 @@ Scene* BatchingExample::scene () { bool BatchingExample::init () { if (!LayerColor::initWithColor(Color4B(128, 128, 128, 255))) return false; - // To avoid the SkeletonBatch buffer from being resized, set this to the number of vertices ever rendered in one frame. - // BatchingExample needs ~3200, but let's set it low to test the buffer resizing. - SkeletonBatch::setBufferSize(512); - // Load the texture atlas. _atlas = spAtlas_createFromFile("spineboy.atlas", 0); CCASSERT(_atlas, "Error reading atlas file."); diff --git a/spine-cocos2dx/src/spine/SkeletonBatch.cpp b/spine-cocos2dx/src/spine/SkeletonBatch.cpp index 1237f0d74..19ea80171 100644 --- a/spine-cocos2dx/src/spine/SkeletonBatch.cpp +++ b/spine-cocos2dx/src/spine/SkeletonBatch.cpp @@ -1,10 +1,10 @@ /****************************************************************************** * Spine Runtimes Software License * Version 2.3 - * + * * Copyright (c) 2013-2015, Esoteric Software * All rights reserved. - * + * * You are granted a perpetual, non-exclusive, non-sublicensable and * non-transferable license to use, install, execute and perform the Spine * Runtimes Software (the "Software") and derivative works solely for personal @@ -16,7 +16,7 @@ * or other intellectual property or proprietary rights notices on or in the * Software, including any copy thereof. Redistributions in binary or source * form must include this license and terms. - * + * * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -38,102 +38,72 @@ USING_NS_CC; using std::max; namespace spine { - -static SkeletonBatch* instance = nullptr; - -void SkeletonBatch::setBufferSize (int vertexCount) { - if (instance) delete instance; - instance = new SkeletonBatch(vertexCount); -} - -SkeletonBatch* SkeletonBatch::getInstance () { - if (!instance) instance = new SkeletonBatch(8192); - return instance; -} -void SkeletonBatch::destroyInstance () { - if (instance) { - delete instance; - instance = nullptr; + static SkeletonBatch* instance = nullptr; + + SkeletonBatch* SkeletonBatch::getInstance () { + if (!instance) instance = new SkeletonBatch(); + return instance; } -} - -SkeletonBatch::SkeletonBatch (int capacity) : - _capacity(capacity), _position(0) -{ - _buffer = new V3F_C4B_T2F[capacity]; - _firstCommand = new Command(); - _command = _firstCommand; - - Director::getInstance()->getEventDispatcher()->addCustomEventListener(EVENT_AFTER_DRAW_RESET_POSITION, [this](EventCustom* eventCustom){ - this->update(0); - });; -} - -SkeletonBatch::~SkeletonBatch () { - Director::getInstance()->getEventDispatcher()->removeCustomEventListeners(EVENT_AFTER_DRAW_RESET_POSITION); - - Command* command = _firstCommand; - while (command) { - Command* next = command->next; - delete command; - command = next; - } - - delete [] _buffer; -} - -void SkeletonBatch::update (float delta) { - _position = 0; - _command = _firstCommand; -} - -void SkeletonBatch::addCommand (cocos2d::Renderer* renderer, float globalZOrder, GLuint textureID, GLProgramState* glProgramState, - BlendFunc blendFunc, const TrianglesCommand::Triangles& triangles, const Mat4& transform, uint32_t transformFlags -) { - if (_position + triangles.vertCount > _capacity) { - int newCapacity = max(_capacity + _capacity / 2, _position + triangles.vertCount); - V3F_C4B_T2F* newBuffer = new V3F_C4B_T2F[newCapacity]; - memcpy(newBuffer, _buffer, _position); - - int newPosition = 0; - Command* command = _firstCommand; - while (newPosition < _position) { - command->triangles->verts = newBuffer + newPosition; - newPosition += command->triangles->vertCount; - command = command->next; - } - - delete [] _buffer; - _buffer = newBuffer; - _capacity = newCapacity; - } - - memcpy(_buffer + _position, triangles.verts, sizeof(V3F_C4B_T2F) * triangles.vertCount); - _command->triangles->verts = _buffer + _position; - _position += triangles.vertCount; - - _command->triangles->vertCount = triangles.vertCount; - _command->triangles->indexCount = triangles.indexCount; - _command->triangles->indices = triangles.indices; - - _command->trianglesCommand->init(globalZOrder, textureID, glProgramState, blendFunc, *_command->triangles, transform, transformFlags); - renderer->addCommand(_command->trianglesCommand); - - if (!_command->next) _command->next = new Command(); - _command = _command->next; -} - -SkeletonBatch::Command::Command () : - next(nullptr) -{ - trianglesCommand = new TrianglesCommand(); - triangles = new TrianglesCommand::Triangles(); -} - -SkeletonBatch::Command::~Command () { - delete triangles; - delete trianglesCommand; -} - -} + + void SkeletonBatch::destroyInstance () { + if (instance) { + delete instance; + instance = nullptr; + } + } + + SkeletonBatch::SkeletonBatch () + { + _firstCommand = new Command(); + _command = _firstCommand; + + Director::getInstance()->getEventDispatcher()->addCustomEventListener(EVENT_AFTER_DRAW_RESET_POSITION, [this](EventCustom* eventCustom){ + this->update(0); + });; + } + + SkeletonBatch::~SkeletonBatch () { + Director::getInstance()->getEventDispatcher()->removeCustomEventListeners(EVENT_AFTER_DRAW_RESET_POSITION); + + Command* command = _firstCommand; + while (command) { + Command* next = command->next; + delete command; + command = next; + } + } + + void SkeletonBatch::update (float delta) { + _command = _firstCommand; + } + + void SkeletonBatch::addCommand (cocos2d::Renderer* renderer, float globalZOrder, GLuint textureID, GLProgramState* glProgramState, + BlendFunc blendFunc, const TrianglesCommand::Triangles& triangles, const Mat4& transform, uint32_t transformFlags + ) { + _command->triangles->verts = triangles.verts; + + _command->triangles->vertCount = triangles.vertCount; + _command->triangles->indexCount = triangles.indexCount; + _command->triangles->indices = triangles.indices; + + _command->trianglesCommand->init(globalZOrder, textureID, glProgramState, blendFunc, *_command->triangles, transform); + renderer->addCommand(_command->trianglesCommand); + + if (!_command->next) _command->next = new Command(); + _command = _command->next; + } + + SkeletonBatch::Command::Command () : + next(nullptr) + { + trianglesCommand = new TrianglesCommand(); + triangles = new TrianglesCommand::Triangles(); + } + + SkeletonBatch::Command::~Command () { + delete triangles; + delete trianglesCommand; + } + +} \ No newline at end of file diff --git a/spine-cocos2dx/src/spine/SkeletonBatch.h b/spine-cocos2dx/src/spine/SkeletonBatch.h index 98419bef1..6c2069ce4 100644 --- a/spine-cocos2dx/src/spine/SkeletonBatch.h +++ b/spine-cocos2dx/src/spine/SkeletonBatch.h @@ -1,10 +1,10 @@ /****************************************************************************** * Spine Runtimes Software License * Version 2.3 - * + * * Copyright (c) 2013-2015, Esoteric Software * All rights reserved. - * + * * You are granted a perpetual, non-exclusive, non-sublicensable and * non-transferable license to use, install, execute and perform the Spine * Runtimes Software (the "Software") and derivative works solely for personal @@ -16,7 +16,7 @@ * or other intellectual property or proprietary rights notices on or in the * Software, including any copy thereof. Redistributions in binary or source * form must include this license and terms. - * + * * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO @@ -36,45 +36,36 @@ #include "cocos2d.h" namespace spine { - -class SkeletonBatch { -public: - /* Sets the max number of vertices that can be drawn in a single frame. The buffer will grow automatically as needed, but - * setting it to the appropriate is more efficient. Best to call before getInstance is called for the first time. Default is - * 8192. */ - static void setBufferSize (int vertexCount); - - static SkeletonBatch* getInstance (); - static void destroyInstance (); - - void update (float delta); - - void addCommand (cocos2d::Renderer* renderer, float globalOrder, GLuint textureID, cocos2d::GLProgramState* glProgramState, - cocos2d::BlendFunc blendType, const cocos2d::TrianglesCommand:: Triangles& triangles, const cocos2d::Mat4& mv, uint32_t flags); - -protected: - SkeletonBatch (int capacity); - virtual ~SkeletonBatch (); - - cocos2d::V3F_C4B_T2F* _buffer; - int _capacity; - int _position; - - class Command { - public: - Command (); - virtual ~Command (); - - cocos2d::TrianglesCommand* trianglesCommand; - cocos2d::TrianglesCommand::Triangles* triangles; - Command* next; - }; - - Command* _firstCommand; - Command* _command; -}; - + class SkeletonBatch { + public: + static SkeletonBatch* getInstance (); + + static void destroyInstance (); + + void update (float delta); + + void addCommand (cocos2d::Renderer* renderer, float globalOrder, GLuint textureID, cocos2d::GLProgramState* glProgramState, + cocos2d::BlendFunc blendType, const cocos2d::TrianglesCommand:: Triangles& triangles, const cocos2d::Mat4& mv, uint32_t flags); + + protected: + SkeletonBatch (); + virtual ~SkeletonBatch (); + + class Command { + public: + Command (); + virtual ~Command (); + + cocos2d::TrianglesCommand* trianglesCommand; + cocos2d::TrianglesCommand::Triangles* triangles; + Command* next; + }; + + Command* _firstCommand; + Command* _command; + }; + } -#endif // SPINE_SKELETONBATCH_H_ +#endif // SPINE_SKELETONBATCH_H_ \ No newline at end of file diff --git a/spine-unity/Assets/spine-unity/Asset Types/Editor/AtlasAssetInspector.cs b/spine-unity/Assets/spine-unity/Asset Types/Editor/AtlasAssetInspector.cs index fb5672492..4531e5be8 100644 --- a/spine-unity/Assets/spine-unity/Asset Types/Editor/AtlasAssetInspector.cs +++ b/spine-unity/Assets/spine-unity/Asset Types/Editor/AtlasAssetInspector.cs @@ -29,6 +29,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ //#define BAKE_ALL_BUTTON +//#define REGION_BAKING_MESH using System; using System.Collections.Generic; @@ -44,8 +45,6 @@ namespace Spine.Unity.Editor { public class AtlasAssetInspector : UnityEditor.Editor { private SerializedProperty atlasFile, materials; private AtlasAsset atlasAsset; - private List baked; - private List bakedObjects; void OnEnable () { SpineEditorUtilities.ConfirmInitialization(); @@ -53,8 +52,14 @@ namespace Spine.Unity.Editor { materials = serializedObject.FindProperty("materials"); materials.isExpanded = true; atlasAsset = (AtlasAsset)target; + #if REGION_BAKING_MESH UpdateBakedList(); + #endif } + + #if REGION_BAKING_MESH + private List baked; + private List bakedObjects; void UpdateBakedList () { AtlasAsset asset = (AtlasAsset)target; @@ -78,13 +83,73 @@ namespace Spine.Unity.Editor { } } } + #endif + + static public void UpdateSpriteSlices (Texture texture, Atlas atlas) { + string texturePath = AssetDatabase.GetAssetPath(texture.GetInstanceID()); + var t = (TextureImporter)TextureImporter.GetAtPath(texturePath); + t.spriteImportMode = SpriteImportMode.Multiple; + var spriteSheet = t.spritesheet; + var sprites = new List(spriteSheet); + + FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.NonPublic); + var regions = (List)field.GetValue(atlas); + int textureHeight = texture.height; + char[] FilenameDelimiter = {'.'}; + int updatedCount = 0; + int addedCount = 0; + + foreach (var r in regions) { + int width, height; + if (r.rotate) { + width = r.height; + height = r.width; + } else { + width = r.width; + height = r.height; + } + + int x = r.x; + int y = textureHeight - height - r.y; + + string pageName = r.page.name.Split(FilenameDelimiter, StringSplitOptions.RemoveEmptyEntries)[0]; + string textureName = texture.name; + bool pageMatch = string.Equals(pageName, textureName,StringComparison.Ordinal); + int spriteIndex = pageMatch ? sprites.FindIndex( + (s) => string.Equals(s.name, r.name, StringComparison.Ordinal) + ) : -1; + bool matchFound = spriteIndex >= 0; + + if (matchFound) { + var s = sprites[spriteIndex]; + s.rect = new Rect(x, y, width, height); + sprites[spriteIndex] = s; + updatedCount++; + } else { + if (pageMatch) { + sprites.Add(new SpriteMetaData { + name = r.name, + pivot = new Vector2(0.5f, 0.5f), + rect = new Rect(x, y, width, height) + }); + addedCount++; + } + } + } + + t.spritesheet = sprites.ToArray(); + EditorUtility.SetDirty(t); + AssetDatabase.ImportAsset(texturePath, ImportAssetOptions.ForceUpdate); + EditorGUIUtility.PingObject(texture); + Debug.Log(string.Format("Applied sprite slices to {2}. {0} added. {1} updated.", addedCount, updatedCount, texture.name)); + } override public void OnInspectorGUI () { serializedObject.Update(); - AtlasAsset asset = (AtlasAsset)target; - + atlasAsset = atlasAsset ?? (AtlasAsset)target; EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(atlasFile); + EditorGUILayout.PropertyField(materials, true); if (EditorGUI.EndChangeCheck()) serializedObject.ApplyModifiedProperties(); @@ -103,6 +168,22 @@ namespace Spine.Unity.Editor { } } + if (atlasFile.objectReferenceValue != null) { + if (GUILayout.Button( + new GUIContent( + "Apply Regions as Texture Sprite Slices", + "Adds Sprite slices to atlas texture(s). " + + "Updates existing slices if ones with matching names exist. \n\n" + + "If your atlas was exported with Premultiply Alpha, " + + "your SpriteRenderer should use the generated Spine _Material asset (or any Material with a PMA shader) instead of Sprites-Default.") + , GUILayout.Height(70f))) { + var atlas = atlasAsset.GetAtlas(); + foreach (var m in atlasAsset.materials) + UpdateSpriteSlices(m.mainTexture, atlas); + } + } + + #if REGION_BAKING_MESH if (atlasFile.objectReferenceValue != null) { Atlas atlas = asset.GetAtlas(); FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic); @@ -206,13 +287,14 @@ namespace Spine.Unity.Editor { } #endif - + } + #endif if (serializedObject.ApplyModifiedProperties() || (UnityEngine.Event.current.type == EventType.ValidateCommand && UnityEngine.Event.current.commandName == "UndoRedoPerformed") ) { - asset.Reset(); + atlasAsset.Reset(); } } }