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-ts/README.md b/spine-ts/README.md index c93ee1b9c..0717e5533 100644 --- a/spine-ts/README.md +++ b/spine-ts/README.md @@ -36,9 +36,8 @@ All `*.js` files are self-contained and include both the core and respective bac If you write your app with TypeScript, additionally copy the corresponding `build/spine-*.d.ts` file to your project. -## Example -To run the examples, spawn a light-weight web server in the root of spine-ts, then navigate to the respective -`index.html` file. E.g.: +## Examples +To run the examples, the image, atlas, and JSON files must be served by a webserver, they can't be loaded from your local disk. Spawn a light-weight web server in the root of spine-ts, then navigate to the `index.html` file for the example you want to view. E.g.: ``` cd spine-ts @@ -47,6 +46,22 @@ python -m SimpleHTTPServer Then open `http://localhost:8000/webgl/example`, `http://localhost:8000/canvas/example`, `https://localhost:8000/threejs/example` or `http://localhost:8000/widget/example` in your browser. +## WebGL Demos +The spine-ts WebGL demos load their image, atlas, and JSON files from our webserver and so can be run directly, without needing a webserver. View the demos [all on one page](http://esotericsoftware.com/spine-demos/) or use the [standalone demos]() which are easy for you to explore and edit. The standalone demos can also be viewed here: + +- [Spine vs sprite sheets](http://rawgit.com/EsotericSoftware/spine-runtimes/master/spine-ts/webgl/demos/spritesheets.html) +- [Image changes](http://rawgit.com/EsotericSoftware/spine-runtimes/master/spine-ts/webgl/demos/imagechanges.html) +- [Transitions](http://rawgit.com/EsotericSoftware/spine-runtimes/master/spine-ts/webgl/demos/transitions.html) +- [Meshes](http://rawgit.com/EsotericSoftware/spine-runtimes/master/spine-ts/webgl/demos/meshes.html) +- [Skins](http://rawgit.com/EsotericSoftware/spine-runtimes/master/spine-ts/webgl/demos/skins.html) +- [Hoverboard](http://rawgit.com/EsotericSoftware/spine-runtimes/master/spine-ts/webgl/demos/hoverboard.html) +- [Transform constraints](http://rawgit.com/EsotericSoftware/spine-runtimes/master/spine-ts/webgl/demos/transforms.html) +- [Tank](http://rawgit.com/EsotericSoftware/spine-runtimes/master/spine-ts/webgl/demos/tank.html) +- [Vine](http://rawgit.com/EsotericSoftware/spine-runtimes/master/spine-ts/webgl/demos/vine.html) +- [Stretchyman](http://rawgit.com/EsotericSoftware/spine-runtimes/master/spine-ts/webgl/demos/stretchyman.html) + +Please note that Chrome and possibly other browsers do not use the original CORS headers when loading cached resources. After the initial page load for a demo, you may need to forcefully refresh (hold `shift` and click refresh) or clear your browser cache. + ## Development Setup The spine-ts runtime and the various backends are implemented in TypeScript for greater maintainability and better tooling support. To setup a development environment, follow these steps. @@ -58,7 +73,7 @@ setup a development environment, follow these steps. 5. Start the TypeScript compiler in watcher mode for the backend you want to work on: * **Core**: `tsc -w -p tsconfig.core.json`, builds `core/src`, outputs `build/spine-core.js|d.ts|js.map` * **WebGL**: `tsc -w -p tsconfig.webgl.json`, builds `core/src` and `webgl/src`, outputs `build/spine-webgl.js|d.ts|js.map` - * **WebGL**: `tsc -w -p tsconfig.canvas.json`, builds `core/src` and `canvas/src`, outputs `build/spine-canvas.js|d.ts|js.map` + * **Canvas**: `tsc -w -p tsconfig.canvas.json`, builds `core/src` and `canvas/src`, outputs `build/spine-canvas.js|d.ts|js.map` * **THREE.JS**: `tsc -w -p tsconfig.threejs.json`, builds `core/src` and `threejs/src`, outputs `build/spine-threejs.js|d.ts|js.map` * **Widget**: `tsc -w -p tsconfig.widget.json`, builds `core/src` and `widget/src`, outputs `build/spine-widget.js|d.ts|js.map` 6. Open the `spine-ts` folder in Visual Studio Code. VS Code will use the `tsconfig.json` file all source files from core and all diff --git a/spine-ts/webgl/demos/demos.css b/spine-ts/webgl/demos/demos.css index 2701203a1..343868faa 100644 --- a/spine-ts/webgl/demos/demos.css +++ b/spine-ts/webgl/demos/demos.css @@ -1,18 +1,43 @@ body, html { margin: 0; - padding: 0; height: 100%; font-family: Tahoma; font-size: 11pt; } -canvas { - position: absolute; width: 100% ;height: 100%; +body { + padding: 15px; +} +br { + display: block; + content: ""; + margin-top: 15px; +} +.aspect { + margin-bottom: 15px; + max-width: 800px; + text-align: center; +} +.aspect div { + position: relative; + padding-bottom: 70.14%; +} +.aspect canvas { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 100%; + border: 1px solid black; } .slider { - width: 50%; + width: 100%; + max-width: 800px; border-radius: 3px; text-align: left; transform: translateZ(0); + background: #222; } .slider, .slider.filled span { height: 15px; diff --git a/spine-ts/webgl/demos/framebyframe.html b/spine-ts/webgl/demos/framebyframe.html deleted file mode 100644 index e0c85fe3c..000000000 --- a/spine-ts/webgl/demos/framebyframe.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - -
-
-
- -
-
-
- - - - - \ No newline at end of file diff --git a/spine-ts/webgl/demos/hoverboard.html b/spine-ts/webgl/demos/hoverboard.html new file mode 100644 index 000000000..9534e2a72 --- /dev/null +++ b/spine-ts/webgl/demos/hoverboard.html @@ -0,0 +1,20 @@ + +IK Constraints - Spine Demo + + + + + + + +
+
+ Display Bones +
+ + + + + \ No newline at end of file diff --git a/spine-ts/webgl/demos/ikconstraint.js b/spine-ts/webgl/demos/hoverboard.js similarity index 93% rename from spine-ts/webgl/demos/ikconstraint.js rename to spine-ts/webgl/demos/hoverboard.js index 1f7e04d4f..ed7c8ade2 100644 --- a/spine-ts/webgl/demos/ikconstraint.js +++ b/spine-ts/webgl/demos/hoverboard.js @@ -1,4 +1,4 @@ -var ikConstraintDemo = function(loadingComplete, bgColor) { +var hoverboardDemo = function(loadingComplete, bgColor) { var COLOR_INNER = new spine.Color(0.8, 0, 0, 0.5); var COLOR_OUTER = new spine.Color(0.8, 0, 0, 0.8); var COLOR_INNER_SELECTED = new spine.Color(0.0, 0, 0.8, 0.5); @@ -9,16 +9,16 @@ var ikConstraintDemo = function(loadingComplete, bgColor) { var timeKeeper, loadingScreen; var target = null; var hoverTargets = []; - var controlBones = ["hoverboard controller", "hip", "board target"]; + var controlBones = ["hoverboard controller", "hip controller", "board target"]; var coords = new spine.webgl.Vector3(), temp = new spine.webgl.Vector3(), temp2 = new spine.Vector2(), temp3 = new spine.webgl.Vector3(); var isPlaying = true; - var DEMO_NAME = "IkConstraintDemo"; + var DEMO_NAME = "HoverboardDemo"; - if (!bgColor) bgColor = new spine.Color(1, 1, 1, 1); + if (!bgColor) bgColor = new spine.Color(235 / 255, 239 / 255, 244 / 255, 1); function init () { - canvas = document.getElementById("ikdemo-canvas"); + canvas = document.getElementById("hoverboard-canvas"); canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; gl = canvas.getContext("webgl", { alpha: false }) || canvas.getContext("experimental-webgl", { alpha: false }); @@ -71,7 +71,7 @@ var ikConstraintDemo = function(loadingComplete, bgColor) { } function setupUI() { - var checkbox = $("#ikdemo-drawbones"); + var checkbox = $("#hoverboard-drawbones"); renderer.skeletonDebugRenderer.drawRegionAttachments = false; renderer.skeletonDebugRenderer.drawPaths = false; renderer.skeletonDebugRenderer.drawBones = false; diff --git a/spine-ts/webgl/demos/ikconstraint.html b/spine-ts/webgl/demos/ikconstraint.html deleted file mode 100644 index c64088548..000000000 --- a/spine-ts/webgl/demos/ikconstraint.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - -
-
Display Bones
-
- - - - - \ No newline at end of file diff --git a/spine-ts/webgl/demos/imagechanges.html b/spine-ts/webgl/demos/imagechanges.html new file mode 100644 index 000000000..43a2ae6f9 --- /dev/null +++ b/spine-ts/webgl/demos/imagechanges.html @@ -0,0 +1,23 @@ + +Frame-by-frame - Spine Demo + + + + + + + +
+
+
+
+ +
+ + + + + \ No newline at end of file diff --git a/spine-ts/webgl/demos/framebyframe.js b/spine-ts/webgl/demos/imagechanges.js similarity index 91% rename from spine-ts/webgl/demos/framebyframe.js rename to spine-ts/webgl/demos/imagechanges.js index c0230a0f2..ad77c37eb 100644 --- a/spine-ts/webgl/demos/framebyframe.js +++ b/spine-ts/webgl/demos/imagechanges.js @@ -1,4 +1,4 @@ -var frameByFrameDemo = function(loadingComplete, bgColor) { +var imageChangesDemo = function(loadingComplete, bgColor) { var OUTLINE_COLOR = new spine.Color(0, 0.8, 0, 1); var canvas, gl, renderer, input, assetManager; @@ -8,12 +8,12 @@ var frameByFrameDemo = function(loadingComplete, bgColor) { var activeSkeleton = "Alien"; var playButton, timeLine, isPlaying = true; - var DEMO_NAME = "FrameByFrameDemo"; + var DEMO_NAME = "ImageChangesDemo"; - if (!bgColor) bgColor = new spine.Color(1, 1, 1, 1); + if (!bgColor) bgColor = new spine.Color(235 / 255, 239 / 255, 244 / 255, 1); function init () { - canvas = document.getElementById("framebyframedemo-canvas"); + canvas = document.getElementById("imagechanges-canvas"); canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; gl = canvas.getContext("webgl", { alpha: false }) || canvas.getContext("experimental-webgl", { alpha: false }); @@ -43,21 +43,18 @@ var frameByFrameDemo = function(loadingComplete, bgColor) { } function setupUI() { - playButton = $("#framebyframedemo-playbutton"); + playButton = $("#imagechanges-playbutton"); var playButtonUpdate = function () { isPlaying = !isPlaying; - if (isPlaying) { - playButton.val("Pause"); - playButton.addClass("pause").removeClass("play"); - } else { - playButton.val("Play"); + if (isPlaying) + playButton.addClass("pause").removeClass("play"); + else playButton.addClass("play").removeClass("pause"); - } } playButton.click(playButtonUpdate); playButton.addClass("pause"); - timeLine = $("#framebyframedemo-timeline").data("slider"); + timeLine = $("#imagechanges-timeline").data("slider"); timeLine.changed = function (percent) { if (isPlaying) playButton.click(); if (!isPlaying) { @@ -71,7 +68,7 @@ var frameByFrameDemo = function(loadingComplete, bgColor) { } }; - var list = $("#framebyframedemo-active-skeleton"); + var list = $("#imagechanges-skeleton"); for (var skeletonName in skeletons) { var option = $(""); option.attr("value", skeletonName).text(skeletonName); @@ -79,7 +76,7 @@ var frameByFrameDemo = function(loadingComplete, bgColor) { list.append(option); } list.change(function() { - activeSkeleton = $("#framebyframedemo-active-skeleton option:selected").text(); + activeSkeleton = $("#imagechanges-skeleton option:selected").text(); var active = skeletons[activeSkeleton]; var animationDuration = active.state.getCurrent(0).animation.duration; timeLine.set(active.playTime / animationDuration); diff --git a/spine-ts/webgl/demos/meshes.html b/spine-ts/webgl/demos/meshes.html index b7ccbbd06..a87f42de4 100644 --- a/spine-ts/webgl/demos/meshes.html +++ b/spine-ts/webgl/demos/meshes.html @@ -1,4 +1,5 @@ +Meshes - Spine Demo @@ -6,15 +7,13 @@ -
-
-
-
Draw bones
-
Draw triangles
- -
-
+
+
+
+
+ Draw bones
+ Draw triangles
- - - - - - -
-
-
Display bones & path
- -
-
-
- - - - - \ No newline at end of file diff --git a/spine-ts/webgl/demos/skins.html b/spine-ts/webgl/demos/skins.html index 132c65d8b..f1e3241cd 100644 --- a/spine-ts/webgl/demos/skins.html +++ b/spine-ts/webgl/demos/skins.html @@ -1,4 +1,5 @@ +Skins - Spine Demo @@ -6,14 +7,12 @@ -
-
-
- - -
Randomize skin
-
+
+
+ +
+ Randomize skin
- - - - - - -
-
- - -
Time multiplier -
-
-
- - - - - \ No newline at end of file diff --git a/spine-ts/webgl/demos/spritesheets.html b/spine-ts/webgl/demos/spritesheets.html new file mode 100644 index 000000000..1f92933eb --- /dev/null +++ b/spine-ts/webgl/demos/spritesheets.html @@ -0,0 +1,24 @@ + +Spine vs Sprite Sheets - Spine Demo + + + + + + + +
+
+ +
+Time multiplier +
+
+ + + + + \ No newline at end of file diff --git a/spine-ts/webgl/demos/spritesheet.js b/spine-ts/webgl/demos/spritesheets.js similarity index 78% rename from spine-ts/webgl/demos/spritesheet.js rename to spine-ts/webgl/demos/spritesheets.js index 7ac08e06b..0d74382db 100644 --- a/spine-ts/webgl/demos/spritesheet.js +++ b/spine-ts/webgl/demos/spritesheets.js @@ -1,4 +1,4 @@ -var spritesheetDemo = function(loadingComplete, bgColor) { +var spritesheetsDemo = function(loadingComplete, bgColor) { var SKELETON_ATLAS_COLOR = new spine.Color(0, 0.8, 0, 0.8); var FRAME_ATLAS_COLOR = new spine.Color(0.8, 0, 0, 0.8); @@ -11,12 +11,12 @@ var spritesheetDemo = function(loadingComplete, bgColor) { var timeKeeper, loadingScreen, input; var playTime = 0, framePlaytime = 0, clickAnim = 0; - var DEMO_NAME = "SpritesheetDemo"; + var DEMO_NAME = "SpritesheetsDemo"; - if (!bgColor) bgColor = new spine.Color(1, 1, 1, 1); + if (!bgColor) bgColor = new spine.Color(235 / 255, 239 / 255, 244 / 255, 1); function init () { - canvas = document.getElementById("spritesheetdemo-canvas"); + canvas = document.getElementById("spritesheets-canvas"); canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; gl = canvas.getContext("webgl", { alpha: false }) || canvas.getContext("experimental-webgl", { alpha: false }); @@ -52,6 +52,7 @@ var spritesheetDemo = function(loadingComplete, bgColor) { offset = new spine.Vector2(); bounds = new spine.Vector2(); skeleton.getBounds(offset, bounds); + skeleton.x -= 60; skeletonSeq = new spine.Skeleton(skeletonData); walkAnim = skeletonSeq.data.findAnimation("walk"); @@ -64,8 +65,8 @@ var spritesheetDemo = function(loadingComplete, bgColor) { setupUI(); setupInput(); - $("#spritesheetdemo-overlay").removeClass("overlay-hide"); - $("#spritesheetdemo-overlay").addClass("overlay"); + $("#spritesheets-overlay").removeClass("overlay-hide"); + $("#spritesheets-overlay").addClass("overlay"); loadingComplete(canvas, render); } else { loadingScreen.draw(); @@ -73,34 +74,36 @@ var spritesheetDemo = function(loadingComplete, bgColor) { } } - function setupUI() { - timeSlider = $("#spritesheetdemo-timeslider").data("slider"); + function setupUI () { + timeSlider = $("#spritesheets-timeslider").data("slider"); timeSlider.set(0.5); - timeSliderLabel = $("#spritesheetdemo-timeslider-label")[0]; + timeSliderLabel = $("#spritesheets-timeslider-label")[0]; } - function setupInput() { + function setupInput () { input.addListener({ down: function(x, y) { - animationState.setAnimation(0, (clickAnim++ % 2 == 0) ? "roar" : "jump", false); - animationState.addAnimation(0, "walk", true, 0); + setAnimation((clickAnim++ % 2 == 0) ? "roar" : "jump"); }, up: function(x, y) { }, moved: function(x, y) { }, dragged: function(x, y) { } }); - $("#spritesheetdemo-roar").click(function () { - animationState.setAnimation(0, "roar", false); - animationState.addAnimation(0, "walk", true, 0); + $("#spritesheets-roar").click(function () { + setAnimation("roar"); }); - $("#spritesheetdemo-jump").click(function () { - animationState.setAnimation(0, "jump", false); - animationState.addAnimation(0, "walk", true, 0); + $("#spritesheets-jump").click(function () { + setAnimation("jump"); }); } + + function setAnimation (name) { + animationState.setAnimation(0, name, false); + animationState.addAnimation(0, "walk", true, 0); + } function resize () { - renderer.camera.position.x = offset.x + viewportWidth / 2 + 100; + renderer.camera.position.x = offset.x + viewportWidth / 2 - 25; renderer.camera.position.y = offset.y + viewportHeight / 2 - 160; renderer.camera.viewportWidth = viewportWidth * 1.2; renderer.camera.viewportHeight = viewportHeight * 1.2; @@ -119,16 +122,12 @@ var spritesheetDemo = function(loadingComplete, bgColor) { var newValue = Math.round(timeSlider.get() * 100) + "%"; if (oldValue !== newValue) timeSliderLabel.textContent = newValue; } - + var animationDuration = animationState.getCurrent(0).animation.duration; playTime += delta; while (playTime >= animationDuration) { playTime -= animationDuration; - } - - animationState.update(delta); - animationState.apply(skeleton); - skeleton.updateWorldTransform(); + } walkLastTimePrecise += delta; while (walkLastTimePrecise - walkLastTime > 1 / FPS) { @@ -138,15 +137,20 @@ var spritesheetDemo = function(loadingComplete, bgColor) { } skeletonSeq.updateWorldTransform(); - + animationState.update(delta); + var current = animationState.getCurrent(0); + if (current.animation.name == "walk") current.time = walkLastTimePrecise; + animationState.apply(skeleton); + skeleton.updateWorldTransform(); + gl.clearColor(bgColor.r, bgColor.g, bgColor.b, bgColor.a); gl.clear(gl.COLOR_BUFFER_BIT); - renderer.begin(); - var frame = frames[currFrame]; + renderer.begin(); + var frame = frames[currFrame]; renderer.drawSkeleton(skeleton, true); renderer.drawSkeleton(skeletonSeq, true); - renderer.end(); + renderer.end(); } init(); diff --git a/spine-ts/webgl/demos/stretchy.html b/spine-ts/webgl/demos/stretchy.html deleted file mode 100644 index 52e017e90..000000000 --- a/spine-ts/webgl/demos/stretchy.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - -
-
-
Display bones
-
-
- - - - - \ No newline at end of file diff --git a/spine-ts/webgl/demos/stretchyman.html b/spine-ts/webgl/demos/stretchyman.html new file mode 100644 index 000000000..a01599cbc --- /dev/null +++ b/spine-ts/webgl/demos/stretchyman.html @@ -0,0 +1,20 @@ + +Strechyman - Spine Demo + + + + + + + +
+
+ Display bones +
+ + + + + \ No newline at end of file diff --git a/spine-ts/webgl/demos/stretchy.js b/spine-ts/webgl/demos/stretchyman.js similarity index 79% rename from spine-ts/webgl/demos/stretchy.js rename to spine-ts/webgl/demos/stretchyman.js index 087011b0e..3a84ce24f 100644 --- a/spine-ts/webgl/demos/stretchy.js +++ b/spine-ts/webgl/demos/stretchyman.js @@ -1,4 +1,4 @@ -var stretchyDemo = function(loadingComplete, bgColor) { +var stretchymanDemo = function(loadingComplete, bgColor) { var COLOR_INNER = new spine.Color(0.8, 0, 0, 0.5); var COLOR_OUTER = new spine.Color(0.8, 0, 0, 0.8); var COLOR_INNER_SELECTED = new spine.Color(0.0, 0, 0.8, 0.5); @@ -21,12 +21,12 @@ var stretchyDemo = function(loadingComplete, bgColor) { var kneePos = new spine.Vector2(); var playButton, timeLine, spacing, isPlaying = true, playTime = 0; - var DEMO_NAME = "StretchyDemo"; + var DEMO_NAME = "StretchymanDemo"; - if (!bgColor) bgColor = new spine.Color(1, 1, 1, 1); + if (!bgColor) bgColor = new spine.Color(235 / 255, 239 / 255, 244 / 255, 1); function init () { - canvas = document.getElementById("stretchydemo-canvas"); + canvas = document.getElementById("stretchyman-canvas"); canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; gl = canvas.getContext("webgl", { alpha: false }) || canvas.getContext("experimental-webgl", { alpha: false }); @@ -79,7 +79,7 @@ var stretchyDemo = function(loadingComplete, bgColor) { } function setupUI() { - var checkbox = $("#stretchydemo-drawbones"); + var checkbox = $("#stretchyman-drawbones"); renderer.skeletonDebugRenderer.drawPaths = false; renderer.skeletonDebugRenderer.drawBones = false; checkbox.change(function() { @@ -105,18 +105,16 @@ var stretchyDemo = function(loadingComplete, bgColor) { dragged: function(x, y) { if (target != null) { renderer.camera.screenToWorld(coords.set(x, y, 0), canvas.width, canvas.height); - var yOnly = target.data.name === "head controller" || target.data.name === "hip controller"; - if (target.parent !== null) { + if (target.parent !== null) target.parent.worldToLocal(temp2.set(coords.x - skeleton.x, coords.y - skeleton.y)); - if (!yOnly) target.x = temp2.x; - target.y = temp2.y; - } else { - if (!yOnly) target.x = coords.x - skeleton.x; - target.y = coords.y - skeleton.y; - } - - if (target.data.name === "hip controller") { - var head = skeleton.findBone("head controller"); + else + temp2.set(coords.x - skeleton.x, coords.y - skeleton.y); + target.x = temp2.x; + target.y = temp2.y; + if (target.data.name === "head controller") { + var hipControl = skeleton.findBone("hip controller"); + target.x = spine.MathUtils.clamp(target.x, -65, 65); + target.y = Math.max(260, target.y); } } }, @@ -134,22 +132,24 @@ var stretchyDemo = function(loadingComplete, bgColor) { }); } - function center(middleBone, hipBone, footBone) { + function center (middleBone, hipBone, footBone, amount, dir) { temp.set(footBone.worldX + skeleton.x, footBone.worldY + skeleton.y, 0) .sub(temp3.set(hipBone.worldX + skeleton.x, hipBone.worldY + skeleton.y, 0)); + var dist = Math.sqrt(temp.x * temp.x + temp.y * temp.y); temp3.set(hipBone.worldX + skeleton.x, hipBone.worldY + skeleton.y, 0); temp.scale(0.5).add(temp3); middleBone.parent.worldToLocal(kneePos.set(temp.x, temp.y)); middleBone.x = kneePos.x; - middleBone.y = kneePos.y; + middleBone.y = kneePos.y; + middleBone.children[0].y = (22 + Math.max(0, amount - dist * 0.3)) * dir; } - var rotate = function(handBone, elbowBone) { - // can do all this in world space cause handBone is essentially in world space - var v = coords.set(handBone.worldX, handBone.worldY, 0).sub(new spine.webgl.Vector3(elbowBone.worldX, elbowBone.worldY, 0)).normalize(); - var angle = Math.acos(v.x) * spine.MathUtils.radiansToDegrees + 180; + function rotate (handBone, elbowBone) { + // can do all this in world space cause handBone is essentially in world space + var v = coords.set(handBone.worldX, handBone.worldY, 0).sub(new spine.webgl.Vector3(elbowBone.worldX, elbowBone.worldY, 0)).normalize(); + var angle = Math.acos(v.x) * spine.MathUtils.radiansToDegrees + 180; if (v.y < 0) angle = 360 - angle; - handBone.rotation = angle; + handBone.rotation = angle; } function render () { @@ -158,12 +158,17 @@ var stretchyDemo = function(loadingComplete, bgColor) { state.update(delta); state.apply(skeleton); - center(skeleton.findBone("back leg middle"), skeleton.findBone("back leg 1"), skeleton.findBone("back leg controller")); - center(skeleton.findBone("front leg middle"), skeleton.findBone("front leg 1"), skeleton.findBone("front leg controller")); - center(skeleton.findBone("front arm middle"), skeleton.findBone("front arm 1"), skeleton.findBone("front arm controller")); - center(skeleton.findBone("back arm middle"), skeleton.findBone("back arm 1"), skeleton.findBone("back arm controller")); + center(skeleton.findBone("back leg middle"), skeleton.findBone("back leg 1"), skeleton.findBone("back leg controller"), 65, 1); + center(skeleton.findBone("front leg middle"), skeleton.findBone("front leg 1"), skeleton.findBone("front leg controller"), 65, 1); + center(skeleton.findBone("front arm middle"), skeleton.findBone("front arm 1"), skeleton.findBone("front arm controller"), 90, -1); + center(skeleton.findBone("back arm middle"), skeleton.findBone("back arm 1"), skeleton.findBone("back arm controller"), 90, -1); rotate(skeleton.findBone("front arm controller"), skeleton.findBone("front arm elbow")); - rotate(skeleton.findBone("back arm controller"), skeleton.findBone("back arm elbow")); + rotate(skeleton.findBone("back arm controller"), skeleton.findBone("back arm elbow")); + var headControl = skeleton.findBone("head controller"), hipControl = skeleton.findBone("hip controller") + var head = skeleton.findBone("head"); + var angle = Math.atan2(headControl.worldY - hipControl.worldY, headControl.worldX - hipControl.worldX) * spine.MathUtils.radDeg; + angle = (angle - 90) * 2.5; + head.rotation = head.data.rotation + Math.min(90, Math.abs(angle)) * Math.sign(angle); skeleton.updateWorldTransform(); renderer.camera.viewportWidth = bounds.x * 1.2; diff --git a/spine-ts/webgl/demos/tank.html b/spine-ts/webgl/demos/tank.html index cfaa31ed3..6b7ba9453 100644 --- a/spine-ts/webgl/demos/tank.html +++ b/spine-ts/webgl/demos/tank.html @@ -1,4 +1,5 @@ +Tank - Spine Demo @@ -6,13 +7,11 @@ -
-
-
Display bones
- -
-
+
+
+
+ Display bones
- - - - - - -
-
- Rotation offset -
- Translation mix -
-
-
- - - - - \ No newline at end of file diff --git a/spine-ts/webgl/demos/transforms.html b/spine-ts/webgl/demos/transforms.html new file mode 100644 index 000000000..a931a1314 --- /dev/null +++ b/spine-ts/webgl/demos/transforms.html @@ -0,0 +1,24 @@ + +Transform Constraints - Spine Demo + + + + + + + +
+
+Rotation offset +

+Translation mix +
+
+ + + + + \ No newline at end of file diff --git a/spine-ts/webgl/demos/transformconstraint.js b/spine-ts/webgl/demos/transforms.js similarity index 90% rename from spine-ts/webgl/demos/transformconstraint.js rename to spine-ts/webgl/demos/transforms.js index d653663c7..c1c90edb6 100644 --- a/spine-ts/webgl/demos/transformconstraint.js +++ b/spine-ts/webgl/demos/transforms.js @@ -1,4 +1,4 @@ -var transformConstraintDemo = function(loadingComplete, bgColor) { +var transformsDemo = function(loadingComplete, bgColor) { var COLOR_INNER = new spine.Color(0.8, 0, 0, 0.5); var COLOR_OUTER = new spine.Color(0.8, 0, 0, 0.8); var COLOR_INNER_SELECTED = new spine.Color(0.0, 0, 0.8, 0.5); @@ -15,12 +15,12 @@ var transformConstraintDemo = function(loadingComplete, bgColor) { var lastRotation = 0; var mix, lastOffset = 0, lastMix = 0.5; - var DEMO_NAME = "TransformConstraintDemo"; + var DEMO_NAME = "TransformsDemo"; - if (!bgColor) bgColor = new spine.Color(1, 1, 1, 1); + if (!bgColor) bgColor = new spine.Color(235 / 255, 239 / 255, 244 / 255, 1); function init () { - canvas = document.getElementById("transformdemo-canvas"); + canvas = document.getElementById("transforms-canvas"); canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; gl = canvas.getContext("webgl", { alpha: false }) || canvas.getContext("experimental-webgl", { alpha: false }); @@ -45,7 +45,7 @@ var transformConstraintDemo = function(loadingComplete, bgColor) { }); var atlasLoader = new spine.TextureAtlasAttachmentLoader(atlas); var skeletonJson = new spine.SkeletonJson(atlasLoader); - var skeletonData = skeletonJson.readSkeletonData(assetManager.get(DEMO_NAME, "demos.json").transformConstraint); + var skeletonData = skeletonJson.readSkeletonData(assetManager.get(DEMO_NAME, "demos.json").transforms); skeleton = new spine.Skeleton(skeletonData); skeleton.setToSetupPose(); skeleton.updateWorldTransform(); @@ -75,27 +75,27 @@ var transformConstraintDemo = function(loadingComplete, bgColor) { } function setupUI() { - var rotationOffset = $("#transformdemo-rotationoffset").data("slider"); + var rotationOffset = $("#transforms-rotationoffset").data("slider"); rotationOffset.changed = function (percent) { var val = percent * 360 - 180; var delta = val - lastOffset; lastOffset = val; skeleton.findTransformConstraint("wheel2").data.offsetRotation += delta; skeleton.findTransformConstraint("wheel3").data.offsetRotation += delta; - $("#transformdemo-rotationoffset-label").text(Math.round(val) + "°"); + $("#transforms-rotationoffset-label").text(Math.round(val) + "°"); }; - $("#transformdemo-rotationoffset-label").text("0°"); + $("#transforms-rotationoffset-label").text("0°"); - var translationMix = $("#transformdemo-translationmix").data("slider"); + var translationMix = $("#transforms-translationmix").data("slider"); translationMix.set(0.5); translationMix.changed = function (percent) { var val = percent; var delta = val - lastMix; lastMix = val; skeleton.findTransformConstraint("wheel1").translateMix += delta; - $("#transformdemo-translationmix-label").text(Math.round(val * 100) + "%"); + $("#transforms-translationmix-label").text(Math.round(val * 100) + "%"); }; - $("#transformdemo-translationmix-label").text("50%"); + $("#transforms-translationmix-label").text("50%"); } function setupInput() { diff --git a/spine-ts/webgl/demos/transitions.html b/spine-ts/webgl/demos/transitions.html index 83483dd3e..ed7a58bc8 100644 --- a/spine-ts/webgl/demos/transitions.html +++ b/spine-ts/webgl/demos/transitions.html @@ -1,4 +1,5 @@ +Transitions - Spine Demo @@ -6,12 +7,10 @@ -
-
- Time multiplier -

-
+
+Time multiplier +
+ + + + + +
+
+
+
+ Display bones & path +
+ + + + + \ No newline at end of file diff --git a/spine-ts/webgl/demos/pathconstraint.js b/spine-ts/webgl/demos/vine.js similarity index 92% rename from spine-ts/webgl/demos/pathconstraint.js rename to spine-ts/webgl/demos/vine.js index 12af8f063..7b9f208dc 100644 --- a/spine-ts/webgl/demos/pathconstraint.js +++ b/spine-ts/webgl/demos/vine.js @@ -1,4 +1,4 @@ -var pathConstraintDemo = function(loadingComplete, bgColor) { +var vineDemo = function(loadingComplete, bgColor) { var COLOR_INNER = new spine.Color(0.8, 0, 0, 0.5); var COLOR_OUTER = new spine.Color(0.8, 0, 0, 0.8); var COLOR_INNER_SELECTED = new spine.Color(0.0, 0, 0.8, 0.5); @@ -13,12 +13,12 @@ var pathConstraintDemo = function(loadingComplete, bgColor) { var coords = new spine.webgl.Vector3(), temp = new spine.webgl.Vector3(), temp2 = new spine.Vector2(); var playButton, timeLine, isPlaying = true, playTime = 0; - var DEMO_NAME = "PathConstraintDemo"; + var DEMO_NAME = "VineDemo"; - if (!bgColor) bgColor = new spine.Color(1, 1, 1, 1); + if (!bgColor) bgColor = new spine.Color(235 / 255, 239 / 255, 244 / 255, 1); function init () { - canvas = document.getElementById("pathconstraintdemo-canvas"); + canvas = document.getElementById("vine-canvas"); canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; gl = canvas.getContext("webgl", { alpha: false }) || canvas.getContext("experimental-webgl", { alpha: false }); @@ -72,21 +72,18 @@ var pathConstraintDemo = function(loadingComplete, bgColor) { } function setupUI() { - playButton = $("#pathconstraintdemo-playbutton"); + playButton = $("#vine-playbutton"); var playButtonUpdate = function () { isPlaying = !isPlaying; - if (isPlaying) { - playButton.val("Pause"); - playButton.addClass("pause").removeClass("play"); - } else { - playButton.val("Play"); + if (isPlaying) + playButton.addClass("pause").removeClass("play"); + else playButton.addClass("play").removeClass("pause"); - } } playButton.click(playButtonUpdate); playButton.addClass("pause"); - timeLine = $("#pathconstraintdemo-timeline").data("slider"); + timeLine = $("#vine-timeline").data("slider"); timeLine.changed = function (percent) { if (isPlaying) playButton.click(); if (!isPlaying) { @@ -101,7 +98,7 @@ var pathConstraintDemo = function(loadingComplete, bgColor) { renderer.skeletonDebugRenderer.drawPaths = false; renderer.skeletonDebugRenderer.drawBones = false; - var checkbox = $("#pathconstraintdemo-drawbones"); + var checkbox = $("#vine-drawbones"); checkbox.change(function() { renderer.skeletonDebugRenderer.drawPaths = this.checked; renderer.skeletonDebugRenderer.drawBones = this.checked; 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(); } } } diff --git a/spine-unity/Assets/spine-unity/Mesh Generation/ISubmeshedMeshGenerator.cs b/spine-unity/Assets/spine-unity/Mesh Generation/ISubmeshedMeshGenerator.cs index 64d13d675..a1fba9084 100644 --- a/spine-unity/Assets/spine-unity/Mesh Generation/ISubmeshedMeshGenerator.cs +++ b/spine-unity/Assets/spine-unity/Mesh Generation/ISubmeshedMeshGenerator.cs @@ -28,6 +28,7 @@ namespace Spine.Unity.MeshGeneration { MeshAndMaterials GenerateMesh (ExposedList instructions, int startSubmesh, int endSubmesh); float ZSpacing { get; set; } + bool PremultiplyVertexColors { get; set; } bool AddNormals { get; set; } bool AddTangents { get; set; } } diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs index 5bf76d18d..806dd356f 100644 --- a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs +++ b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs @@ -137,6 +137,7 @@ namespace Spine.Unity.Modules { var currentRenderer = partsRenderers[rendererIndex]; bool addNormals = skeletonRenderer.calculateNormals; bool addTangents = skeletonRenderer.calculateTangents; + bool pmaVertexColors = skeletonRenderer.pmaVertexColors; for (int si = 0, start = 0; si <= lastSubmeshInstruction; si++) { if (submeshInstructionsItems[si].forceSeparate || si == lastSubmeshInstruction) { @@ -144,6 +145,7 @@ namespace Spine.Unity.Modules { var meshGenerator = currentRenderer.MeshGenerator; meshGenerator.AddNormals = addNormals; meshGenerator.AddTangents = addTangents; + meshGenerator.PremultiplyVertexColors = pmaVertexColors; if (copyPropertyBlock) currentRenderer.SetPropertyBlock(copiedBlock);