mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
Merge branch '4.0' of https://github.com/esotericsoftware/spine-runtimes into 4.0
This commit is contained in:
commit
01524d4cdc
@ -163,6 +163,9 @@
|
||||
* Improved `Advanced - Fix Prefab Override MeshFilter` property for `SkeletonRenderer` (and subclasses`SkeletonAnimation` and `SkeletonMecanim`), now providing an additional option to use a global value which can be set in `Edit - Preferences - Spine`.
|
||||
* Timeline naming improvements: `Spine AnimationState Clip` Inspector parameter `Custom Duration` changed and inverted to `Default Mix Duration` for more clarity. Shortened all Timeline add track menu entries from: `Spine.Unity.Playables - <track type>` to `Spine - <track type>`, `Spine Animation State Track` to `SkeletonAnimation Track`, `Spine AnimationState Graphic Track` to `SkeletonGraphic Track`, and `Spine Skeleton Flip Track` to `Skeleton Flip Track`.
|
||||
* Timeline track appearance and Inspector: Tracks now show icons and track colors to make them easier to distinguish. When a Track is selected, the Inspector now shows an editable track name which was previously only editable at the Timeline asset.
|
||||
* Added example component `SkeletonRenderTexture` to render a `SkeletonRenderer` to a `RenderTexture`, mainly for proper transparency. Added an example scene named `RenderTexture FadeOut Transparency` that demonstrates usage for a fadeout transparency effect.
|
||||
* Added another fadeout example component named `SkeletonRenderTextureFadeout` which takes over transparency fadeout when enabled. You can use this component as-is, attach it in disabled state and enable it to start a fadeout effect.
|
||||
* Timeline clips now offer an additional `Alpha` parameter for setting a custom constant mix alpha value other than 1.0, just as `TrackEntry.Alpha`. Defaults to 1.0.
|
||||
|
||||
* **Changes of default values**
|
||||
|
||||
@ -237,6 +240,7 @@
|
||||
* `SkeletonMesh` now takes an optional `SkeletonMeshMaterialParametersCustomizer` function that allows you to modify the `ShaderMaterialParameters` before the material is finalized. Use it to modify things like THREEJS' `Material.depthTest` etc. See #1590.
|
||||
* **Breaking change:** the global object `spine.canvas` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.threejs.` in your source code with `spine.`.
|
||||
* **Breaking change:** the default fragment shader of `SkeletonMeshMaterial` now explicitely discards fragments with alpha < 0.5. See https://github.com/EsotericSoftware/spine-runtimes/issues/1985
|
||||
* **Breaking change:** reversal of the previous breaking change: the default fragment shader of `SkeletonMeshMaterial` does no longer discard fragments with alpha < 0.5. Pass a `SkeletonMeshMaterialParametersCustomizer` to the `SkeletonMesh` constructor, and modify `parameters.alphaTest` to be > 0.
|
||||
|
||||
### Player
|
||||
* Added `SpinePlayerConfig.rawDataURIs`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. See the example for a demonstration.
|
||||
@ -631,6 +635,8 @@
|
||||
* Added `MeshAttachment#newLinkedMesh()`, creates a linked mesh linkted to either the original mesh, or the parent of the original mesh.
|
||||
* Added IK softness.
|
||||
* Added `AssetManager.setRawDataURI(path, data)`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file.
|
||||
* Added `AssetManager.loadAll()` to allow Promise/async/await based waiting for completion of asset load. See the `spine-canvas` examples.
|
||||
* Added `Skeleton.getBoundRect()` helper method to calculate the bouding rectangle of the current pose, returning the result as `{ x, y, width, height }`. Note that this method will create temporary objects which can add to garbage collection pressure.
|
||||
|
||||
### WebGL backend
|
||||
* `Input` can now take a partially defined implementation of `InputListener`.
|
||||
|
||||
@ -1,6 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.17)
|
||||
project(spine)
|
||||
|
||||
set(CMAKE_INSTALL_PREFIX "./")
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(SPINE_SFML FALSE CACHE BOOL FALSE)
|
||||
set(SPINE_COCOS2D_OBJC FALSE CACHE BOOL FALSE)
|
||||
set(SPINE_COCOS2D_X FALSE CACHE BOOL FALSE)
|
||||
set(SPINE_SANITIZE FALSE CACHE BOOL FALSE)
|
||||
|
||||
if(MSVC)
|
||||
message("MSCV detected")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
@ -8,13 +15,12 @@ if(MSVC)
|
||||
else()
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wunused-value -Wno-c++11-long-long -Wno-variadic-macros -Werror -Wextra -pedantic -Wnonportable-include-path -Wshadow -std=c89")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunused-value -Wno-c++11-long-long -Wno-variadic-macros -Werror -Wextra -Wnon-virtual-dtor -pedantic -Wnonportable-include-path -Wshadow -std=c++11 -fno-exceptions -fno-rtti")
|
||||
endif()
|
||||
|
||||
set(CMAKE_INSTALL_PREFIX "./")
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(SPINE_SFML FALSE CACHE BOOL FALSE)
|
||||
set(SPINE_COCOS2D_OBJC FALSE CACHE BOOL FALSE)
|
||||
set(SPINE_COCOS2D_X FALSE CACHE BOOL FALSE)
|
||||
if (${SPINE_SANITIZE})
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize=undefined")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if((${SPINE_SFML}) OR (${CMAKE_CURRENT_BINARY_DIR} MATCHES "spine-sfml"))
|
||||
add_subdirectory(spine-c)
|
||||
|
||||
@ -1189,7 +1189,7 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
|
||||
highHash = readInt(input);
|
||||
sprintf(buffer, "%x%x", highHash, lowHash);
|
||||
buffer[31] = 0;
|
||||
skeletonData->hash = strdup(buffer);
|
||||
MALLOC_STR(skeletonData->hash, buffer);
|
||||
|
||||
skeletonData->version = readString(input);
|
||||
if (!strlen(skeletonData->version)) {
|
||||
|
||||
@ -34,10 +34,6 @@
|
||||
#include <spine/extension.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const char *parent;
|
||||
const char *skin;
|
||||
@ -938,9 +934,17 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
|
||||
skeletonData->height = Json_getFloat(skeleton, "height", 0);
|
||||
skeletonData->fps = Json_getFloat(skeleton, "fps", 30);
|
||||
skeletonData->imagesPath = Json_getString(skeleton, "images", 0);
|
||||
if (skeletonData->imagesPath) skeletonData->imagesPath = strdup(skeletonData->imagesPath);
|
||||
if (skeletonData->imagesPath) {
|
||||
char *tmp = NULL;
|
||||
MALLOC_STR(tmp, skeletonData->imagesPath);
|
||||
skeletonData->imagesPath = tmp;
|
||||
}
|
||||
skeletonData->audioPath = Json_getString(skeleton, "audio", 0);
|
||||
if (skeletonData->audioPath) skeletonData->audioPath = strdup(skeletonData->audioPath);
|
||||
if (skeletonData->audioPath) {
|
||||
char *tmp = NULL;
|
||||
MALLOC_STR(tmp, skeletonData->audioPath);
|
||||
skeletonData->audioPath = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Bones. */
|
||||
|
||||
@ -104,15 +104,15 @@ namespace spine {
|
||||
virtual ~DefaultSpineExtension();
|
||||
|
||||
protected:
|
||||
virtual void *_alloc(size_t size, const char *file, int line);
|
||||
virtual void *_alloc(size_t size, const char *file, int line) override;
|
||||
|
||||
virtual void *_calloc(size_t size, const char *file, int line);
|
||||
virtual void *_calloc(size_t size, const char *file, int line) override;
|
||||
|
||||
virtual void *_realloc(void *ptr, size_t size, const char *file, int line);
|
||||
virtual void *_realloc(void *ptr, size_t size, const char *file, int line) override;
|
||||
|
||||
virtual void _free(void *mem, const char *file, int line);
|
||||
virtual void _free(void *mem, const char *file, int line) override;
|
||||
|
||||
virtual char *_readFile(const String &path, int *length);
|
||||
virtual char *_readFile(const String &path, int *length) override;
|
||||
};
|
||||
|
||||
// This function is to be implemented by engine specific runtimes to provide
|
||||
|
||||
@ -73,10 +73,6 @@
|
||||
#include <spine/TranslateTimeline.h>
|
||||
#include <spine/Vertices.h>
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
using namespace spine;
|
||||
|
||||
static float toColor(const char *value, size_t index) {
|
||||
@ -418,6 +414,8 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
|
||||
data->_spacingMode = SpacingMode_Fixed;
|
||||
else if (strcmp(item, "percent") == 0)
|
||||
data->_spacingMode = SpacingMode_Percent;
|
||||
else
|
||||
data->_spacingMode = SpacingMode_Proportional;
|
||||
|
||||
item = Json::getString(constraintMap, "rotateMode", "tangent");
|
||||
if (strcmp(item, "tangent") == 0) data->_rotateMode = RotateMode_Tangent;
|
||||
|
||||
@ -1200,7 +1200,7 @@ namespace Spine {
|
||||
input.Position = initialPosition;
|
||||
return GetVersionStringOld3X();
|
||||
} catch (Exception e) {
|
||||
throw new ArgumentException("Stream does not contain a valid binary Skeleton Data.\n" + e, "input");
|
||||
throw new ArgumentException("Stream does not contain valid binary Skeleton Data.\n" + e, "input");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1212,13 +1212,13 @@ namespace Spine {
|
||||
|
||||
// Version.
|
||||
byteCount = ReadInt(true);
|
||||
if (byteCount > 1) {
|
||||
if (byteCount > 1 && byteCount <= 13) {
|
||||
byteCount--;
|
||||
var buffer = new byte[byteCount];
|
||||
ReadFully(buffer, 0, byteCount);
|
||||
return System.Text.Encoding.UTF8.GetString(buffer, 0, byteCount);
|
||||
}
|
||||
return null;
|
||||
throw new ArgumentException("Stream does not contain valid binary Skeleton Data.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,9 +11,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:EsotericSoftware/spine-runtimes.git"
|
||||
|
||||
14
spine-ts/.vscode/launch.json
vendored
14
spine-ts/.vscode/launch.json
vendored
@ -17,6 +17,20 @@
|
||||
"name": "drag-and-drop",
|
||||
"url": "http://localhost:8080/spine-webgl/example/drag-and-drop.html",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "barebones-dragon",
|
||||
"url": "http://localhost:8080/spine-webgl/example/barebones-dragon.html",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "threejs-example",
|
||||
"url": "http://localhost:8080/spine-threejs/example/index.html",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -56,8 +56,8 @@ You can include a module in your project via a `<script>` tag from the [unpkg](h
|
||||
<script src="https://unpkg.com/@esotericsoftware/spine-player@4.0.*/dist/iife/spine-player.js">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@esotericsoftware/spine-player@4.0.*/dist/spine-player.css">
|
||||
|
||||
// spine-ts WebGL
|
||||
<script src="https://unpkg.com/@esotericsoftware/spine-threejs@4.0.*/dist/iife/spine-webgl.js">
|
||||
// spine-ts ThreeJS
|
||||
<script src="https://unpkg.com/@esotericsoftware/spine-threejs@4.0.*/dist/iife/spine-threejs.js">
|
||||
```
|
||||
|
||||
We also provide `js.map` source maps. They will be automatically fetched from unpkg when debugging code of a spine-module in Chrome, Firefox, or Safari, mapping the JavaScript code back to its original TypeScript sources.
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
<li>Canvas</li>
|
||||
<ul>
|
||||
<li><a href="/spine-canvas/example">Example</a></li>
|
||||
<li><a href="/spine-canvas/example/mouse-click.html">Mouse click</a></li>
|
||||
</ul>
|
||||
<li>Player</li>
|
||||
<ul>
|
||||
|
||||
311
spine-ts/package-lock.json
generated
311
spine-ts/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-ts",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@esotericsoftware/spine-ts",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"license": "LicenseRef-LICENSE",
|
||||
"workspaces": [
|
||||
"spine-core",
|
||||
@ -53,18 +53,18 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/three": {
|
||||
"version": "0.133.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.133.1.tgz",
|
||||
"integrity": "sha512-XqBrP/+kbs+o0CYRhCVVE95v7FaL2bO5Z7+3VQJE0nEyjo+9LoLfeNgZITOnndKHxM+7ltEciAIR7uE0SZlsOg=="
|
||||
"version": "0.138.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.138.0.tgz",
|
||||
"integrity": "sha512-D8AoV7h2kbCfrv/DcebHOFh1WDwyus3HdooBkAwcBikXArdqnsQ38PQ85JCunnvun160oA9jz53GszF3zch3tg=="
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"mime-types": "~2.1.24",
|
||||
"negotiator": "0.6.2"
|
||||
"mime-types": "~2.1.34",
|
||||
"negotiator": "0.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
@ -656,10 +656,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/destroy": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
|
||||
"dev": true
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
|
||||
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.8",
|
||||
"npm": "1.2.8000 || >= 1.4.16"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexer": {
|
||||
"version": "0.1.2",
|
||||
@ -1031,9 +1035,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.9",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
|
||||
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
|
||||
"version": "4.2.10",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
|
||||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
@ -1100,34 +1104,34 @@
|
||||
}
|
||||
},
|
||||
"node_modules/http-errors": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
|
||||
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"depd": "~1.1.2",
|
||||
"depd": "2.0.0",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"statuses": "2.0.1",
|
||||
"toidentifier": "1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/http-errors/node_modules/depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||
"node_modules/http-errors/node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/http-parser-js": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz",
|
||||
"integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==",
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz",
|
||||
"integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
@ -1468,30 +1472,30 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.51.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
|
||||
"integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.34",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
|
||||
"integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"mime-db": "1.51.0"
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
@ -1623,9 +1627,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
@ -7101,44 +7105,56 @@
|
||||
}
|
||||
},
|
||||
"node_modules/send": {
|
||||
"version": "0.17.2",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
|
||||
"integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==",
|
||||
"version": "0.18.0",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
|
||||
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"destroy": "~1.0.4",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "1.8.1",
|
||||
"http-errors": "2.0.0",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.3",
|
||||
"on-finished": "~2.3.0",
|
||||
"on-finished": "2.4.1",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "~1.5.0"
|
||||
"statuses": "2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/send/node_modules/on-finished": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ee-first": "1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/serve-index": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
|
||||
@ -7553,9 +7569,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/three": {
|
||||
"version": "0.133.1",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.133.1.tgz",
|
||||
"integrity": "sha512-WydohO8ll949B0FTD6MGz59Yv2Lwj8hvObg/0Heh2r42S6+tQC1WByfCNRdmG4D7+odfGod+n8JPV1I2xrboWw=="
|
||||
"version": "0.138.3",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.138.3.tgz",
|
||||
"integrity": "sha512-4t1cKC8gimNyJChJbaklg8W/qj3PpsLJUIFm5LIuAy/hVxxNm1ru2FGTSfbTSsuHmC/7ipsyuGKqrSAKLNtkzg=="
|
||||
},
|
||||
"node_modules/through": {
|
||||
"version": "2.3.8",
|
||||
@ -7693,9 +7709,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.5.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
|
||||
"integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
|
||||
"version": "4.6.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
|
||||
"integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
@ -7951,41 +7967,41 @@
|
||||
},
|
||||
"spine-canvas": {
|
||||
"name": "@esotericsoftware/spine-canvas",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"license": "LicenseRef-LICENSE",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-core": "^4.0.20"
|
||||
"@esotericsoftware/spine-core": "^4.0.27"
|
||||
}
|
||||
},
|
||||
"spine-core": {
|
||||
"name": "@esotericsoftware/spine-core",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"license": "LicenseRef-LICENSE"
|
||||
},
|
||||
"spine-player": {
|
||||
"name": "@esotericsoftware/spine-player",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"license": "LicenseRef-LICENSE",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-webgl": "^4.0.20"
|
||||
"@esotericsoftware/spine-webgl": "^4.0.27"
|
||||
}
|
||||
},
|
||||
"spine-threejs": {
|
||||
"name": "@esotericsoftware/spine-threejs",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"license": "LicenseRef-LICENSE",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-core": "^4.0.20",
|
||||
"@types/three": "^0.133.1",
|
||||
"three": "^0.133.1"
|
||||
"@esotericsoftware/spine-core": "^4.0.27",
|
||||
"@types/three": "^0.138.0",
|
||||
"three": "^0.138.3"
|
||||
}
|
||||
},
|
||||
"spine-webgl": {
|
||||
"name": "@esotericsoftware/spine-webgl",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"license": "LicenseRef-LICENSE",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-core": "^4.0.20"
|
||||
"@esotericsoftware/spine-core": "^4.0.27"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -7993,7 +8009,7 @@
|
||||
"@esotericsoftware/spine-canvas": {
|
||||
"version": "file:spine-canvas",
|
||||
"requires": {
|
||||
"@esotericsoftware/spine-core": "^4.0.20"
|
||||
"@esotericsoftware/spine-core": "^4.0.27"
|
||||
}
|
||||
},
|
||||
"@esotericsoftware/spine-core": {
|
||||
@ -8002,21 +8018,21 @@
|
||||
"@esotericsoftware/spine-player": {
|
||||
"version": "file:spine-player",
|
||||
"requires": {
|
||||
"@esotericsoftware/spine-webgl": "^4.0.20"
|
||||
"@esotericsoftware/spine-webgl": "^4.0.27"
|
||||
}
|
||||
},
|
||||
"@esotericsoftware/spine-threejs": {
|
||||
"version": "file:spine-threejs",
|
||||
"requires": {
|
||||
"@esotericsoftware/spine-core": "^4.0.20",
|
||||
"@types/three": "^0.133.1",
|
||||
"three": "^0.133.1"
|
||||
"@esotericsoftware/spine-core": "^4.0.27",
|
||||
"@types/three": "^0.138.0",
|
||||
"three": "^0.138.3"
|
||||
}
|
||||
},
|
||||
"@esotericsoftware/spine-webgl": {
|
||||
"version": "file:spine-webgl",
|
||||
"requires": {
|
||||
"@esotericsoftware/spine-core": "^4.0.20"
|
||||
"@esotericsoftware/spine-core": "^4.0.27"
|
||||
}
|
||||
},
|
||||
"@types/offscreencanvas": {
|
||||
@ -8026,18 +8042,18 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/three": {
|
||||
"version": "0.133.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.133.1.tgz",
|
||||
"integrity": "sha512-XqBrP/+kbs+o0CYRhCVVE95v7FaL2bO5Z7+3VQJE0nEyjo+9LoLfeNgZITOnndKHxM+7ltEciAIR7uE0SZlsOg=="
|
||||
"version": "0.138.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.138.0.tgz",
|
||||
"integrity": "sha512-D8AoV7h2kbCfrv/DcebHOFh1WDwyus3HdooBkAwcBikXArdqnsQ38PQ85JCunnvun160oA9jz53GszF3zch3tg=="
|
||||
},
|
||||
"accepts": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mime-types": "~2.1.24",
|
||||
"negotiator": "0.6.2"
|
||||
"mime-types": "~2.1.34",
|
||||
"negotiator": "0.6.3"
|
||||
}
|
||||
},
|
||||
"ansi-regex": {
|
||||
@ -8505,9 +8521,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"destroy": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
|
||||
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
|
||||
"dev": true
|
||||
},
|
||||
"duplexer": {
|
||||
@ -8807,9 +8823,9 @@
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.9",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
|
||||
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
|
||||
"version": "4.2.10",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
|
||||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
@ -8863,30 +8879,30 @@
|
||||
}
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
|
||||
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"depd": "2.0.0",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"statuses": "2.0.1",
|
||||
"toidentifier": "1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||
"statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"http-parser-js": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz",
|
||||
"integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==",
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz",
|
||||
"integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==",
|
||||
"dev": true
|
||||
},
|
||||
"inflight": {
|
||||
@ -9154,24 +9170,24 @@
|
||||
"dev": true
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.51.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
|
||||
"integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.34",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
|
||||
"integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mime-db": "1.51.0"
|
||||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
@ -9277,9 +9293,9 @@
|
||||
}
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
|
||||
"dev": true
|
||||
},
|
||||
"noms": {
|
||||
@ -13565,37 +13581,46 @@
|
||||
}
|
||||
},
|
||||
"send": {
|
||||
"version": "0.17.2",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz",
|
||||
"integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==",
|
||||
"version": "0.18.0",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
|
||||
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"destroy": "~1.0.4",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "1.8.1",
|
||||
"http-errors": "2.0.0",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.3",
|
||||
"on-finished": "~2.3.0",
|
||||
"on-finished": "2.4.1",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "~1.5.0"
|
||||
"statuses": "2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||
"dev": true
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -13938,9 +13963,9 @@
|
||||
}
|
||||
},
|
||||
"three": {
|
||||
"version": "0.133.1",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.133.1.tgz",
|
||||
"integrity": "sha512-WydohO8ll949B0FTD6MGz59Yv2Lwj8hvObg/0Heh2r42S6+tQC1WByfCNRdmG4D7+odfGod+n8JPV1I2xrboWw=="
|
||||
"version": "0.138.3",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.138.3.tgz",
|
||||
"integrity": "sha512-4t1cKC8gimNyJChJbaklg8W/qj3PpsLJUIFm5LIuAy/hVxxNm1ru2FGTSfbTSsuHmC/7ipsyuGKqrSAKLNtkzg=="
|
||||
},
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
@ -14061,9 +14086,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.5.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
|
||||
"integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
|
||||
"version": "4.6.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
|
||||
"integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
|
||||
"dev": true
|
||||
},
|
||||
"union-value": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-ts",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"description": "The official Spine Runtimes for the web.",
|
||||
"files": [
|
||||
"README.md"
|
||||
|
||||
@ -1,181 +1,89 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="../dist/iife/spine-canvas.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
height: 100%
|
||||
}
|
||||
<head>
|
||||
<!--<script src="https://unpkg.com/@esotericsoftware/spine-canvas@4.0.*/dist/iife/spine-canvas.js"></script>-->
|
||||
<script src="../dist/iife/spine-canvas.js"></script>
|
||||
</head>
|
||||
|
||||
canvas {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
<body style="margin: 0; padding: 0; background: #333">
|
||||
<canvas id="canvas" style="width: 100%; height: 100vh;"></canvas>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
let lastFrameTime = Date.now() / 1000;
|
||||
let canvas, context;
|
||||
let assetManager;
|
||||
let skeleton, animationState, bounds;
|
||||
let skeletonRenderer;
|
||||
|
||||
var lastFrameTime = Date.now() / 1000;
|
||||
var canvas, context;
|
||||
var assetManager;
|
||||
var skeleton, state, bounds;
|
||||
var skeletonRenderer;
|
||||
|
||||
var skelName = "spineboy-ess";
|
||||
var animName = "walk";
|
||||
|
||||
function init() {
|
||||
async function load() {
|
||||
canvas = document.getElementById("canvas");
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
context = canvas.getContext("2d");
|
||||
|
||||
skeletonRenderer = new spine.SkeletonRenderer(context);
|
||||
// enable debug rendering
|
||||
skeletonRenderer.debugRendering = true;
|
||||
// enable the triangle renderer, supports meshes, but may produce artifacts in some browsers
|
||||
skeletonRenderer.triangleRendering = false;
|
||||
|
||||
assetManager = new spine.AssetManager("assets/");
|
||||
// Load the assets.
|
||||
assetManager = new spine.AssetManager("https://esotericsoftware.com/files/examples/4.0/spineboy/export/");
|
||||
assetManager.loadText("spineboy-ess.json");
|
||||
assetManager.loadTextureAtlas("spineboy.atlas");
|
||||
await assetManager.loadAll();
|
||||
|
||||
assetManager.loadText(skelName + ".json");
|
||||
assetManager.loadText(skelName.replace("-pro", "").replace("-ess", "") + ".atlas");
|
||||
assetManager.loadTexture(skelName.replace("-pro", "").replace("-ess", "") + ".png");
|
||||
// Create the texture atlas and skeleton data.
|
||||
let atlas = assetManager.require("spineboy.atlas");
|
||||
let atlasLoader = new spine.AtlasAttachmentLoader(atlas);
|
||||
let skeletonJson = new spine.SkeletonJson(atlasLoader);
|
||||
let skeletonData = skeletonJson.readSkeletonData(assetManager.require("spineboy-ess.json"));
|
||||
|
||||
requestAnimationFrame(load);
|
||||
}
|
||||
|
||||
function load() {
|
||||
if (assetManager.isLoadingComplete()) {
|
||||
var data = loadSkeleton(skelName, animName, "default");
|
||||
skeleton = data.skeleton;
|
||||
state = data.state;
|
||||
bounds = data.bounds;
|
||||
requestAnimationFrame(render);
|
||||
} else {
|
||||
requestAnimationFrame(load);
|
||||
}
|
||||
}
|
||||
|
||||
function loadSkeleton(name, initialAnimation, skin) {
|
||||
if (skin === undefined) skin = "default";
|
||||
|
||||
// Load the texture atlas using name.atlas and name.png from the AssetManager.
|
||||
// The function passed to TextureAtlas is used to resolve relative paths.
|
||||
atlas = new spine.TextureAtlas(assetManager.require(name.replace("-pro", "").replace("-ess", "") + ".atlas"));
|
||||
atlas.setTextures(assetManager);
|
||||
|
||||
// Create a AtlasAttachmentLoader, which is specific to the WebGL backend.
|
||||
atlasLoader = new spine.AtlasAttachmentLoader(atlas);
|
||||
|
||||
// Create a SkeletonJson instance for parsing the .json file.
|
||||
var skeletonJson = new spine.SkeletonJson(atlasLoader);
|
||||
|
||||
// Set the scale to apply during parsing, parse the file, and create a new skeleton.
|
||||
var skeletonData = skeletonJson.readSkeletonData(assetManager.require(name + ".json"));
|
||||
var skeleton = new spine.Skeleton(skeletonData);
|
||||
skeleton.scaleY = -1;
|
||||
var bounds = calculateBounds(skeleton);
|
||||
skeleton.setSkinByName(skin);
|
||||
|
||||
// Create an AnimationState, and set the initial animation in looping mode.
|
||||
var animationState = new spine.AnimationState(new spine.AnimationStateData(skeleton.data));
|
||||
animationState.setAnimation(0, initialAnimation, true);
|
||||
animationState.addListener({
|
||||
event: function (trackIndex, event) {
|
||||
// console.log("Event on track " + trackIndex + ": " + JSON.stringify(event));
|
||||
},
|
||||
complete: function (trackIndex, loopCount) {
|
||||
// console.log("Animation on track " + trackIndex + " completed, loop count: " + loopCount);
|
||||
},
|
||||
start: function (trackIndex) {
|
||||
// console.log("Animation on track " + trackIndex + " started");
|
||||
},
|
||||
end: function (trackIndex) {
|
||||
// console.log("Animation on track " + trackIndex + " ended");
|
||||
}
|
||||
})
|
||||
|
||||
// Pack everything up and return to caller.
|
||||
return { skeleton: skeleton, state: animationState, bounds: bounds };
|
||||
}
|
||||
|
||||
function calculateBounds(skeleton) {
|
||||
var data = skeleton.data;
|
||||
// Instantiate a new skeleton based on the atlas and skeleton data.
|
||||
skeleton = new spine.Skeleton(skeletonData);
|
||||
skeleton.setToSetupPose();
|
||||
skeleton.updateWorldTransform();
|
||||
var offset = new spine.Vector2();
|
||||
var size = new spine.Vector2();
|
||||
skeleton.getBounds(offset, size, []);
|
||||
return { offset: offset, size: size };
|
||||
bounds = skeleton.getBoundsRect();
|
||||
|
||||
// Setup an animation state with a default mix of 0.2 seconds.
|
||||
var animationStateData = new spine.AnimationStateData(skeleton.data);
|
||||
animationStateData.defaultMix = 0.2;
|
||||
animationState = new spine.AnimationState(animationStateData);
|
||||
|
||||
// Set the run animation, looping.
|
||||
animationState.setAnimation(0, "run", true);
|
||||
|
||||
// Start rendering.
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
function render() {
|
||||
// Calculate the delta time between this and the last frame in seconds.
|
||||
var now = Date.now() / 1000;
|
||||
var delta = now - lastFrameTime;
|
||||
lastFrameTime = now;
|
||||
|
||||
resize();
|
||||
// Resize the canvas drawing buffer if the canvas CSS width and height changed
|
||||
// and clear the canvas.
|
||||
if (canvas.width != canvas.clientWidth || canvas.height != canvas.clientHeight) {
|
||||
canvas.width = canvas.clientWidth;
|
||||
canvas.height = canvas.clientHeight;
|
||||
}
|
||||
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
context.save();
|
||||
context.setTransform(1, 0, 0, 1, 0, 0);
|
||||
context.fillStyle = "#cccccc";
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
context.restore();
|
||||
// Center the skeleton and resize it so it fits inside the canvas.
|
||||
skeleton.x = canvas.width / 2;
|
||||
skeleton.y = canvas.height - canvas.height * 0.1;
|
||||
let scale = canvas.height / bounds.height * 0.8;
|
||||
skeleton.scaleX = scale;
|
||||
skeleton.scaleY = -scale;
|
||||
|
||||
state.update(delta);
|
||||
state.apply(skeleton);
|
||||
// Update and apply the animation state, update the skeleton's
|
||||
// world transforms and render the skeleton.
|
||||
animationState.update(delta);
|
||||
animationState.apply(skeleton);
|
||||
skeleton.updateWorldTransform();
|
||||
skeletonRenderer.draw(skeleton);
|
||||
|
||||
context.strokeStyle = "green";
|
||||
context.beginPath();
|
||||
context.moveTo(-1000, 0);
|
||||
context.lineTo(1000, 0);
|
||||
context.moveTo(0, -1000);
|
||||
context.lineTo(0, 1000);
|
||||
context.stroke();
|
||||
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
function resize() {
|
||||
var w = canvas.clientWidth;
|
||||
var h = canvas.clientHeight;
|
||||
if (canvas.width != w || canvas.height != h) {
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
}
|
||||
|
||||
// magic
|
||||
var centerX = bounds.offset.x + bounds.size.x / 2;
|
||||
var centerY = bounds.offset.y + bounds.size.y / 2;
|
||||
var scaleX = bounds.size.x / canvas.width;
|
||||
var scaleY = bounds.size.y / canvas.height;
|
||||
var scale = Math.max(scaleX, scaleY) * 1.2;
|
||||
if (scale < 1) scale = 1;
|
||||
var width = canvas.width * scale;
|
||||
var height = canvas.height * scale;
|
||||
|
||||
context.setTransform(1, 0, 0, 1, 0, 0);
|
||||
context.scale(1 / scale, 1 / scale);
|
||||
context.translate(-centerX, -centerY);
|
||||
context.translate(width / 2, height / 2);
|
||||
}
|
||||
|
||||
(function () {
|
||||
init();
|
||||
}());
|
||||
|
||||
load();
|
||||
</script>
|
||||
|
||||
</html>
|
||||
111
spine-ts/spine-canvas/example/mouse-click.html
Normal file
111
spine-ts/spine-canvas/example/mouse-click.html
Normal file
@ -0,0 +1,111 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<!--<script src="https://unpkg.com/@esotericsoftware/spine-canvas@4.0.*/dist/iife/spine-canvas.js"></script>-->
|
||||
<script src="../dist/iife/spine-canvas.js"></script>
|
||||
</head>
|
||||
|
||||
<body style="margin: 0; padding: 0; background: #333">
|
||||
<canvas id="canvas" style="width: 100%; height: 100vh;"></canvas>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
let lastFrameTime = Date.now() / 1000;
|
||||
let canvas, context;
|
||||
let assetManager;
|
||||
let skeleton, animationState, bounds;
|
||||
let skeletonRenderer;
|
||||
|
||||
async function load() {
|
||||
canvas = document.getElementById("canvas");
|
||||
context = canvas.getContext("2d");
|
||||
skeletonRenderer = new spine.SkeletonRenderer(context);
|
||||
|
||||
// Load the assets.
|
||||
assetManager = new spine.AssetManager("https://esotericsoftware.com/files/examples/4.0/spineboy/export/");
|
||||
assetManager.loadText("spineboy-ess.json");
|
||||
assetManager.loadTextureAtlas("spineboy.atlas");
|
||||
await assetManager.loadAll();
|
||||
|
||||
// Create the texture atlas and skeleton data.
|
||||
let atlas = assetManager.require("spineboy.atlas");
|
||||
let atlasLoader = new spine.AtlasAttachmentLoader(atlas);
|
||||
let skeletonJson = new spine.SkeletonJson(atlasLoader);
|
||||
let skeletonData = skeletonJson.readSkeletonData(assetManager.require("spineboy-ess.json"));
|
||||
|
||||
// Instantiate a new skeleton based on the atlas and skeleton data.
|
||||
skeleton = new spine.Skeleton(skeletonData);
|
||||
skeleton.setToSetupPose();
|
||||
skeleton.updateWorldTransform();
|
||||
bounds = skeleton.getBoundsRect();
|
||||
|
||||
// Setup an animation state with a default mix of 0.2 seconds.
|
||||
var animationStateData = new spine.AnimationStateData(skeleton.data);
|
||||
animationStateData.defaultMix = 0.2;
|
||||
animationState = new spine.AnimationState(animationStateData);
|
||||
|
||||
// Add a click listener to the canvas which checks if Spineboy's head
|
||||
// was clicked.
|
||||
canvas.addEventListener('click', event => {
|
||||
// Make the mouse click coordinates relative to the canvas.
|
||||
let canvasRect = canvas.getBoundingClientRect();
|
||||
var mouseX = event.x - canvasRect.x;
|
||||
var mouseY = event.y - canvasRect.y;
|
||||
|
||||
// Find the "head" bone.
|
||||
var headBone = skeleton.findBone("head");
|
||||
|
||||
// If the mouse pointer is within 100 pixels of the head bone, fire the jump animation event.
|
||||
// Afterwards, loop the run animation.
|
||||
if (pointInCircle(mouseX, mouseY, headBone.worldX, headBone.worldY, 100)) {
|
||||
var jumpEntry = animationState.setAnimation(0, "jump", false);
|
||||
var walkEntry = animationState.addAnimation(0, "run", true);
|
||||
}
|
||||
});
|
||||
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
function render() {
|
||||
// Calculate the delta time between this and the last frame in seconds.
|
||||
var now = Date.now() / 1000;
|
||||
var delta = now - lastFrameTime;
|
||||
lastFrameTime = now;
|
||||
|
||||
// Resize the canvas drawing buffer if the canvas CSS width and height changed
|
||||
// and clear the canvas.
|
||||
if (canvas.width != canvas.clientWidth || canvas.height != canvas.clientHeight) {
|
||||
canvas.width = canvas.clientWidth;
|
||||
canvas.height = canvas.clientHeight;
|
||||
}
|
||||
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Center the skeleton and resize it so it fits inside the canvas.
|
||||
skeleton.x = canvas.width / 2;
|
||||
skeleton.y = canvas.height - canvas.height * 0.1;
|
||||
let scale = canvas.height / bounds.height * 0.8;
|
||||
skeleton.scaleX = scale;
|
||||
skeleton.scaleY = -scale;
|
||||
|
||||
// Update and apply the animation state, update the skeleton's
|
||||
// world transforms and render the skeleton.
|
||||
animationState.update(delta);
|
||||
animationState.apply(skeleton);
|
||||
skeleton.updateWorldTransform();
|
||||
skeletonRenderer.draw(skeleton);
|
||||
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
// Checks if the point given by x/y are within the circle.
|
||||
function pointInCircle(x, y, circleX, circleY, circleRadius) {
|
||||
var distX = x - circleX;
|
||||
var distY = y - circleY;
|
||||
return distX * distX + distY * distY <= circleRadius * circleRadius;
|
||||
}
|
||||
|
||||
load();
|
||||
</script>
|
||||
|
||||
</html>
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-canvas",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"description": "The official Spine Runtimes for the web.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@ -30,6 +30,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-core": "^4.0.20"
|
||||
"@esotericsoftware/spine-core": "^4.0.27"
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-core",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"description": "The official Spine Runtimes for the web.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@ -65,6 +65,21 @@ export class AssetManagerBase implements Disposable {
|
||||
if (callback) callback(path, message);
|
||||
}
|
||||
|
||||
loadAll () {
|
||||
let promise = new Promise((resolve: (assetManager: AssetManagerBase) => void, reject: (errors: StringMap<string>) => void) => {
|
||||
let check = () => {
|
||||
if (this.isLoadingComplete()) {
|
||||
if (this.hasErrors()) reject(this.errors);
|
||||
else resolve(this);
|
||||
return;
|
||||
}
|
||||
requestAnimationFrame(check);
|
||||
}
|
||||
requestAnimationFrame(check);
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
setRawDataURI (path: string, data: string) {
|
||||
this.downloader.rawDataUris[this.pathPrefix + path] = data;
|
||||
}
|
||||
|
||||
@ -585,6 +585,15 @@ export class Skeleton {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose as `{ x: number, y: number, width: number, height: number }`.
|
||||
* Note that this method will create temporary objects which can add to garbage collection pressure. Use `getBounds()` if garbage collection is a concern. */
|
||||
getBoundsRect () {
|
||||
let offset = new Vector2();
|
||||
let size = new Vector2();
|
||||
this.getBounds(offset, size);
|
||||
return { x: offset.x, y: offset.y, width: size.x, height: size.y };
|
||||
}
|
||||
|
||||
/** Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
|
||||
* @param offset An output value, the distance from the skeleton origin to the bottom left corner of the AABB.
|
||||
* @param size An output value, the width and height of the AABB.
|
||||
|
||||
@ -1022,7 +1022,7 @@ export class BinaryInput {
|
||||
let chars = "";
|
||||
let charCount = 0;
|
||||
for (let i = 0; i < byteCount;) {
|
||||
let b = this.readByte();
|
||||
let b = this.readUnsignedByte();
|
||||
switch (b >> 4) {
|
||||
case 12:
|
||||
case 13:
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-player",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"description": "The official Spine Runtimes for the web.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@ -30,6 +30,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-webgl": "^4.0.20"
|
||||
"@esotericsoftware/spine-webgl": "^4.0.27"
|
||||
}
|
||||
}
|
||||
@ -258,7 +258,7 @@ export class SpinePlayer implements Disposable {
|
||||
|
||||
dispose (): void {
|
||||
this.sceneRenderer.dispose();
|
||||
this.loadingScreen.dispose();
|
||||
if (this.loadingScreen) this.loadingScreen.dispose();
|
||||
this.assetManager.dispose();
|
||||
for (var i = 0; i < this.eventListeners.length; i++) {
|
||||
var eventListener = this.eventListeners[i];
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>spine-threejs</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.js"></script>
|
||||
<script src="https://unpkg.com/three@0.138.3/build/three.js"></script>
|
||||
<script src="../dist/iife/spine-threejs.js"></script>
|
||||
</head>
|
||||
<style>
|
||||
@ -81,8 +81,9 @@
|
||||
var skeletonData = skeletonJson.readSkeletonData(assetManager.require(skeletonFile));
|
||||
|
||||
// Create a SkeletonMesh from the data and attach it to the scene
|
||||
skeletonMesh = new spine.SkeletonMesh(skeletonData, function (parameters) {
|
||||
skeletonMesh = new spine.SkeletonMesh(skeletonData, (parameters) => {
|
||||
parameters.depthTest = false;
|
||||
parameters.alphaTest = 0.5;
|
||||
});
|
||||
skeletonMesh.state.setAnimation(0, animation, true);
|
||||
mesh.add(skeletonMesh);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-threejs",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"description": "The official Spine Runtimes for the web.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@ -30,8 +30,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
|
||||
"dependencies": {
|
||||
"@types/three": "^0.133.1",
|
||||
"three": "^0.133.1",
|
||||
"@esotericsoftware/spine-core": "^4.0.20"
|
||||
"@types/three": "^0.138.0",
|
||||
"three": "^0.138.3",
|
||||
"@esotericsoftware/spine-core": "^4.0.27"
|
||||
}
|
||||
}
|
||||
@ -32,9 +32,7 @@ import { MeshBatcher } from "./MeshBatcher";
|
||||
import * as THREE from "three";
|
||||
import { ThreeJsTexture } from "./ThreeJsTexture";
|
||||
|
||||
export interface SkeletonMeshMaterialParametersCustomizer {
|
||||
(materialParameters: THREE.ShaderMaterialParameters): void;
|
||||
}
|
||||
export type SkeletonMeshMaterialParametersCustomizer = (materialParameters: THREE.ShaderMaterialParameters) => void;
|
||||
|
||||
export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
|
||||
constructor (customizer: SkeletonMeshMaterialParametersCustomizer) {
|
||||
@ -50,26 +48,35 @@ export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
|
||||
`;
|
||||
let fragmentShader = `
|
||||
uniform sampler2D map;
|
||||
#ifdef USE_SPINE_ALPHATEST
|
||||
uniform float alphaTest;
|
||||
#endif
|
||||
varying vec2 vUv;
|
||||
varying vec4 vColor;
|
||||
void main(void) {
|
||||
gl_FragColor = texture2D(map, vUv)*vColor;
|
||||
if (gl_FragColor.a < 0.5) discard;
|
||||
#ifdef USE_SPINE_ALPHATEST
|
||||
if (gl_FragColor.a < alphaTest) discard;
|
||||
#endif
|
||||
}
|
||||
`;
|
||||
|
||||
let parameters: THREE.ShaderMaterialParameters = {
|
||||
uniforms: {
|
||||
map: { type: "t", value: null } as any
|
||||
map: { value: null },
|
||||
},
|
||||
vertexShader: vertexShader,
|
||||
fragmentShader: fragmentShader,
|
||||
side: THREE.DoubleSide,
|
||||
transparent: true,
|
||||
depthWrite: false,
|
||||
alphaTest: 0.5
|
||||
alphaTest: 0.0
|
||||
};
|
||||
customizer(parameters);
|
||||
if (parameters.alphaTest > 0) {
|
||||
parameters.defines = { "USE_SPINE_ALPHATEST": 1 };
|
||||
parameters.uniforms["alphaTest"] = { value: parameters.alphaTest };
|
||||
}
|
||||
super(parameters);
|
||||
};
|
||||
}
|
||||
@ -94,7 +101,7 @@ export class SkeletonMesh extends THREE.Object3D {
|
||||
private vertices = Utils.newFloatArray(1024);
|
||||
private tempColor = new Color();
|
||||
|
||||
constructor (skeletonData: SkeletonData) {
|
||||
constructor (skeletonData: SkeletonData, private materialCustomerizer: SkeletonMeshMaterialParametersCustomizer = (material) => { }) {
|
||||
super();
|
||||
|
||||
this.skeleton = new Skeleton(skeletonData);
|
||||
@ -129,7 +136,7 @@ export class SkeletonMesh extends THREE.Object3D {
|
||||
|
||||
private nextBatch () {
|
||||
if (this.batches.length == this.nextBatchIndex) {
|
||||
let batch = new MeshBatcher();
|
||||
let batch = new MeshBatcher(10920, this.materialCustomerizer);
|
||||
this.add(batch);
|
||||
this.batches.push(batch);
|
||||
}
|
||||
@ -164,7 +171,10 @@ export class SkeletonMesh extends THREE.Object3D {
|
||||
for (let i = 0, n = drawOrder.length; i < n; i++) {
|
||||
let vertexSize = clipper.isClipping() ? 2 : SkeletonMesh.VERTEX_SIZE;
|
||||
let slot = drawOrder[i];
|
||||
if (!slot.bone.active) continue;
|
||||
if (!slot.bone.active) {
|
||||
clipper.clipEndWithSlot(slot);
|
||||
continue;
|
||||
}
|
||||
let attachment = slot.getAttachment();
|
||||
let attachmentColor: Color = null;
|
||||
let texture: ThreeJsTexture = null;
|
||||
@ -194,7 +204,10 @@ export class SkeletonMesh extends THREE.Object3D {
|
||||
let clip = <ClippingAttachment>(attachment);
|
||||
clipper.clipStart(slot, clip);
|
||||
continue;
|
||||
} else continue;
|
||||
} else {
|
||||
clipper.clipEndWithSlot(slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (texture != null) {
|
||||
let skeleton = slot.bone.skeleton;
|
||||
@ -278,8 +291,10 @@ export class SkeletonMesh extends THREE.Object3D {
|
||||
finalIndicesLength = triangles.length;
|
||||
}
|
||||
|
||||
if (finalVerticesLength == 0 || finalIndicesLength == 0)
|
||||
if (finalVerticesLength == 0 || finalIndicesLength == 0) {
|
||||
clipper.clipEndWithSlot(slot);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Start new batch if this one can't hold vertices/indices
|
||||
if (!batch.canBatch(finalVerticesLength, finalIndicesLength)) {
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
<div style="position: absolute; top: 1em; left: 1em; z-index: 1; color: #ccc;">
|
||||
<label style="margin-right: 0.5em;">Animations</label>
|
||||
<select id="animations"></select>
|
||||
<label>PMA</label>
|
||||
<input type="checkbox" id="pma" checked>
|
||||
</div>
|
||||
<script src="drag-and-drop.js"></script>
|
||||
</body>
|
||||
|
||||
@ -3,6 +3,7 @@ class App {
|
||||
this.skeleton = null;
|
||||
this.animationState = null;
|
||||
this.canvas = null;
|
||||
this.pma = true;
|
||||
}
|
||||
|
||||
loadAssets(canvas) {
|
||||
@ -23,6 +24,12 @@ class App {
|
||||
this.animationState.setAnimation(0, animationSelectBox.value, true);
|
||||
}
|
||||
|
||||
// Setup listener for the PMA checkbox
|
||||
let pmaCheckbox = document.body.querySelector("#pma");
|
||||
pmaCheckbox.onchange = () => {
|
||||
this.pma = pmaCheckbox.checked;
|
||||
}
|
||||
|
||||
// Setup the drag and drop listener
|
||||
new FileDragAndDrop(canvas.htmlCanvas, (files) => this.onDrop(files))
|
||||
|
||||
@ -116,8 +123,7 @@ class App {
|
||||
option.selected = animation.name == animationName;
|
||||
animationSelectBox.appendChild(option);
|
||||
}
|
||||
|
||||
if (animationName) this.animationState.setAnimation(0, animationName, true);
|
||||
this.animationState.setAnimation(0, animationName, true);
|
||||
|
||||
// Center the skeleton in the viewport
|
||||
this.centerSkeleton();
|
||||
@ -153,10 +159,11 @@ class App {
|
||||
renderer.resize(spine.ResizeMode.Expand);
|
||||
|
||||
canvas.clear(0.2, 0.2, 0.2, 1);
|
||||
|
||||
renderer.begin();
|
||||
renderer.line(-10000, 0, 10000, 0, spine.Color.RED);
|
||||
renderer.line(0, -10000, 0, 10000, spine.Color.GREEN);
|
||||
renderer.drawSkeleton(this.skeleton, true);
|
||||
renderer.drawSkeleton(this.skeleton, this.pma);
|
||||
renderer.end();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@esotericsoftware/spine-webgl",
|
||||
"version": "4.0.20",
|
||||
"version": "4.0.27",
|
||||
"description": "The official Spine Runtimes for the web.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@ -30,6 +30,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/esotericsoftware/spine-runtimes#readme",
|
||||
"dependencies": {
|
||||
"@esotericsoftware/spine-core": "^4.0.20"
|
||||
"@esotericsoftware/spine-core": "^4.0.27"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28687d6c4c7e84e48a6907ea466198f9
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,90 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated January 1, 2020. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2022, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#define HAS_VECTOR_INT
|
||||
#endif
|
||||
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
public class RenderTextureFadeoutExample : MonoBehaviour {
|
||||
|
||||
public SkeletonRenderTextureFadeout renderTextureFadeout;
|
||||
public SkeletonRenderer normalSkeletonRenderer;
|
||||
|
||||
float fadeoutSeconds = 2.0f;
|
||||
float fadeoutSecondsRemaining;
|
||||
|
||||
IEnumerator Start () {
|
||||
while (true) {
|
||||
StartFadeoutBad();
|
||||
StartFadeoutGood();
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
}
|
||||
}
|
||||
void Update () {
|
||||
UpdateBadFadeOutAlpha();
|
||||
}
|
||||
|
||||
void UpdateBadFadeOutAlpha () {
|
||||
if (fadeoutSecondsRemaining == 0)
|
||||
return;
|
||||
|
||||
fadeoutSecondsRemaining -= Time.deltaTime;
|
||||
if (fadeoutSecondsRemaining <= 0) {
|
||||
fadeoutSecondsRemaining = 0;
|
||||
return;
|
||||
}
|
||||
float fadeoutAlpha = fadeoutSecondsRemaining / fadeoutSeconds;
|
||||
|
||||
// changing transparency at a MeshRenderer does not yield the desired effect
|
||||
// due to overlapping attachment meshes.
|
||||
normalSkeletonRenderer.Skeleton.SetColor(new Color(1, 1, 1, fadeoutAlpha));
|
||||
}
|
||||
|
||||
void StartFadeoutBad () {
|
||||
fadeoutSecondsRemaining = fadeoutSeconds;
|
||||
}
|
||||
|
||||
void StartFadeoutGood () {
|
||||
renderTextureFadeout.gameObject.SetActive(true);
|
||||
// enabling the SkeletonRenderTextureFadeout component starts the fadeout.
|
||||
renderTextureFadeout.enabled = true;
|
||||
renderTextureFadeout.OnFadeoutComplete -= DisableGameObject;
|
||||
renderTextureFadeout.OnFadeoutComplete += DisableGameObject;
|
||||
}
|
||||
|
||||
void DisableGameObject (SkeletonRenderTextureFadeout target) {
|
||||
target.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e55c8477eccddc4cb5c3551a3945ca7
|
||||
guid: a4cc2b5fcffcac846aacb02b6dad0440
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b5dc12395d030642b857afc9dff2ae2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,90 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: RenderQuadMaterial
|
||||
m_Shader: {fileID: 4800000, guid: 1e0cc951f440af74dacaf86ac4ae2602, type: 3}
|
||||
m_ShaderKeywords: _ALPHAPREMULTIPLY_ON _USE8NEIGHBOURHOOD_ON
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DarkColorAlphaAdditive: 0
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 10
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 3
|
||||
- _OcclusionStrength: 1
|
||||
- _OutlineMipLevel: 0
|
||||
- _OutlineReferenceTexWidth: 1024
|
||||
- _OutlineSmoothness: 1
|
||||
- _OutlineWidth: 3
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _StencilComp: 8
|
||||
- _StencilRef: 1
|
||||
- _StraightAlphaInput: 0
|
||||
- _ThresholdEnd: 0.25
|
||||
- _UVSec: 0
|
||||
- _Use8Neighbourhood: 1
|
||||
- _ZWrite: 0
|
||||
m_Colors:
|
||||
- _Black: {r: 0, g: 0, b: 0, a: 0}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _OutlineColor: {r: 1, g: 1, b: 0, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c507f887c6274a44a603d96e0eabf2a
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,104 @@
|
||||
// Simple shader for e.g. a Quad that renders a RenderTexture.
|
||||
// Texture color is multiplied by a color property, mostly for alpha fadeout.
|
||||
Shader "Spine/RenderQuad" {
|
||||
Properties{
|
||||
_Color("Color", Color) = (1,1,1,1)
|
||||
[NoScaleOffset] _MainTex("MainTex", 2D) = "white" {}
|
||||
_Cutoff("Shadow alpha cutoff", Range(0,1)) = 0.1
|
||||
[HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
|
||||
[HideInInspector][Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
|
||||
}
|
||||
SubShader{
|
||||
Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" }
|
||||
Blend One OneMinusSrcAlpha
|
||||
Cull Off
|
||||
ZWrite Off
|
||||
Lighting Off
|
||||
|
||||
Stencil {
|
||||
Ref[_StencilRef]
|
||||
Comp[_StencilComp]
|
||||
Pass Keep
|
||||
}
|
||||
|
||||
Pass {
|
||||
Name "Normal"
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#include "UnityCG.cginc"
|
||||
sampler2D _MainTex;
|
||||
float4 _Color;
|
||||
|
||||
struct VertexInput {
|
||||
float4 vertex : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 vertexColor : COLOR;
|
||||
};
|
||||
|
||||
struct VertexOutput {
|
||||
float4 pos : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 vertexColor : COLOR;
|
||||
};
|
||||
|
||||
VertexOutput vert(VertexInput v) {
|
||||
VertexOutput o = (VertexOutput)0;
|
||||
o.uv = v.uv;
|
||||
o.vertexColor = v.vertexColor;
|
||||
o.pos = UnityObjectToClipPos(v.vertex);
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 frag(VertexOutput i) : SV_Target {
|
||||
float4 texColor = tex2D(_MainTex,i.uv);
|
||||
_Color.rgb *= _Color.a;
|
||||
return texColor * _Color;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
|
||||
Pass {
|
||||
Name "Caster"
|
||||
Tags { "LightMode" = "ShadowCaster" }
|
||||
Offset 1, 1
|
||||
ZWrite On
|
||||
ZTest LEqual
|
||||
|
||||
Fog { Mode Off }
|
||||
Cull Off
|
||||
Lighting Off
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
#pragma multi_compile_shadowcaster
|
||||
#pragma fragmentoption ARB_precision_hint_fastest
|
||||
#include "UnityCG.cginc"
|
||||
sampler2D _MainTex;
|
||||
fixed _Cutoff;
|
||||
|
||||
struct VertexOutput {
|
||||
V2F_SHADOW_CASTER;
|
||||
float4 uvAndAlpha : TEXCOORD1;
|
||||
};
|
||||
|
||||
VertexOutput vert(appdata_base v, float4 vertexColor : COLOR) {
|
||||
VertexOutput o;
|
||||
o.uvAndAlpha = v.texcoord;
|
||||
o.uvAndAlpha.a = vertexColor.a;
|
||||
TRANSFER_SHADOW_CASTER(o)
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 frag(VertexOutput i) : SV_Target {
|
||||
fixed4 texcol = tex2D(_MainTex, i.uvAndAlpha.xy);
|
||||
clip(texcol.a* i.uvAndAlpha.a - _Cutoff);
|
||||
SHADOW_CASTER_FRAGMENT(i)
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
FallBack "Diffuse"
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e0cc951f440af74dacaf86ac4ae2602
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
preprocessorOverride: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,248 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated January 1, 2020. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2022, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
#define HAS_FORCE_RENDER_OFF
|
||||
#endif
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#define HAS_VECTOR_INT
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
/// <summary>
|
||||
/// When enabled, this component renders a skeleton to a RenderTexture and
|
||||
/// then draws this RenderTexture at a quad of the same size.
|
||||
/// This allows changing transparency at a single quad, which produces a more
|
||||
/// natural fadeout effect.
|
||||
/// Note: It is recommended to keep this component disabled as much as possible
|
||||
/// because of the additional rendering overhead. Only enable it when alpha blending is required.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(SkeletonRenderer))]
|
||||
public class SkeletonRenderTexture : MonoBehaviour {
|
||||
#if HAS_VECTOR_INT
|
||||
public Color color = Color.white;
|
||||
public Material quadMaterial;
|
||||
public Camera targetCamera;
|
||||
public int maxRenderTextureSize = 1024;
|
||||
protected SkeletonRenderer skeletonRenderer;
|
||||
protected MeshRenderer meshRenderer;
|
||||
protected MeshFilter meshFilter;
|
||||
public GameObject quad;
|
||||
protected MeshRenderer quadMeshRenderer;
|
||||
protected MeshFilter quadMeshFilter;
|
||||
protected Mesh quadMesh;
|
||||
public RenderTexture renderTexture;
|
||||
|
||||
private CommandBuffer commandBuffer;
|
||||
private MaterialPropertyBlock propertyBlock;
|
||||
private readonly List<Material> materials = new List<Material>();
|
||||
|
||||
protected Vector2Int requiredRenderTextureSize;
|
||||
protected Vector2Int allocatedRenderTextureSize;
|
||||
|
||||
void Awake () {
|
||||
meshRenderer = this.GetComponent<MeshRenderer>();
|
||||
meshFilter = this.GetComponent<MeshFilter>();
|
||||
skeletonRenderer = this.GetComponent<SkeletonRenderer>();
|
||||
if (targetCamera == null)
|
||||
targetCamera = Camera.main;
|
||||
|
||||
commandBuffer = new CommandBuffer();
|
||||
propertyBlock = new MaterialPropertyBlock();
|
||||
|
||||
CreateQuadChild();
|
||||
}
|
||||
|
||||
void OnDestroy () {
|
||||
if (renderTexture)
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
}
|
||||
|
||||
void CreateQuadChild () {
|
||||
quad = new GameObject(this.name + " RenderTexture", typeof(MeshRenderer), typeof(MeshFilter));
|
||||
quad.transform.SetParent(this.transform.parent, false);
|
||||
quadMeshRenderer = quad.GetComponent<MeshRenderer>();
|
||||
quadMeshFilter = quad.GetComponent<MeshFilter>();
|
||||
|
||||
quadMesh = new Mesh();
|
||||
quadMesh.MarkDynamic();
|
||||
quadMesh.name = "RenderTexture Quad";
|
||||
quadMesh.hideFlags = HideFlags.DontSaveInBuild | HideFlags.DontSaveInEditor;
|
||||
|
||||
if (quadMaterial != null)
|
||||
quadMeshRenderer.material = new Material(quadMaterial);
|
||||
else
|
||||
quadMeshRenderer.material = new Material(Shader.Find("Spine/RenderQuad"));
|
||||
}
|
||||
|
||||
void OnEnable () {
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated += RenderOntoQuad;
|
||||
#if HAS_FORCE_RENDER_OFF
|
||||
meshRenderer.forceRenderingOff = true;
|
||||
#else
|
||||
Debug.LogError("This component requires Unity 2019.3 or newer for meshRenderer.forceRenderingOff. " +
|
||||
"Otherwise you will see the mesh rendered twice.");
|
||||
#endif
|
||||
if (quadMeshRenderer)
|
||||
quadMeshRenderer.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
void OnDisable () {
|
||||
skeletonRenderer.OnMeshAndMaterialsUpdated -= RenderOntoQuad;
|
||||
#if HAS_FORCE_RENDER_OFF
|
||||
meshRenderer.forceRenderingOff = false;
|
||||
#endif
|
||||
if (quadMeshRenderer)
|
||||
quadMeshRenderer.gameObject.SetActive(false);
|
||||
if (renderTexture)
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
allocatedRenderTextureSize = Vector2Int.zero;
|
||||
}
|
||||
|
||||
void RenderOntoQuad (SkeletonRenderer skeletonRenderer) {
|
||||
PrepareForMesh();
|
||||
RenderToRenderTexture();
|
||||
AssignAtQuad();
|
||||
}
|
||||
|
||||
protected void PrepareForMesh () {
|
||||
Bounds boundsLocalSpace = meshFilter.sharedMesh.bounds;
|
||||
Vector3 meshMinWorldSpace = transform.TransformPoint(boundsLocalSpace.min);
|
||||
Vector3 meshMaxWorldSpace = transform.TransformPoint(boundsLocalSpace.max);
|
||||
Vector3 meshMinXMaxYWorldSpace = new Vector3(meshMinWorldSpace.x, meshMaxWorldSpace.y);
|
||||
Vector3 meshMaxXMinYWorldSpace = new Vector3(meshMaxWorldSpace.x, meshMinWorldSpace.y);
|
||||
|
||||
// We need to get the min/max of all four corners, close position and rotation of the skeleton
|
||||
// in combination with perspective projection otherwise might lead to incorrect screen space min/max.
|
||||
Vector3 meshMinProjected = targetCamera.WorldToScreenPoint(meshMinWorldSpace);
|
||||
Vector3 meshMaxProjected = targetCamera.WorldToScreenPoint(meshMaxWorldSpace);
|
||||
Vector3 meshMinXMaxYProjected = targetCamera.WorldToScreenPoint(meshMinXMaxYWorldSpace);
|
||||
Vector3 meshMaxXMinYProjected = targetCamera.WorldToScreenPoint(meshMaxXMinYWorldSpace);
|
||||
// To handle 180 degree rotation and thus min/max inversion, we get min/max of all four corners
|
||||
Vector3 meshMinScreenSpace =
|
||||
Vector3.Min(meshMinProjected, Vector3.Min(meshMaxProjected,
|
||||
Vector3.Min(meshMinXMaxYProjected, meshMaxXMinYProjected)));
|
||||
Vector3 meshMaxScreenSpace =
|
||||
Vector3.Max(meshMinProjected, Vector3.Max(meshMaxProjected,
|
||||
Vector3.Max(meshMinXMaxYProjected, meshMaxXMinYProjected)));
|
||||
|
||||
requiredRenderTextureSize = new Vector2Int(
|
||||
Mathf.Min(maxRenderTextureSize, Mathf.CeilToInt(Mathf.Abs(meshMaxScreenSpace.x - meshMinScreenSpace.x))),
|
||||
Mathf.Min(maxRenderTextureSize, Mathf.CeilToInt(Mathf.Abs(meshMaxScreenSpace.y - meshMinScreenSpace.y))));
|
||||
|
||||
PrepareRenderTexture();
|
||||
PrepareCommandBuffer(meshMinWorldSpace, meshMaxWorldSpace);
|
||||
}
|
||||
|
||||
protected void PrepareCommandBuffer (Vector3 meshMinWorldSpace, Vector3 meshMaxWorldSpace) {
|
||||
commandBuffer.Clear();
|
||||
commandBuffer.SetRenderTarget(renderTexture);
|
||||
commandBuffer.ClearRenderTarget(true, true, Color.clear);
|
||||
|
||||
Matrix4x4 projectionMatrix = Matrix4x4.Ortho(
|
||||
meshMinWorldSpace.x, meshMaxWorldSpace.x,
|
||||
meshMinWorldSpace.y, meshMaxWorldSpace.y,
|
||||
float.MinValue, float.MaxValue);
|
||||
|
||||
commandBuffer.SetProjectionMatrix(projectionMatrix);
|
||||
commandBuffer.SetViewport(new Rect(Vector2.zero, requiredRenderTextureSize));
|
||||
}
|
||||
|
||||
protected void RenderToRenderTexture () {
|
||||
meshRenderer.GetPropertyBlock(propertyBlock);
|
||||
meshRenderer.GetSharedMaterials(materials);
|
||||
|
||||
for (int i = 0; i < materials.Count; i++)
|
||||
commandBuffer.DrawMesh(meshFilter.sharedMesh, transform.localToWorldMatrix,
|
||||
materials[i], meshRenderer.subMeshStartIndex + i, -1, propertyBlock);
|
||||
Graphics.ExecuteCommandBuffer(commandBuffer);
|
||||
}
|
||||
|
||||
protected void AssignAtQuad () {
|
||||
Vector2 min = meshFilter.sharedMesh.bounds.min;
|
||||
Vector2 max = meshFilter.sharedMesh.bounds.max;
|
||||
|
||||
Vector3[] vertices = new Vector3[4] {
|
||||
new Vector3(min.x, min.y, 0),
|
||||
new Vector3(max.x, min.y, 0),
|
||||
new Vector3(min.x, max.y, 0),
|
||||
new Vector3(max.x, max.y, 0)
|
||||
};
|
||||
quadMesh.vertices = vertices;
|
||||
|
||||
int[] indices = new int[6] { 0, 2, 1, 2, 3, 1 };
|
||||
quadMesh.triangles = indices;
|
||||
|
||||
Vector3[] normals = new Vector3[4] {
|
||||
-Vector3.forward,
|
||||
-Vector3.forward,
|
||||
-Vector3.forward,
|
||||
-Vector3.forward
|
||||
};
|
||||
quadMesh.normals = normals;
|
||||
|
||||
float maxU = (float)(requiredRenderTextureSize.x) / allocatedRenderTextureSize.x;
|
||||
float maxV = (float)(requiredRenderTextureSize.y) / allocatedRenderTextureSize.y;
|
||||
Vector2[] uv = new Vector2[4] {
|
||||
new Vector2(0, 0),
|
||||
new Vector2(maxU, 0),
|
||||
new Vector2(0, maxV),
|
||||
new Vector2(maxU, maxV)
|
||||
};
|
||||
quadMesh.uv = uv;
|
||||
quadMeshFilter.mesh = quadMesh;
|
||||
quadMeshRenderer.sharedMaterial.mainTexture = this.renderTexture;
|
||||
quadMeshRenderer.sharedMaterial.color = color;
|
||||
|
||||
quadMeshRenderer.transform.position = this.transform.position;
|
||||
quadMeshRenderer.transform.rotation = this.transform.rotation;
|
||||
quadMeshRenderer.transform.localScale = this.transform.localScale;
|
||||
}
|
||||
|
||||
protected void PrepareRenderTexture () {
|
||||
Vector2Int textureSize = new Vector2Int(
|
||||
Mathf.NextPowerOfTwo(requiredRenderTextureSize.x),
|
||||
Mathf.NextPowerOfTwo(requiredRenderTextureSize.y));
|
||||
|
||||
if (textureSize != allocatedRenderTextureSize) {
|
||||
if (renderTexture)
|
||||
RenderTexture.ReleaseTemporary(renderTexture);
|
||||
renderTexture = RenderTexture.GetTemporary(textureSize.x, textureSize.y);
|
||||
allocatedRenderTextureSize = textureSize;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25e6ceb271c9af848ae53f2af1073d0d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,88 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated January 1, 2020. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2022, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
#define HAS_FORCE_RENDER_OFF
|
||||
#endif
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
#define HAS_VECTOR_INT
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Spine.Unity.Examples {
|
||||
|
||||
/// <summary>
|
||||
/// A simple fadeout component that uses a <see cref="SkeletonRenderTexture"/> for transparency fadeout.
|
||||
/// Attach a <see cref="SkeletonRenderTexture"/> and this component to a skeleton GameObject and disable both
|
||||
/// components initially and keep them disabled during normal gameplay. When you need to start fadeout,
|
||||
/// enable this component.
|
||||
/// At the end of the fadeout, the event delegate <c>OnFadeoutComplete</c> is called, to which you can bind e.g.
|
||||
/// a method that disables or destroys the entire GameObject.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(SkeletonRenderTexture))]
|
||||
public class SkeletonRenderTextureFadeout : MonoBehaviour {
|
||||
SkeletonRenderTexture skeletonRenderTexture;
|
||||
|
||||
public float fadeoutSeconds = 2.0f;
|
||||
protected float fadeoutSecondsRemaining;
|
||||
|
||||
public delegate void FadeoutCallback (SkeletonRenderTextureFadeout skeleton);
|
||||
public event FadeoutCallback OnFadeoutComplete;
|
||||
|
||||
protected void Awake () {
|
||||
skeletonRenderTexture = this.GetComponent<SkeletonRenderTexture>();
|
||||
}
|
||||
|
||||
protected void OnEnable () {
|
||||
fadeoutSecondsRemaining = fadeoutSeconds;
|
||||
skeletonRenderTexture.enabled = true;
|
||||
}
|
||||
|
||||
protected void Update () {
|
||||
if (fadeoutSecondsRemaining == 0)
|
||||
return;
|
||||
|
||||
fadeoutSecondsRemaining -= Time.deltaTime;
|
||||
if (fadeoutSecondsRemaining <= 0) {
|
||||
fadeoutSecondsRemaining = 0;
|
||||
if (OnFadeoutComplete != null)
|
||||
OnFadeoutComplete(this);
|
||||
return;
|
||||
}
|
||||
float fadeoutAlpha = fadeoutSecondsRemaining / fadeoutSeconds;
|
||||
#if HAS_VECTOR_INT
|
||||
skeletonRenderTexture.color.a = fadeoutAlpha;
|
||||
#else
|
||||
Debug.LogError("The SkeletonRenderTexture component requires Unity 2017.2 or newer.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5fc94f89310427643babb41e000a8462
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -71,6 +71,7 @@ namespace Spine.Unity.Editor {
|
||||
readonly List<string> warnings = new List<string>();
|
||||
CompatibilityProblemInfo compatibilityProblemInfo = null;
|
||||
readonly SkeletonInspectorPreview preview = new SkeletonInspectorPreview();
|
||||
bool requiresReload = false;
|
||||
|
||||
GUIStyle activePlayButtonStyle, idlePlayButtonStyle;
|
||||
readonly GUIContent DefaultMixLabel = new GUIContent("Default Mix Duration", "Sets 'SkeletonDataAsset.defaultMix' in the asset and 'AnimationState.data.defaultMix' at runtime load time.");
|
||||
@ -153,7 +154,7 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
void Clear () {
|
||||
preview.Clear();
|
||||
targetSkeletonDataAsset.Clear();
|
||||
SpineEditorUtilities.ClearSkeletonDataAsset(targetSkeletonDataAsset);
|
||||
targetSkeletonData = null;
|
||||
}
|
||||
|
||||
@ -192,13 +193,12 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
|
||||
if (changeCheck.changed) {
|
||||
if (serializedObject.ApplyModifiedProperties()) {
|
||||
if (requiresReload || serializedObject.ApplyModifiedProperties()) {
|
||||
this.Clear();
|
||||
this.InitializeEditor();
|
||||
|
||||
if (SpineEditorUtilities.Preferences.autoReloadSceneSkeletons)
|
||||
if (SpineEditorUtilities.Preferences.autoReloadSceneSkeletons && NoProblems())
|
||||
SpineEditorUtilities.DataReloadHandler.ReloadSceneSkeletonComponents(targetSkeletonDataAsset);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -361,18 +361,24 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
void DrawAtlasAssetsFields () {
|
||||
EditorGUILayout.LabelField("Atlas", EditorStyles.boldLabel);
|
||||
#if !SPINE_TK2D
|
||||
EditorGUILayout.PropertyField(atlasAssets, true);
|
||||
#else
|
||||
using (new EditorGUI.DisabledGroupScope(spriteCollection.objectReferenceValue != null)) {
|
||||
EditorGUILayout.PropertyField(atlasAssets, true);
|
||||
}
|
||||
EditorGUILayout.LabelField("spine-tk2d", EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(spriteCollection, true);
|
||||
#endif
|
||||
|
||||
if (atlasAssets.arraySize == 0)
|
||||
EditorGUILayout.HelpBox("AtlasAssets array is empty. Skeleton's attachments will load without being mapped to images.", MessageType.Info);
|
||||
using (var changeCheck = new EditorGUI.ChangeCheckScope()) {
|
||||
#if !SPINE_TK2D
|
||||
EditorGUILayout.PropertyField(atlasAssets, true);
|
||||
#else
|
||||
using (new EditorGUI.DisabledGroupScope(spriteCollection.objectReferenceValue != null)) {
|
||||
EditorGUILayout.PropertyField(atlasAssets, true);
|
||||
}
|
||||
EditorGUILayout.LabelField("spine-tk2d", EditorStyles.boldLabel);
|
||||
EditorGUILayout.PropertyField(spriteCollection, true);
|
||||
#endif
|
||||
if (atlasAssets.arraySize == 0)
|
||||
EditorGUILayout.HelpBox("AtlasAssets array is empty. Skeleton's attachments will load without being mapped to images.", MessageType.Info);
|
||||
|
||||
if (changeCheck.changed) {
|
||||
requiresReload = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleAtlasAssetsNulls () {
|
||||
|
||||
@ -462,7 +462,7 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
|
||||
Debug.LogFormat("Changes to '{0}' or atlas detected. Clearing SkeletonDataAsset: {1}", skeletonJSONPath, localPath);
|
||||
skeletonDataAsset.Clear();
|
||||
SpineEditorUtilities.ClearSkeletonDataAsset(skeletonDataAsset);
|
||||
|
||||
string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(skeletonDataAsset));
|
||||
string lastHash = EditorPrefs.GetString(guid + "_hash");
|
||||
@ -947,7 +947,7 @@ namespace Spine.Unity.Editor {
|
||||
AssetDatabase.CreateAsset(skeletonDataAsset, filePath);
|
||||
} else {
|
||||
skeletonDataAsset.atlasAssets = atlasAssets;
|
||||
skeletonDataAsset.Clear();
|
||||
SpineEditorUtilities.ClearSkeletonDataAsset(skeletonDataAsset);
|
||||
}
|
||||
var skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
if (skeletonData != null)
|
||||
|
||||
@ -96,7 +96,7 @@ namespace Spine.Unity.Editor {
|
||||
}
|
||||
}
|
||||
|
||||
skeletonDataAsset.Clear();
|
||||
SpineEditorUtilities.ClearSkeletonDataAsset(skeletonDataAsset);
|
||||
skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
if (anyMaterialsChanged)
|
||||
ReloadSceneSkeletons(skeletonDataAsset);
|
||||
@ -164,7 +164,7 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
var skinEntries = new List<Skin.SkinEntry>();
|
||||
|
||||
skeletonDataAsset.Clear();
|
||||
SpineEditorUtilities.ClearSkeletonDataAsset(skeletonDataAsset);
|
||||
skeletonDataAsset.isUpgradingBlendModeMaterials = true;
|
||||
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(true);
|
||||
|
||||
|
||||
@ -80,36 +80,24 @@ namespace Spine.Unity.Editor {
|
||||
// Here we save the skeletonGraphic.skeletonDataAsset asset path in order
|
||||
// to restore it later.
|
||||
var activeSkeletonGraphics = GameObject.FindObjectsOfType<SkeletonGraphic>();
|
||||
foreach (var sg in activeSkeletonGraphics) {
|
||||
var skeletonDataAsset = sg.skeletonDataAsset;
|
||||
foreach (var skeletonGraphic in activeSkeletonGraphics) {
|
||||
var skeletonDataAsset = skeletonGraphic.skeletonDataAsset;
|
||||
if (skeletonDataAsset != null) {
|
||||
var assetPath = AssetDatabase.GetAssetPath(skeletonDataAsset);
|
||||
var sgID = sg.GetInstanceID();
|
||||
var sgID = skeletonGraphic.GetInstanceID();
|
||||
savedSkeletonDataAssetAtSKeletonGraphicID[sgID] = assetPath;
|
||||
skeletonDataAssetsToReload.Add(skeletonDataAsset);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var sda in skeletonDataAssetsToReload) {
|
||||
sda.Clear();
|
||||
sda.GetSkeletonData(true);
|
||||
foreach (var skeletonDataAsset in skeletonDataAssetsToReload) {
|
||||
ReloadSkeletonDataAsset(skeletonDataAsset, false);
|
||||
}
|
||||
|
||||
foreach (var sr in activeSkeletonRenderers) {
|
||||
var meshRenderer = sr.GetComponent<MeshRenderer>();
|
||||
var sharedMaterials = meshRenderer.sharedMaterials;
|
||||
foreach (var m in sharedMaterials) {
|
||||
if (m == null) {
|
||||
sr.Initialize(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var sg in activeSkeletonGraphics) {
|
||||
if (sg.mainTexture == null)
|
||||
sg.Initialize(true);
|
||||
}
|
||||
foreach (var skeletonRenderer in activeSkeletonRenderers)
|
||||
skeletonRenderer.Initialize(true);
|
||||
foreach (var skeletonGraphic in activeSkeletonGraphics)
|
||||
skeletonGraphic.Initialize(true);
|
||||
}
|
||||
|
||||
public static void ReloadSceneSkeletonComponents (SkeletonDataAsset skeletonDataAsset) {
|
||||
@ -119,24 +107,35 @@ namespace Spine.Unity.Editor {
|
||||
if (EditorApplication.isPlayingOrWillChangePlaymode) return;
|
||||
|
||||
var activeSkeletonRenderers = GameObject.FindObjectsOfType<SkeletonRenderer>();
|
||||
foreach (var sr in activeSkeletonRenderers) {
|
||||
if (sr.isActiveAndEnabled && sr.skeletonDataAsset == skeletonDataAsset) sr.Initialize(true);
|
||||
foreach (var renderer in activeSkeletonRenderers) {
|
||||
if (renderer.isActiveAndEnabled && renderer.skeletonDataAsset == skeletonDataAsset) renderer.Initialize(true);
|
||||
}
|
||||
|
||||
var activeSkeletonGraphics = GameObject.FindObjectsOfType<SkeletonGraphic>();
|
||||
foreach (var sg in activeSkeletonGraphics) {
|
||||
if (sg.isActiveAndEnabled && sg.skeletonDataAsset == skeletonDataAsset) sg.Initialize(true);
|
||||
foreach (var graphic in activeSkeletonGraphics) {
|
||||
if (graphic.isActiveAndEnabled && graphic.skeletonDataAsset == skeletonDataAsset)
|
||||
graphic.Initialize(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearAnimationReferenceAssets (SkeletonDataAsset skeletonDataAsset) {
|
||||
ForEachAnimationReferenceAsset(skeletonDataAsset, (referenceAsset) => referenceAsset.Clear());
|
||||
}
|
||||
|
||||
public static void ReloadAnimationReferenceAssets (SkeletonDataAsset skeletonDataAsset) {
|
||||
ForEachAnimationReferenceAsset(skeletonDataAsset, (referenceAsset) => referenceAsset.Initialize());
|
||||
}
|
||||
|
||||
private static void ForEachAnimationReferenceAsset (SkeletonDataAsset skeletonDataAsset,
|
||||
System.Action<AnimationReferenceAsset> func) {
|
||||
|
||||
string[] guids = UnityEditor.AssetDatabase.FindAssets("t:AnimationReferenceAsset");
|
||||
foreach (string guid in guids) {
|
||||
string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (!string.IsNullOrEmpty(path)) {
|
||||
var referenceAsset = UnityEditor.AssetDatabase.LoadAssetAtPath<AnimationReferenceAsset>(path);
|
||||
if (referenceAsset.SkeletonDataAsset == skeletonDataAsset)
|
||||
referenceAsset.Initialize();
|
||||
func(referenceAsset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,62 +71,83 @@ namespace Spine.Unity.Editor {
|
||||
|
||||
#if HAS_ON_POSTPROCESS_PREFAB
|
||||
internal static void PreprocessSpinePrefabMeshes () {
|
||||
AssetDatabase.StartAssetEditing();
|
||||
prefabsToRestore.Clear();
|
||||
var prefabAssets = AssetDatabase.FindAssets("t:Prefab");
|
||||
foreach (var asset in prefabAssets) {
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(asset);
|
||||
GameObject prefabGameObject = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
|
||||
if (SpineEditorUtilities.CleanupSpinePrefabMesh(prefabGameObject)) {
|
||||
prefabsToRestore.Add(assetPath);
|
||||
BuildUtilities.IsInSkeletonAssetBuildPreProcessing = true;
|
||||
try {
|
||||
AssetDatabase.StartAssetEditing();
|
||||
prefabsToRestore.Clear();
|
||||
var prefabAssets = AssetDatabase.FindAssets("t:Prefab");
|
||||
foreach (var asset in prefabAssets) {
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(asset);
|
||||
GameObject prefabGameObject = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
|
||||
if (SpineEditorUtilities.CleanupSpinePrefabMesh(prefabGameObject)) {
|
||||
prefabsToRestore.Add(assetPath);
|
||||
}
|
||||
EditorUtility.UnloadUnusedAssetsImmediate();
|
||||
}
|
||||
EditorUtility.UnloadUnusedAssetsImmediate();
|
||||
AssetDatabase.StopAssetEditing();
|
||||
if (prefabAssets.Length > 0)
|
||||
AssetDatabase.SaveAssets();
|
||||
} finally {
|
||||
BuildUtilities.IsInSkeletonAssetBuildPreProcessing = false;
|
||||
}
|
||||
AssetDatabase.StopAssetEditing();
|
||||
if (prefabAssets.Length > 0)
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
||||
internal static void PostprocessSpinePrefabMeshes () {
|
||||
foreach (string assetPath in prefabsToRestore) {
|
||||
GameObject g = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
|
||||
SpineEditorUtilities.SetupSpinePrefabMesh(g, null);
|
||||
BuildUtilities.IsInSkeletonAssetBuildPostProcessing = true;
|
||||
try {
|
||||
foreach (string assetPath in prefabsToRestore) {
|
||||
GameObject g = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
|
||||
SpineEditorUtilities.SetupSpinePrefabMesh(g, null);
|
||||
}
|
||||
if (prefabsToRestore.Count > 0)
|
||||
AssetDatabase.SaveAssets();
|
||||
prefabsToRestore.Clear();
|
||||
|
||||
} finally {
|
||||
BuildUtilities.IsInSkeletonAssetBuildPostProcessing = false;
|
||||
}
|
||||
if (prefabsToRestore.Count > 0)
|
||||
AssetDatabase.SaveAssets();
|
||||
prefabsToRestore.Clear();
|
||||
}
|
||||
#endif
|
||||
internal static void PreprocessSpriteAtlases () {
|
||||
AssetDatabase.StartAssetEditing();
|
||||
spriteAtlasTexturesToRestore.Clear();
|
||||
var spriteAtlasAssets = AssetDatabase.FindAssets("t:SpineSpriteAtlasAsset");
|
||||
foreach (var asset in spriteAtlasAssets) {
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(asset);
|
||||
SpineSpriteAtlasAsset atlasAsset = AssetDatabase.LoadAssetAtPath<SpineSpriteAtlasAsset>(assetPath);
|
||||
if (atlasAsset && atlasAsset.materials.Length > 0) {
|
||||
spriteAtlasTexturesToRestore[assetPath] = AssetDatabase.GetAssetPath(atlasAsset.materials[0].mainTexture);
|
||||
atlasAsset.materials[0].mainTexture = null;
|
||||
BuildUtilities.IsInSpriteAtlasBuildPreProcessing = true;
|
||||
try {
|
||||
AssetDatabase.StartAssetEditing();
|
||||
spriteAtlasTexturesToRestore.Clear();
|
||||
var spriteAtlasAssets = AssetDatabase.FindAssets("t:SpineSpriteAtlasAsset");
|
||||
foreach (var asset in spriteAtlasAssets) {
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(asset);
|
||||
SpineSpriteAtlasAsset atlasAsset = AssetDatabase.LoadAssetAtPath<SpineSpriteAtlasAsset>(assetPath);
|
||||
if (atlasAsset && atlasAsset.materials.Length > 0) {
|
||||
spriteAtlasTexturesToRestore[assetPath] = AssetDatabase.GetAssetPath(atlasAsset.materials[0].mainTexture);
|
||||
atlasAsset.materials[0].mainTexture = null;
|
||||
}
|
||||
EditorUtility.UnloadUnusedAssetsImmediate();
|
||||
}
|
||||
EditorUtility.UnloadUnusedAssetsImmediate();
|
||||
AssetDatabase.StopAssetEditing();
|
||||
if (spriteAtlasAssets.Length > 0)
|
||||
AssetDatabase.SaveAssets();
|
||||
} finally {
|
||||
BuildUtilities.IsInSpriteAtlasBuildPreProcessing = false;
|
||||
}
|
||||
AssetDatabase.StopAssetEditing();
|
||||
if (spriteAtlasAssets.Length > 0)
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
||||
internal static void PostprocessSpriteAtlases () {
|
||||
foreach (var pair in spriteAtlasTexturesToRestore) {
|
||||
string assetPath = pair.Key;
|
||||
SpineSpriteAtlasAsset atlasAsset = AssetDatabase.LoadAssetAtPath<SpineSpriteAtlasAsset>(assetPath);
|
||||
if (atlasAsset && atlasAsset.materials.Length > 0) {
|
||||
Texture atlasTexture = AssetDatabase.LoadAssetAtPath<Texture>(pair.Value);
|
||||
atlasAsset.materials[0].mainTexture = atlasTexture;
|
||||
BuildUtilities.IsInSpriteAtlasBuildPostProcessing = true;
|
||||
try {
|
||||
foreach (var pair in spriteAtlasTexturesToRestore) {
|
||||
string assetPath = pair.Key;
|
||||
SpineSpriteAtlasAsset atlasAsset = AssetDatabase.LoadAssetAtPath<SpineSpriteAtlasAsset>(assetPath);
|
||||
if (atlasAsset && atlasAsset.materials.Length > 0) {
|
||||
Texture atlasTexture = AssetDatabase.LoadAssetAtPath<Texture>(pair.Value);
|
||||
atlasAsset.materials[0].mainTexture = atlasTexture;
|
||||
}
|
||||
}
|
||||
if (spriteAtlasTexturesToRestore.Count > 0)
|
||||
AssetDatabase.SaveAssets();
|
||||
spriteAtlasTexturesToRestore.Clear();
|
||||
} finally {
|
||||
BuildUtilities.IsInSpriteAtlasBuildPostProcessing = false;
|
||||
}
|
||||
if (spriteAtlasTexturesToRestore.Count > 0)
|
||||
AssetDatabase.SaveAssets();
|
||||
spriteAtlasTexturesToRestore.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -266,14 +266,23 @@ namespace Spine.Unity.Editor {
|
||||
ReinitializeComponent(component);
|
||||
}
|
||||
|
||||
public static void ReloadSkeletonDataAsset (SkeletonDataAsset skeletonDataAsset) {
|
||||
if (skeletonDataAsset != null) {
|
||||
public static void ClearSkeletonDataAsset (SkeletonDataAsset skeletonDataAsset) {
|
||||
skeletonDataAsset.Clear();
|
||||
DataReloadHandler.ClearAnimationReferenceAssets(skeletonDataAsset);
|
||||
}
|
||||
|
||||
public static void ReloadSkeletonDataAsset (SkeletonDataAsset skeletonDataAsset, bool clearAtlasAssets = true) {
|
||||
if (skeletonDataAsset == null)
|
||||
return;
|
||||
|
||||
if (clearAtlasAssets) {
|
||||
foreach (AtlasAssetBase aa in skeletonDataAsset.atlasAssets) {
|
||||
if (aa != null) aa.Clear();
|
||||
}
|
||||
skeletonDataAsset.Clear();
|
||||
}
|
||||
ClearSkeletonDataAsset(skeletonDataAsset);
|
||||
skeletonDataAsset.GetSkeletonData(true);
|
||||
DataReloadHandler.ReloadAnimationReferenceAssets(skeletonDataAsset);
|
||||
}
|
||||
|
||||
public static void ReinitializeComponent (SkeletonRenderer component) {
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b53e3e7c2824094b9259a24cd9a7e03
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -48,11 +48,16 @@ namespace Spine.Unity {
|
||||
if (animation == null)
|
||||
Initialize();
|
||||
#endif
|
||||
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Clears the cached animation corresponding to a loaded SkeletonData object.
|
||||
/// Use this to force a reload for the next time Animation is called.</summary>
|
||||
public void Clear () {
|
||||
animation = null;
|
||||
}
|
||||
|
||||
public void Initialize () {
|
||||
if (skeletonDataAsset == null) return;
|
||||
SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(AnimationReferenceAsset.QuietSkeletonData);
|
||||
|
||||
@ -238,6 +238,11 @@ namespace Spine.Unity {
|
||||
}
|
||||
|
||||
public void Load (AtlasPage page, string path) {
|
||||
#if UNITY_EDITOR
|
||||
if (BuildUtilities.IsInSkeletonAssetBuildPreProcessing ||
|
||||
BuildUtilities.IsInSkeletonAssetBuildPostProcessing)
|
||||
return;
|
||||
#endif
|
||||
String name = Path.GetFileNameWithoutExtension(path);
|
||||
Material material = null;
|
||||
foreach (Material other in atlasAsset.materials) {
|
||||
|
||||
@ -166,6 +166,10 @@ namespace Spine.Unity {
|
||||
public override void Initialize (bool overwrite, bool quiet = false) {
|
||||
if (valid && !overwrite)
|
||||
return;
|
||||
#if UNITY_EDITOR
|
||||
if (BuildUtilities.IsInSkeletonAssetBuildPreProcessing)
|
||||
return;
|
||||
#endif
|
||||
base.Initialize(overwrite, quiet);
|
||||
|
||||
if (!valid)
|
||||
|
||||
@ -102,7 +102,7 @@ namespace Spine.Unity {
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate () {
|
||||
// This handles Scene View preview.
|
||||
base.OnValidate ();
|
||||
base.OnValidate();
|
||||
if (this.IsValid) {
|
||||
if (skeletonDataAsset == null) {
|
||||
Clear();
|
||||
@ -360,8 +360,7 @@ namespace Spine.Unity {
|
||||
separatorSlots.Add(slot);
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
else
|
||||
{
|
||||
else {
|
||||
Debug.LogWarning(slotName + " is not a slot in " + skeletonDataAsset.skeletonJSON.name);
|
||||
}
|
||||
#endif
|
||||
@ -521,7 +520,10 @@ namespace Spine.Unity {
|
||||
|
||||
public void Initialize (bool overwrite) {
|
||||
if (this.IsValid && !overwrite) return;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (BuildUtilities.IsInSkeletonAssetBuildPreProcessing)
|
||||
return;
|
||||
#endif
|
||||
if (this.skeletonDataAsset == null) return;
|
||||
var skeletonData = this.skeletonDataAsset.GetSkeletonData(false);
|
||||
if (skeletonData == null) return;
|
||||
@ -839,7 +841,7 @@ namespace Spine.Unity {
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isEditor && !Application.isPlaying) {
|
||||
for (int i = separatorParts.Count-1; i >= 0; --i) {
|
||||
for (int i = separatorParts.Count - 1; i >= 0; --i) {
|
||||
if (separatorParts[i] == null) {
|
||||
separatorParts.RemoveAt(i);
|
||||
}
|
||||
|
||||
@ -72,7 +72,10 @@ namespace Spine.Unity {
|
||||
public override void Initialize (bool overwrite, bool quiet = false) {
|
||||
if (valid && !overwrite)
|
||||
return;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (BuildUtilities.IsInSkeletonAssetBuildPreProcessing)
|
||||
return;
|
||||
#endif
|
||||
base.Initialize(overwrite, quiet);
|
||||
|
||||
if (!valid)
|
||||
@ -104,8 +107,7 @@ namespace Spine.Unity {
|
||||
|
||||
if (Application.isPlaying) {
|
||||
translator.Apply(skeleton);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (translatorAnimator != null && translatorAnimator.isInitialized &&
|
||||
translatorAnimator.isActiveAndEnabled && translatorAnimator.runtimeAnimatorController != null) {
|
||||
// Note: Rebind is required to prevent warning "Animator is not playing an AnimatorController" with prefabs
|
||||
@ -535,7 +537,7 @@ namespace Spine.Unity {
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void GetLayerBlendModes() {
|
||||
void GetLayerBlendModes () {
|
||||
if (layerBlendModes.Length < animator.layerCount) {
|
||||
System.Array.Resize<MixBlend>(ref layerBlendModes, animator.layerCount);
|
||||
}
|
||||
|
||||
@ -367,7 +367,10 @@ namespace Spine.Unity {
|
||||
public virtual void Initialize (bool overwrite, bool quiet = false) {
|
||||
if (valid && !overwrite)
|
||||
return;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (BuildUtilities.IsInSkeletonAssetBuildPreProcessing)
|
||||
return;
|
||||
#endif
|
||||
// Clear
|
||||
{
|
||||
// Note: do not reset meshFilter.sharedMesh or meshRenderer.sharedMaterial to null,
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
/******************************************************************************
|
||||
* Spine Runtimes License Agreement
|
||||
* Last updated January 1, 2020. Replaces all prior versions.
|
||||
*
|
||||
* Copyright (c) 2013-2022, Esoteric Software LLC
|
||||
*
|
||||
* Integration of the Spine Runtimes into software or otherwise creating
|
||||
* derivative works of the Spine Runtimes is permitted under the terms and
|
||||
* conditions of Section 2 of the Spine Editor License Agreement:
|
||||
* http://esotericsoftware.com/spine-editor-license
|
||||
*
|
||||
* Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
* or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
* "Products"), provided that each user of the Products must obtain their own
|
||||
* Spine Editor license and redistribution of the Products in any form must
|
||||
* include this license and copyright notice.
|
||||
*
|
||||
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "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 EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
namespace Spine.Unity {
|
||||
|
||||
public static class BuildUtilities {
|
||||
public static bool IsInSkeletonAssetBuildPreProcessing = false;
|
||||
public static bool IsInSkeletonAssetBuildPostProcessing = false;
|
||||
public static bool IsInSpriteAtlasBuildPreProcessing = false;
|
||||
public static bool IsInSpriteAtlasBuildPostProcessing = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2f1169aaf0063f4da1c2b6033bbc13f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -58,6 +58,7 @@ You can add a `Spine Animation State Clip` to a `SkeletonAnimation Track` (or `S
|
||||
- *Event Threshold.* See [TrackEntry.EventThreshold](http://esotericsoftware.com/spine-api-reference#TrackEntry-eventThreshold).
|
||||
- *Attachment Threshold.* See [TrackEntry.AttachmentThreshold](http://esotericsoftware.com/spine-api-reference#TrackEntry-attachmentThreshold).
|
||||
- *Draw Order Threshold.* See [TrackEntry.DrawOrderThreshold](http://esotericsoftware.com/spine-api-reference#TrackEntry-drawOrderThreshold).
|
||||
- *Alpha.* See [TrackEntry.Alpha](http://esotericsoftware.com/spine-api-reference#TrackEntry-alpha).
|
||||
|
||||
*Ignored Parameters*
|
||||
- *Ease Out Duration, Blend Curves*. These parameters are ignored and have no effect.
|
||||
@ -111,5 +112,3 @@ This track type can be used to flip the skeleton of the target `SkeletonAnimatio
|
||||
|
||||
#### Known Issues
|
||||
- The Console potentially logs an incorrect and harmless error `DrivenPropertyManager has failed to register property "m_Script" of object "Spine GameObject (spineboy-pro)" with driver "" because the property doesn't exist.`. This is a known issue on Unity's end. See more here: https://forum.unity.com/threads/default-playables-text-switcher-track-error.502903/
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 50 KiB |
@ -36,7 +36,7 @@ using UnityEngine;
|
||||
public class SpineAnimationStateDrawer : PropertyDrawer {
|
||||
|
||||
public override float GetPropertyHeight (SerializedProperty property, GUIContent label) {
|
||||
const int fieldCount = 15;
|
||||
const int fieldCount = 16;
|
||||
return fieldCount * EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ public class SpineAnimationStateDrawer : PropertyDrawer {
|
||||
SerializedProperty useBlendDurationProp = property.FindPropertyRelative("useBlendDuration");
|
||||
SerializedProperty mixDurationProp = property.FindPropertyRelative("mixDuration");
|
||||
SerializedProperty holdPreviousProp = property.FindPropertyRelative("holdPrevious");
|
||||
SerializedProperty alphaProp = property.FindPropertyRelative("alpha");
|
||||
SerializedProperty dontPauseWithDirectorProp = property.FindPropertyRelative("dontPauseWithDirector");
|
||||
SerializedProperty dontEndWithClip = property.FindPropertyRelative("dontEndWithClip");
|
||||
SerializedProperty endMixOutDuration = property.FindPropertyRelative("endMixOutDuration");
|
||||
@ -129,5 +130,8 @@ public class SpineAnimationStateDrawer : PropertyDrawer {
|
||||
|
||||
singleFieldRect.y += lineHeightWithSpacing;
|
||||
EditorGUI.PropertyField(singleFieldRect, drawOrderProp);
|
||||
|
||||
singleFieldRect.y += lineHeightWithSpacing;
|
||||
EditorGUI.PropertyField(singleFieldRect, alphaProp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ using UnityEngine;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
[CustomTimelineEditor(typeof(SpineAnimationStateGraphicTrack))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SpineAnimationStateGraphicTrackInspector : TrackEditor {
|
||||
@ -46,4 +46,22 @@ namespace Spine.Unity.Editor {
|
||||
return options;
|
||||
}
|
||||
}
|
||||
#else
|
||||
[CustomEditor(typeof(SpineAnimationStateGraphicTrack))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SpineAnimationStateGraphicTrackInspector : UnityEditor.Editor {
|
||||
|
||||
protected SerializedProperty trackIndexProperty = null;
|
||||
|
||||
public void OnEnable () {
|
||||
trackIndexProperty = serializedObject.FindProperty("trackIndex");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
serializedObject.Update();
|
||||
EditorGUILayout.PropertyField(trackIndexProperty);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@ using UnityEngine;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
[CustomTimelineEditor(typeof(SpineAnimationStateTrack))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SpineAnimationStateTrackInspector : TrackEditor {
|
||||
@ -45,4 +46,22 @@ namespace Spine.Unity.Editor {
|
||||
return options;
|
||||
}
|
||||
}
|
||||
#else
|
||||
[CustomEditor(typeof(SpineAnimationStateTrack))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SpineAnimationStateTrackInspector : UnityEditor.Editor {
|
||||
|
||||
protected SerializedProperty trackIndexProperty = null;
|
||||
|
||||
public void OnEnable () {
|
||||
trackIndexProperty = serializedObject.FindProperty("trackIndex");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI () {
|
||||
serializedObject.Update();
|
||||
EditorGUILayout.PropertyField(trackIndexProperty);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@ using UnityEngine;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace Spine.Unity.Editor {
|
||||
#if UNITY_2019_1_OR_NEWER
|
||||
[CustomTimelineEditor(typeof(SpineSkeletonFlipTrack))]
|
||||
[CanEditMultipleObjects]
|
||||
public class SpineSkeletonFlipTrackInspector : TrackEditor {
|
||||
@ -45,4 +46,5 @@ namespace Spine.Unity.Editor {
|
||||
return options;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -69,6 +69,9 @@ namespace Spine.Unity.Playables {
|
||||
|
||||
[Range(0, 1f)]
|
||||
public float drawOrderThreshold = 0.5f;
|
||||
|
||||
[Range(0, 1f)]
|
||||
public float alpha = 1.0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -191,6 +191,7 @@ namespace Spine.Unity.Playables {
|
||||
trackEntry.TimeScale = (float)clipPlayable.GetSpeed();
|
||||
trackEntry.AttachmentThreshold = clipData.attachmentThreshold;
|
||||
trackEntry.HoldPrevious = clipData.holdPrevious;
|
||||
trackEntry.Alpha = clipData.alpha;
|
||||
|
||||
if (clipData.customDuration)
|
||||
trackEntry.MixDuration = customMixDuration;
|
||||
@ -286,6 +287,7 @@ namespace Spine.Unity.Playables {
|
||||
if (toAnimation != null) {
|
||||
toEntry = dummyAnimationState.SetAnimation(0, toAnimation, clipData.loop);
|
||||
toEntry.HoldPrevious = clipData.holdPrevious;
|
||||
toEntry.Alpha = clipData.alpha;
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,7 +303,7 @@ namespace Spine.Unity.Playables {
|
||||
dummyAnimationState.Apply(skeleton);
|
||||
} else {
|
||||
if (toAnimation != null)
|
||||
toAnimation.Apply(skeleton, 0, toClipTime, clipData.loop, null, 1f, MixBlend.Setup, MixDirection.In);
|
||||
toAnimation.Apply(skeleton, 0, toClipTime, clipData.loop, null, clipData.alpha, MixBlend.Setup, MixDirection.In);
|
||||
}
|
||||
|
||||
if (skeletonAnimation) {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "com.esotericsoftware.spine.timeline",
|
||||
"displayName": "Spine Timeline Extensions",
|
||||
"description": "This plugin provides integration of spine-unity for the Unity Timeline.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime (via the spine-unity unitypackage), version 4.0.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)",
|
||||
"version": "4.0.9",
|
||||
"version": "4.0.10",
|
||||
"unity": "2018.3",
|
||||
"author": {
|
||||
"name": "Esoteric Software",
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "com.esotericsoftware.spine.timeline",
|
||||
"displayName": "Spine Timeline Extensions",
|
||||
"description": "This plugin provides integration of spine-unity for the Unity Timeline.\n\nPrerequisites:\nIt requires a working installation of the spine-unity and spine-csharp runtimes as UPM packages (not as spine-unity unitypackage), version 4.0.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)",
|
||||
"version": "4.0.9",
|
||||
"version": "4.0.10",
|
||||
"unity": "2018.3",
|
||||
"author": {
|
||||
"name": "Esoteric Software",
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
#ifndef SKELETONLIT_UNLIT_PASS_INCLUDED
|
||||
#define SKELETONLIT_UNLIT_PASS_INCLUDED
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
float4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
TEXTURE2D(_MainTex);
|
||||
SAMPLER(sampler_MainTex);
|
||||
float4 _MainTex_ST;
|
||||
|
||||
Varyings UnlitVertex(Attributes attributes)
|
||||
{
|
||||
Varyings o = (Varyings)0;
|
||||
|
||||
o.positionCS = TransformObjectToHClip(attributes.positionOS);
|
||||
o.uv = TRANSFORM_TEX(attributes.uv, _MainTex);
|
||||
o.uv = attributes.uv;
|
||||
o.color = attributes.color;
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 UnlitFragment(Varyings i) : SV_Target
|
||||
{
|
||||
half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
|
||||
half4 main;
|
||||
#if defined(_STRAIGHT_ALPHA_INPUT)
|
||||
main.rgb = tex.rgb * i.color.rgb * tex.a;
|
||||
#else
|
||||
main.rgb = tex.rgb * i.color.rgb;
|
||||
#endif
|
||||
main.a = tex.a * i.color.a;
|
||||
|
||||
return main;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 580dd7e812fc63c4a9330abe519946de
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
preprocessorOverride: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -193,52 +193,12 @@
|
||||
Blend One OneMinusSrcAlpha
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
|
||||
#pragma prefer_hlslcc gles
|
||||
#pragma vertex UnlitVertex
|
||||
#pragma fragment UnlitFragment
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
float4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
TEXTURE2D(_MainTex);
|
||||
SAMPLER(sampler_MainTex);
|
||||
float4 _MainTex_ST;
|
||||
|
||||
Varyings UnlitVertex(Attributes attributes)
|
||||
{
|
||||
Varyings o = (Varyings)0;
|
||||
|
||||
o.positionCS = TransformObjectToHClip(attributes.positionOS);
|
||||
o.uv = TRANSFORM_TEX(attributes.uv, _MainTex);
|
||||
o.uv = attributes.uv;
|
||||
o.color = attributes.color;
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 UnlitFragment(Varyings i) : SV_Target
|
||||
{
|
||||
half4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
|
||||
half4 main;
|
||||
#if defined(_STRAIGHT_ALPHA_INPUT)
|
||||
main.rgb = tex.rgb * i.color.rgb * tex.a;
|
||||
#else
|
||||
main.rgb = tex.rgb * i.color.rgb;
|
||||
#endif
|
||||
main.a = tex.a * i.color.a;
|
||||
|
||||
return main;
|
||||
}
|
||||
#include "Include/Spine-SkeletonLit-UnlitPass-URP-2D.hlsl"
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,7 +147,28 @@ Shader "Universal Render Pipeline/2D/Spine/Sprite"
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
UsePass "Universal Render Pipeline/2D/Spine/Skeleton Lit/UNLIT"
|
||||
Pass
|
||||
{
|
||||
Name "Unlit"
|
||||
Tags { "LightMode" = "UniversalForward" "Queue" = "Transparent" "RenderType" = "Transparent"}
|
||||
|
||||
ZWrite Off
|
||||
Cull Off
|
||||
Blend One OneMinusSrcAlpha
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma shader_feature _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAPREMULTIPLY_VERTEX_ONLY _ADDITIVEBLEND _ADDITIVEBLEND_SOFT _MULTIPLYBLEND _MULTIPLYBLEND_X2
|
||||
#if defined(_ALPHAPREMULTIPLY_VERTEX_ONLY) || defined(_ALPHABLEND_ON)
|
||||
#define _STRAIGHT_ALPHA_INPUT
|
||||
#endif
|
||||
|
||||
#pragma prefer_hlslcc gles
|
||||
#pragma vertex UnlitVertex
|
||||
#pragma fragment UnlitFragment
|
||||
|
||||
#include "Include/Spine-SkeletonLit-UnlitPass-URP-2D.hlsl"
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
|
||||
FallBack "Universal Render Pipeline/2D/Spine/Skeleton Lit"
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
// Adapt this path accordingly if you have unpacked the Spine directory to another location.
|
||||
#include "Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/ShaderShared.cginc"
|
||||
//#include "Packages/com.esotericsoftware.spine.spine-unity/Runtime/spine-unity/Shaders/Sprite/CGIncludes/ShaderShared.cginc"
|
||||
//#include "Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/ShaderShared.cginc"
|
||||
#include "Packages/com.esotericsoftware.spine.spine-unity/Runtime/spine-unity/Shaders/Sprite/CGIncludes/ShaderShared.cginc"
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
// Adapt this path accordingly if you have unpacked the Spine directory to another location.
|
||||
#include "Assets/Spine/Runtime/spine-unity/Shaders/CGIncludes/Spine-Common.cginc"
|
||||
//#include "Packages/com.esotericsoftware.spine.spine-unity/Runtime/spine-unity/Shaders/CGIncludes/Spine-Common.cginc"
|
||||
//#include "Assets/Spine/Runtime/spine-unity/Shaders/CGIncludes/Spine-Common.cginc"
|
||||
#include "Packages/com.esotericsoftware.spine.spine-unity/Runtime/spine-unity/Shaders/CGIncludes/Spine-Common.cginc"
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
// Adapt this path accordingly if you have unpacked the Spine directory to another location.
|
||||
#include "Assets/Spine/Runtime/spine-unity/Shaders/CGIncludes/Spine-Outline-Common.cginc"
|
||||
//#include "Packages/com.esotericsoftware.spine.spine-unity/Runtime/spine-unity/Shaders/CGIncludes/Spine-Outline-Common.cginc"
|
||||
//#include "Assets/Spine/Runtime/spine-unity/Shaders/CGIncludes/Spine-Outline-Common.cginc"
|
||||
#include "Packages/com.esotericsoftware.spine.spine-unity/Runtime/spine-unity/Shaders/CGIncludes/Spine-Outline-Common.cginc"
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
// Adapt this path accordingly if you have unpacked the Spine directory to another location.
|
||||
#include "Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/SpriteLighting.cginc"
|
||||
//#include "Packages/com.esotericsoftware.spine.spine-unity/Runtime/spine-unity/Shaders/Sprite/CGIncludes/SpriteLighting.cginc"
|
||||
//#include "Assets/Spine/Runtime/spine-unity/Shaders/Sprite/CGIncludes/SpriteLighting.cginc"
|
||||
#include "Packages/com.esotericsoftware.spine.spine-unity/Runtime/spine-unity/Shaders/Sprite/CGIncludes/SpriteLighting.cginc"
|
||||
|
||||
@ -113,7 +113,7 @@ Shader "Universal Render Pipeline/Spine/Sprite"
|
||||
#pragma multi_compile _ DIRLIGHTMAP_COMBINED
|
||||
#pragma multi_compile _ LIGHTMAP_ON
|
||||
|
||||
//--------------------------------------
|
||||
//--------------------------------------
|
||||
// GPU Instancing
|
||||
#pragma multi_compile_instancing
|
||||
|
||||
@ -202,6 +202,36 @@ Shader "Universal Render Pipeline/Spine/Sprite"
|
||||
#include "Include/Spine-Sprite-DepthOnlyPass-URP.hlsl"
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Unlit"
|
||||
Tags { "LightMode" = "UniversalForward" "Queue" = "Transparent" "RenderType" = "Transparent"}
|
||||
|
||||
ZWrite Off
|
||||
Cull Off
|
||||
Blend One OneMinusSrcAlpha
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma shader_feature _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ALPHAPREMULTIPLY_VERTEX_ONLY _ADDITIVEBLEND _ADDITIVEBLEND_SOFT _MULTIPLYBLEND _MULTIPLYBLEND_X2
|
||||
#if defined(_ALPHAPREMULTIPLY_VERTEX_ONLY) || defined(_ALPHABLEND_ON)
|
||||
#define _STRAIGHT_ALPHA_INPUT
|
||||
#endif
|
||||
|
||||
#pragma prefer_hlslcc gles
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
#undef LIGHTMAP_ON
|
||||
|
||||
#define USE_URP
|
||||
#define fixed4 half4
|
||||
#define fixed3 half3
|
||||
#define fixed half
|
||||
#include "Include/Spine-Input-URP.hlsl"
|
||||
#include "Include/Spine-Skeleton-ForwardPass-URP.hlsl"
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
|
||||
FallBack "Hidden/InternalErrorShader"
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "com.esotericsoftware.spine.urp-shaders",
|
||||
"displayName": "Spine Universal RP Shaders",
|
||||
"description": "This plugin provides universal render pipeline (URP) shaders for the spine-unity runtime.\n\nPrerequisites:\nIt requires a working installation of the spine-unity runtime, version 4.0.\n(See http://esotericsoftware.com/git/spine-runtimes/spine-unity)",
|
||||
"version": "4.0.6",
|
||||
"version": "4.0.7",
|
||||
"unity": "2019.3",
|
||||
"author": {
|
||||
"name": "Esoteric Software",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user