diff --git a/CHANGELOG.md b/CHANGELOG.md index 658e6a3cf..0405c927c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -149,6 +149,7 @@ * Added outline shader parameter `Advanced - Opaque Alpha` which can be used to exclude problematic semi-transparent areas, which may receive an undesired large outline color overlay otherwise. * Added Spine Preferences setting `Prefabs` - `Optimize Preview Meshes`. When enabled, Spine prefab preview meshes will be removed in a pre-build step to reduce build size. This increases build time as all prefabs in the project will be processed. Defaults to false to not slow down builds substantially every time. * Added Spine Preferences setting `Reload SkeletonData after Play`. When enabled, the shared `SkeletonData` of all skeletons in the active scene is reloaded (from the `.json` or `.skel.bytes` file) after exiting play-mode. You can disable this setting to avoid the reloading delay if you can ensure that there are no (accidental) modifications to the shared `SkeletonData` during play-mode (otherwise it would carry over its effect into subsequent plays). Defaults to `true` (the safe setting), which maintains existing behaviour. + * Added `SkeletonAnimationMulti` sample component methods `SetActiveSkeleton(int index)` and getter property `SkeletonAnimations` to more easily apply changes at all SkeletonAnimation instances instead of only the active one. * **Breaking changes** * Made `SkeletonGraphic.unscaledTime` parameter protected, use the new property `UnscaledTime` instead. diff --git a/spine-c/spine-c/src/spine/Animation.c b/spine-c/spine-c/src/spine/Animation.c index 9c70f0962..55dd1ddab 100644 --- a/spine-c/spine-c/src/spine/Animation.c +++ b/spine-c/spine-c/src/spine/Animation.c @@ -2016,7 +2016,8 @@ void _spSequenceTimeline_apply(spTimeline *timeline, spSkeleton *skeleton, float slotAttachment = slot->attachment; if (slotAttachment != self->attachment) { - switch (slot->attachment->type) { + if (slotAttachment == NULL) return; + switch (slotAttachment->type) { case SP_ATTACHMENT_BOUNDING_BOX: case SP_ATTACHMENT_CLIPPING: case SP_ATTACHMENT_MESH: diff --git a/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp b/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp index 652def340..c96305db3 100644 --- a/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/SequenceTimeline.cpp @@ -72,7 +72,7 @@ void SequenceTimeline::apply(Skeleton &skeleton, float lastTime, float time, Vec if (!slot->getBone().isActive()) return; Attachment *slotAttachment = slot->getAttachment(); if (slotAttachment != _attachment) { - if (!slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti) || ((VertexAttachment *) slotAttachment)->getTimelineAttachment() != _attachment) return; + if (slotAttachment == NULL || !slotAttachment->getRTTI().instanceOf(VertexAttachment::rtti) || ((VertexAttachment *) slotAttachment)->getTimelineAttachment() != _attachment) return; } Vector &frames = this->_frames; diff --git a/spine-sfml/cpp/CMakeLists.txt b/spine-sfml/cpp/CMakeLists.txt index 903d0f7d4..a56e2d912 100644 --- a/spine-sfml/cpp/CMakeLists.txt +++ b/spine-sfml/cpp/CMakeLists.txt @@ -62,6 +62,7 @@ install(FILES ${INCLUDES} DESTINATION dist/include) # Define spine-sfml example executable add_executable(spine-sfml-cpp-example example/main.cpp) +add_executable(spine-sfml-cpp-test example/test.cpp) # Link in SFML libraries and OS dependencies like OpenGL if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") @@ -70,8 +71,10 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") find_library(SFML_WINDOW sfml-window PATHS ${SFML_DIR}/Frameworks) find_library(SFML_GRAPHICS sfml-graphics PATHS ${SFML_DIR}/Frameworks) target_link_libraries(spine-sfml-cpp-example ${SFML} ${SFML_SYSTEM} ${SFML_WINDOW} ${SFML_GRAPHICS}) + target_link_libraries(spine-sfml-cpp-test ${SFML} ${SFML_SYSTEM} ${SFML_WINDOW} ${SFML_GRAPHICS}) elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") target_link_libraries(spine-sfml-cpp-example sfml-graphics sfml-window sfml-system) + target_link_libraries(spine-sfml-cpp-test sfml-graphics sfml-window sfml-system) else() set(SFML_LIBS ${SFML_DIR}/lib) target_link_libraries(spine-sfml-cpp-example ${SFML_LIBS}/sfml-main-d.lib) @@ -83,6 +86,15 @@ else() target_link_libraries(spine-sfml-cpp-example opengl32) target_link_libraries(spine-sfml-cpp-example gdi32) target_link_libraries(spine-sfml-cpp-example winmm) + target_link_libraries(spine-sfml-cpp-test ${SFML_LIBS}/sfml-main-d.lib) + target_link_libraries(spine-sfml-cpp-test ${SFML_LIBS}/sfml-graphics-s-d.lib) + target_link_libraries(spine-sfml-cpp-test ${SFML_LIBS}/sfml-window-s-d.lib) + target_link_libraries(spine-sfml-cpp-test ${SFML_LIBS}/sfml-system-s-d.lib) + target_link_libraries(spine-sfml-cpp-test ${SFML_LIBS}/freetype.lib) + target_link_libraries(spine-sfml-cpp-test ${SFML_LIBS}/jpeg.lib) + target_link_libraries(spine-sfml-cpp-test opengl32) + target_link_libraries(spine-sfml-cpp-test gdi32) + target_link_libraries(spine-sfml-cpp-test winmm) add_definitions(-DSFML_STATIC) endif() @@ -90,6 +102,12 @@ endif() add_custom_command(TARGET spine-sfml-cpp-example PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/data $/data) +add_custom_command(TARGET spine-sfml-cpp-test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/data $/data) target_link_libraries(spine-sfml-cpp-example spine-cpp) target_link_libraries(spine-sfml-cpp-example spine-sfml-cpp) + +target_link_libraries(spine-sfml-cpp-test spine-cpp) +target_link_libraries(spine-sfml-cpp-test spine-sfml-cpp) diff --git a/spine-sfml/cpp/example/test.cpp b/spine-sfml/cpp/example/test.cpp new file mode 100644 index 000000000..e228d7159 --- /dev/null +++ b/spine-sfml/cpp/example/test.cpp @@ -0,0 +1,78 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated September 24, 2021. Replaces all prior versions. + * + * Copyright (c) 2013-2021, 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. + *****************************************************************************/ + +#include +#include +#include +#include + +using namespace std; +using namespace spine; + +DebugExtension dbgExtension(SpineExtension::getInstance()); + +void test() { + SFMLTextureLoader textureLoader; + Atlas atlas("data/bomb.atlas", &textureLoader); + SkeletonBinary loader(&atlas); + SkeletonData *skeletonData = loader.readSkeletonDataFile("data/bomb.skel"); + + SkeletonDrawable drawable(skeletonData); + drawable.setUsePremultipliedAlpha(true); + drawable.skeleton->setPosition(320, 590); + drawable.state->setAnimation(0, "expl", false); + drawable.skeleton->setSkin("mdl"); + + sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - Test"); + window.setFramerateLimit(60); + sf::Event event; + sf::Clock deltaClock; + while (window.isOpen()) { + while (window.pollEvent(event)) + if (event.type == sf::Event::Closed) window.close(); + + float delta = deltaClock.getElapsedTime().asSeconds(); + deltaClock.restart(); + + drawable.update(delta); + + window.clear(); + window.draw(drawable); + window.display(); + } + + delete skeletonData; +} + +int main() { + SpineExtension::setInstance(&dbgExtension); + test(); + dbgExtension.reportLeaks(); + return 0; +} \ No newline at end of file diff --git a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonAnimationMulti/SkeletonAnimationMulti.cs b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonAnimationMulti/SkeletonAnimationMulti.cs index 509230bb4..f207c3074 100644 --- a/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonAnimationMulti/SkeletonAnimationMulti.cs +++ b/spine-unity/Assets/Spine Examples/Scripts/Sample Components/SkeletonAnimationMulti/SkeletonAnimationMulti.cs @@ -56,17 +56,24 @@ namespace Spine.Unity { SkeletonAnimation currentSkeletonAnimation; void Clear () { - foreach (var s in skeletonAnimations) - Destroy(s.gameObject); + foreach (SkeletonAnimation skeletonAnimation in skeletonAnimations) + Destroy(skeletonAnimation.gameObject); skeletonAnimations.Clear(); animationNameTable.Clear(); animationSkeletonTable.Clear(); } + void SetActiveSkeleton (int index) { + if (index < 0 || index >= skeletonAnimations.Count) + SetActiveSkeleton(null); + else + SetActiveSkeleton(skeletonAnimations[index]); + } + void SetActiveSkeleton (SkeletonAnimation skeletonAnimation) { - foreach (var sa in skeletonAnimations) - sa.gameObject.SetActive(sa == skeletonAnimation); + foreach (SkeletonAnimation iter in skeletonAnimations) + iter.gameObject.SetActive(iter == skeletonAnimation); currentSkeletonAnimation = skeletonAnimation; } @@ -81,34 +88,35 @@ namespace Spine.Unity { public Dictionary AnimationSkeletonTable { get { return this.animationSkeletonTable; } } public Dictionary AnimationNameTable { get { return this.animationNameTable; } } public SkeletonAnimation CurrentSkeletonAnimation { get { return this.currentSkeletonAnimation; } } + public List SkeletonAnimations { get { return skeletonAnimations; } } public void Initialize (bool overwrite) { if (skeletonAnimations.Count != 0 && !overwrite) return; Clear(); - var settings = this.meshGeneratorSettings; + MeshGenerator.Settings settings = this.meshGeneratorSettings; Transform thisTransform = this.transform; - foreach (var sda in skeletonDataAssets) { - var sa = SkeletonAnimation.NewSkeletonAnimationGameObject(sda); - sa.transform.SetParent(thisTransform, false); + foreach (SkeletonDataAsset dataAsset in skeletonDataAssets) { + SkeletonAnimation newSkeletonAnimation = SkeletonAnimation.NewSkeletonAnimationGameObject(dataAsset); + newSkeletonAnimation.transform.SetParent(thisTransform, false); - sa.SetMeshSettings(settings); - sa.initialFlipX = this.initialFlipX; - sa.initialFlipY = this.initialFlipY; - var skeleton = sa.skeleton; + newSkeletonAnimation.SetMeshSettings(settings); + newSkeletonAnimation.initialFlipX = this.initialFlipX; + newSkeletonAnimation.initialFlipY = this.initialFlipY; + Skeleton skeleton = newSkeletonAnimation.skeleton; skeleton.ScaleX = this.initialFlipX ? -1 : 1; skeleton.ScaleY = this.initialFlipY ? -1 : 1; - sa.Initialize(false); - skeletonAnimations.Add(sa); + newSkeletonAnimation.Initialize(false); + skeletonAnimations.Add(newSkeletonAnimation); } // Build cache - var animationNameTable = this.animationNameTable; - var animationSkeletonTable = this.animationSkeletonTable; - foreach (var skeletonAnimation in skeletonAnimations) { - foreach (var animationObject in skeletonAnimation.Skeleton.Data.Animations) { + Dictionary animationNameTable = this.animationNameTable; + Dictionary animationSkeletonTable = this.animationSkeletonTable; + foreach (SkeletonAnimation skeletonAnimation in skeletonAnimations) { + foreach (Animation animationObject in skeletonAnimation.Skeleton.Data.Animations) { animationNameTable[animationObject.Name] = animationObject; animationSkeletonTable[animationObject] = skeletonAnimation; } @@ -119,7 +127,6 @@ namespace Spine.Unity { } public Animation FindAnimation (string animationName) { - // Analysis disable once LocalVariableHidesMember Animation animation; animationNameTable.TryGetValue(animationName, out animation); return animation; @@ -138,11 +145,10 @@ namespace Spine.Unity { if (skeletonAnimation != null) { SetActiveSkeleton(skeletonAnimation); skeletonAnimation.skeleton.SetToSetupPose(); - var trackEntry = skeletonAnimation.state.SetAnimation(MainTrackIndex, animation, loop); + TrackEntry trackEntry = skeletonAnimation.state.SetAnimation(MainTrackIndex, animation, loop); skeletonAnimation.Update(0); return trackEntry; } - return null; }