mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[flutter] Reduce allocations by using a block/bump allocator for rendering commands.
This commit is contained in:
parent
40df75abf4
commit
28312004e3
@ -6,13 +6,14 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:esotericsoftware_spine_flutter/spine_flutter.dart';
|
import 'package:esotericsoftware_spine_flutter/spine_flutter.dart';
|
||||||
|
|
||||||
class SpineComponent extends PositionComponent {
|
class SpineComponent extends PositionComponent {
|
||||||
|
static final Finalizer<SpineComponent> _finalizer = Finalizer((spineComponent) => spineComponent.dispose());
|
||||||
final BoundsProvider _boundsProvider;
|
final BoundsProvider _boundsProvider;
|
||||||
final SkeletonDrawable _drawable;
|
final SkeletonDrawable _drawable;
|
||||||
late final Bounds _bounds;
|
late final Bounds _bounds;
|
||||||
final bool _ownsDrawable;
|
final bool _ownsDrawable;
|
||||||
|
|
||||||
SpineComponent(this._drawable, {
|
SpineComponent(this._drawable, {
|
||||||
bool ownsDrawable = false,
|
bool ownsDrawable = true,
|
||||||
BoundsProvider boundsProvider = const SetupPoseBounds(),
|
BoundsProvider boundsProvider = const SetupPoseBounds(),
|
||||||
super.position,
|
super.position,
|
||||||
super.scale,
|
super.scale,
|
||||||
@ -26,6 +27,7 @@ class SpineComponent extends PositionComponent {
|
|||||||
_drawable.update(0);
|
_drawable.update(0);
|
||||||
_bounds = _boundsProvider.computeBounds(_drawable);
|
_bounds = _boundsProvider.computeBounds(_drawable);
|
||||||
size = Vector2(_bounds.width, _bounds.height);
|
size = Vector2(_bounds.width, _bounds.height);
|
||||||
|
_finalizer.attach(this, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<SpineComponent> fromAssets(String atlasFile, String skeletonFile, {
|
static Future<SpineComponent> fromAssets(String atlasFile, String skeletonFile, {
|
||||||
@ -50,9 +52,11 @@ class SpineComponent extends PositionComponent {
|
|||||||
priority: priority);
|
priority: priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
void dispose() {
|
||||||
void onRemove() {
|
if (_ownsDrawable) {
|
||||||
if (_ownsDrawable) _drawable.dispose();
|
_drawable.dispose();
|
||||||
|
}
|
||||||
|
_finalizer.detach(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -92,12 +96,18 @@ class SimpleFlameExample extends FlameGame {
|
|||||||
spineboy.animationState.setAnimationByName(0, "walk", true);
|
spineboy.animationState.setAnimationByName(0, "walk", true);
|
||||||
await add(spineboy);
|
await add(spineboy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onDetach() {
|
||||||
|
// Dispose the native resources that have been loaded for spineboy.
|
||||||
|
spineboy.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PreloadAndShareSpineDataExample extends FlameGame {
|
class PreloadAndShareSpineDataExample extends FlameGame {
|
||||||
late final SkeletonData cachedSkeletonData;
|
late final SkeletonData cachedSkeletonData;
|
||||||
late final Atlas cachedAtlas;
|
late final Atlas cachedAtlas;
|
||||||
late final List<SpineComponent> spineboys;
|
late final List<SpineComponent> spineboys = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onLoad() async {
|
Future<void> onLoad() async {
|
||||||
@ -109,7 +119,7 @@ class PreloadAndShareSpineDataExample extends FlameGame {
|
|||||||
// gets their own SkeletonDrawable copy derived from the cached data. The
|
// gets their own SkeletonDrawable copy derived from the cached data. The
|
||||||
// SkeletonDrawable copies do not own the underlying skeleton data and atlas.
|
// SkeletonDrawable copies do not own the underlying skeleton data and atlas.
|
||||||
final rng = Random();
|
final rng = Random();
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 50; i++) {
|
||||||
final drawable = SkeletonDrawable(cachedAtlas, cachedSkeletonData, false);
|
final drawable = SkeletonDrawable(cachedAtlas, cachedSkeletonData, false);
|
||||||
final scale = 0.1 + rng.nextDouble() * 0.2;
|
final scale = 0.1 + rng.nextDouble() * 0.2;
|
||||||
final position = Vector2(rng.nextDouble() * size.x, rng.nextDouble() * size.y);
|
final position = Vector2(rng.nextDouble() * size.x, rng.nextDouble() * size.y);
|
||||||
@ -119,15 +129,19 @@ class PreloadAndShareSpineDataExample extends FlameGame {
|
|||||||
position: position
|
position: position
|
||||||
);
|
);
|
||||||
spineboy.animationState.setAnimationByName(0, "walk", true);
|
spineboy.animationState.setAnimationByName(0, "walk", true);
|
||||||
|
spineboys.add(spineboy);
|
||||||
await add(spineboy);
|
await add(spineboy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onRemove() {
|
void onDetach() {
|
||||||
// Dispose the pre-loaded atlas and skeleton data when the game/scene is removed
|
// Dispose the pre-loaded atlas and skeleton data when the game/scene is removed
|
||||||
cachedAtlas.dispose();
|
cachedAtlas.dispose();
|
||||||
cachedSkeletonData.dispose();
|
cachedSkeletonData.dispose();
|
||||||
|
for (final spineboy in spineboys) {
|
||||||
|
spineboy.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -126,7 +126,7 @@ class ExampleSelector extends StatelessWidget {
|
|||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await initSpineFlutter();
|
await initSpineFlutter(enableMemoryDebugging: false);
|
||||||
runApp(const MaterialApp(
|
runApp(const MaterialApp(
|
||||||
title: "Spine Examples",
|
title: "Spine Examples",
|
||||||
home: ExampleSelector()
|
home: ExampleSelector()
|
||||||
|
|||||||
@ -18,10 +18,11 @@ import 'package:flutter/foundation.dart' show kIsWeb;
|
|||||||
late SpineFlutterBindings _bindings;
|
late SpineFlutterBindings _bindings;
|
||||||
late Allocator _allocator;
|
late Allocator _allocator;
|
||||||
|
|
||||||
Future<void> initSpineFlutter() async {
|
Future<void> initSpineFlutter({bool enableMemoryDebugging = false}) async {
|
||||||
final ffi = await initSpineFlutterFFI();
|
final ffi = await initSpineFlutterFFI();
|
||||||
_bindings = SpineFlutterBindings(ffi.dylib);
|
_bindings = SpineFlutterBindings(ffi.dylib);
|
||||||
_allocator = ffi.allocator;
|
_allocator = ffi.allocator;
|
||||||
|
if (enableMemoryDebugging) _bindings.spine_enable_debug_extension(-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,6 +44,20 @@ class SpineFlutterBindings {
|
|||||||
late final _spine_minor_version =
|
late final _spine_minor_version =
|
||||||
_spine_minor_versionPtr.asFunction<int Function()>();
|
_spine_minor_versionPtr.asFunction<int Function()>();
|
||||||
|
|
||||||
|
void spine_enable_debug_extension(
|
||||||
|
int enable,
|
||||||
|
) {
|
||||||
|
return _spine_enable_debug_extension(
|
||||||
|
enable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
late final _spine_enable_debug_extensionPtr =
|
||||||
|
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>(
|
||||||
|
'spine_enable_debug_extension');
|
||||||
|
late final _spine_enable_debug_extension =
|
||||||
|
_spine_enable_debug_extensionPtr.asFunction<void Function(int)>();
|
||||||
|
|
||||||
void spine_report_leaks() {
|
void spine_report_leaks() {
|
||||||
return _spine_report_leaks();
|
return _spine_report_leaks();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -224,10 +224,8 @@ class _SpineWidgetState extends State<SpineWidget> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (widget._controller._drawable != null) {
|
if (widget._controller._drawable != null) {
|
||||||
print("Skeleton loaded, rebuilding painter");
|
|
||||||
return _SpineRenderObjectWidget(widget._controller._drawable!, widget._controller, widget._fit, widget._alignment, widget._boundsProvider, widget._sizedByBounds);
|
return _SpineRenderObjectWidget(widget._controller._drawable!, widget._controller, widget._fit, widget._alignment, widget._boundsProvider, widget._sizedByBounds);
|
||||||
} else {
|
} else {
|
||||||
print("Skeleton not loaded yet");
|
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,3 +19,10 @@ set_target_properties(esotericsoftware_spine_flutter PROPERTIES
|
|||||||
target_include_directories(esotericsoftware_spine_flutter PUBLIC spine-cpp/include)
|
target_include_directories(esotericsoftware_spine_flutter PUBLIC spine-cpp/include)
|
||||||
target_compile_definitions(esotericsoftware_spine_flutter PUBLIC DART_SHARED_LIB)
|
target_compile_definitions(esotericsoftware_spine_flutter PUBLIC DART_SHARED_LIB)
|
||||||
|
|
||||||
|
if(${SPINE_FLUTTER_TESTBED})
|
||||||
|
set (CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize=undefined")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined")
|
||||||
|
add_executable(spine_flutter_test main.cpp spine_flutter.cpp ${SPINE_SOURCES})
|
||||||
|
include_directories(spine_flutter_test PUBLIC spine-cpp/include)
|
||||||
|
endif()
|
||||||
22
spine-flutter/src/main.cpp
Normal file
22
spine-flutter/src/main.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "spine/spine.h"
|
||||||
|
#include "spine_flutter.h"
|
||||||
|
|
||||||
|
using namespace spine;
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
int atlasLength = 0;
|
||||||
|
void* atlasData = SpineExtension::getInstance()->_readFile("/Users/badlogic/workspaces/spine-runtimes/spine-flutter/example/assets/spineboy.atlas", &atlasLength);
|
||||||
|
uint8_t* cstringAtlas = SpineExtension::calloc<uint8_t>(atlasLength + 1, __FILE__, __LINE__);
|
||||||
|
memcpy(cstringAtlas, atlasData, atlasLength);
|
||||||
|
int dataLength = 0;
|
||||||
|
uint8_t* data = (uint8_t*)SpineExtension::getInstance()->_readFile("/Users/badlogic/workspaces/spine-runtimes/spine-flutter/example/assets/spineboy-pro.skel", &dataLength);
|
||||||
|
|
||||||
|
spine_atlas atlas = spine_atlas_load((const utf8*)cstringAtlas);
|
||||||
|
spine_skeleton_data_result result = spine_skeleton_data_load_binary(atlas, data, dataLength);
|
||||||
|
spine_skeleton_drawable drawable = spine_skeleton_drawable_create(spine_skeleton_data_result_get_data(result));
|
||||||
|
spine_render_command cmd = spine_skeleton_drawable_render(drawable);
|
||||||
|
while (cmd) {
|
||||||
|
uint16_t *indices = spine_render_command_get_indices(cmd);
|
||||||
|
cmd = spine_render_command_get_next(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -34,6 +34,75 @@
|
|||||||
|
|
||||||
using namespace spine;
|
using namespace spine;
|
||||||
|
|
||||||
|
struct Block {
|
||||||
|
int size;
|
||||||
|
int allocated;
|
||||||
|
uint8_t* memory;
|
||||||
|
|
||||||
|
int free() {
|
||||||
|
return size - allocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool canFit(int numBytes) {
|
||||||
|
return free() >= numBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* allocate(int numBytes) {
|
||||||
|
uint8_t *ptr = memory + allocated;
|
||||||
|
memset(ptr, 0, numBytes);
|
||||||
|
allocated += numBytes;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BlockAllocator : public SpineObject{
|
||||||
|
int initialBlockSize;
|
||||||
|
Vector<Block> blocks;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BlockAllocator(int initialBlockSize) : initialBlockSize(initialBlockSize) {
|
||||||
|
blocks.add(newBlock(initialBlockSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
~BlockAllocator() {
|
||||||
|
for (int i = 0; i < blocks.size(); i++) {
|
||||||
|
SpineExtension::free(blocks[i].memory, __FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Block newBlock(int numBytes) {
|
||||||
|
Block block = {MathUtil::max(initialBlockSize, numBytes), 0, nullptr};
|
||||||
|
block.memory = SpineExtension::alloc<uint8_t>(block.size, __FILE__, __LINE__);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T *allocate(size_t num) {
|
||||||
|
return (T *) _allocate((int)(sizeof(T) * num));
|
||||||
|
}
|
||||||
|
|
||||||
|
void compress() {
|
||||||
|
int totalSize = 0;
|
||||||
|
for (int i = 0; i < blocks.size(); i++) {
|
||||||
|
totalSize += blocks[i].size;
|
||||||
|
SpineExtension::free(blocks[i].memory, __FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
blocks.clear();
|
||||||
|
blocks.add(newBlock(totalSize));
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void *_allocate(int numBytes) {
|
||||||
|
// 16-byte align allocations
|
||||||
|
int alignedNumBytes = numBytes + (numBytes % 16 != 0 ? 16 - (numBytes % 16) : 0);
|
||||||
|
Block *block = &blocks[blocks.size() - 1];
|
||||||
|
if (!block->canFit(alignedNumBytes)) {
|
||||||
|
blocks.add(newBlock(MathUtil::max(initialBlockSize, alignedNumBytes)));
|
||||||
|
block = &blocks[blocks.size() - 1];
|
||||||
|
}
|
||||||
|
return block->allocate(alignedNumBytes);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct AnimationStateEvent {
|
struct AnimationStateEvent {
|
||||||
EventType type;
|
EventType type;
|
||||||
TrackEntry *entry;
|
TrackEntry *entry;
|
||||||
@ -88,6 +157,7 @@ typedef struct _spine_skeleton_drawable {
|
|||||||
spine_animation_state_events animationStateEvents;
|
spine_animation_state_events animationStateEvents;
|
||||||
void *clipping;
|
void *clipping;
|
||||||
_spine_render_command *renderCommand;
|
_spine_render_command *renderCommand;
|
||||||
|
BlockAllocator *allocator;
|
||||||
} _spine_skeleton_drawable;
|
} _spine_skeleton_drawable;
|
||||||
|
|
||||||
typedef struct _spine_skin_entry {
|
typedef struct _spine_skin_entry {
|
||||||
@ -103,9 +173,24 @@ typedef struct _spine_skin_entries {
|
|||||||
|
|
||||||
static Color NULL_COLOR(0, 0, 0, 0);
|
static Color NULL_COLOR(0, 0, 0, 0);
|
||||||
|
|
||||||
|
static SpineExtension *defaultExtension = nullptr;
|
||||||
|
static DebugExtension *debugExtension = nullptr;
|
||||||
|
|
||||||
|
static void initExtensions() {
|
||||||
|
if (defaultExtension == nullptr) {
|
||||||
|
defaultExtension = new DefaultSpineExtension();
|
||||||
|
debugExtension = new DebugExtension(defaultExtension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
spine::SpineExtension *spine::getDefaultExtension() {
|
spine::SpineExtension *spine::getDefaultExtension() {
|
||||||
// return new spine::DebugExtension(new spine::DefaultSpineExtension());
|
initExtensions();
|
||||||
return new spine::DefaultSpineExtension();
|
return defaultExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spine_enable_debug_extension(int enable) {
|
||||||
|
initExtensions();
|
||||||
|
SpineExtension::setInstance(enable ? debugExtension : defaultExtension);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t spine_major_version() {
|
int32_t spine_major_version() {
|
||||||
@ -117,7 +202,9 @@ int32_t spine_minor_version() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void spine_report_leaks() {
|
void spine_report_leaks() {
|
||||||
// ((DebugExtension*)spine::SpineExtension::getInstance())->reportLeaks();
|
initExtensions();
|
||||||
|
debugExtension->reportLeaks();
|
||||||
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
@ -515,13 +602,13 @@ void spine_skeleton_data_dispose(spine_skeleton_data data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RenderCommand
|
// RenderCommand
|
||||||
_spine_render_command *spine_render_command_create(int numVertices, int32_t numIndices, spine_blend_mode blendMode, int32_t pageIndex) {
|
static _spine_render_command *spine_render_command_create(BlockAllocator &allocator, int numVertices, int32_t numIndices, spine_blend_mode blendMode, int32_t pageIndex) {
|
||||||
_spine_render_command *cmd = SpineExtension::alloc<_spine_render_command>(1, __FILE__, __LINE__);
|
_spine_render_command *cmd = allocator.allocate<_spine_render_command>(1);
|
||||||
cmd->positions = SpineExtension::alloc<float>(numVertices << 1, __FILE__, __LINE__);
|
cmd->positions = allocator.allocate<float>(numVertices << 1);
|
||||||
cmd->uvs = SpineExtension::alloc<float>(numVertices << 1, __FILE__, __LINE__);
|
cmd->uvs = allocator.allocate<float>(numVertices << 1);
|
||||||
cmd->colors = SpineExtension::alloc<int32_t>(numVertices, __FILE__, __LINE__);
|
cmd->colors = allocator.allocate<int32_t>(numVertices);
|
||||||
cmd->numVertices = numVertices;
|
cmd->numVertices = numVertices;
|
||||||
cmd->indices = SpineExtension::alloc<uint16_t>(numIndices, __FILE__, __LINE__);
|
cmd->indices = allocator.allocate<uint16_t>(numIndices);
|
||||||
cmd->numIndices = numIndices;
|
cmd->numIndices = numIndices;
|
||||||
cmd->blendMode = blendMode;
|
cmd->blendMode = blendMode;
|
||||||
cmd->atlasPage = pageIndex;
|
cmd->atlasPage = pageIndex;
|
||||||
@ -529,15 +616,6 @@ _spine_render_command *spine_render_command_create(int numVertices, int32_t numI
|
|||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spine_render_command_dispose(_spine_render_command *cmd) {
|
|
||||||
if (!cmd) return;
|
|
||||||
if (cmd->positions) SpineExtension::free(cmd->positions, __FILE__, __LINE__);
|
|
||||||
if (cmd->uvs) SpineExtension::free(cmd->uvs, __FILE__, __LINE__);
|
|
||||||
if (cmd->colors) SpineExtension::free(cmd->colors, __FILE__, __LINE__);
|
|
||||||
if (cmd->indices) SpineExtension::free(cmd->indices, __FILE__, __LINE__);
|
|
||||||
SpineExtension::free(cmd, __FILE__, __LINE__);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SkeletonDrawable
|
// SkeletonDrawable
|
||||||
|
|
||||||
spine_skeleton_drawable spine_skeleton_drawable_create(spine_skeleton_data skeletonData) {
|
spine_skeleton_drawable spine_skeleton_drawable_create(spine_skeleton_data skeletonData) {
|
||||||
@ -552,6 +630,7 @@ spine_skeleton_drawable spine_skeleton_drawable_create(spine_skeleton_data skele
|
|||||||
drawable->animationStateEvents = (spine_animation_state_events) listener;
|
drawable->animationStateEvents = (spine_animation_state_events) listener;
|
||||||
state->setListener(listener);
|
state->setListener(listener);
|
||||||
drawable->clipping = new (__FILE__, __LINE__) SkeletonClipping();
|
drawable->clipping = new (__FILE__, __LINE__) SkeletonClipping();
|
||||||
|
drawable->allocator = new (__FILE__, __LINE__) BlockAllocator(2048);
|
||||||
return (spine_skeleton_drawable) drawable;
|
return (spine_skeleton_drawable) drawable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,11 +642,7 @@ void spine_skeleton_drawable_dispose(spine_skeleton_drawable drawable) {
|
|||||||
if (_drawable->animationStateData) delete (AnimationStateData *) _drawable->animationStateData;
|
if (_drawable->animationStateData) delete (AnimationStateData *) _drawable->animationStateData;
|
||||||
if (_drawable->animationStateEvents) delete (Vector<AnimationStateEvent> *) (_drawable->animationStateEvents);
|
if (_drawable->animationStateEvents) delete (Vector<AnimationStateEvent> *) (_drawable->animationStateEvents);
|
||||||
if (_drawable->clipping) delete (SkeletonClipping *) _drawable->clipping;
|
if (_drawable->clipping) delete (SkeletonClipping *) _drawable->clipping;
|
||||||
while (_drawable->renderCommand) {
|
if (_drawable->allocator) delete (BlockAllocator *) _drawable->allocator;
|
||||||
_spine_render_command *cmd = _drawable->renderCommand;
|
|
||||||
_drawable->renderCommand = cmd->next;
|
|
||||||
spine_render_command_dispose(cmd);
|
|
||||||
}
|
|
||||||
SpineExtension::free(drawable, __FILE__, __LINE__);
|
SpineExtension::free(drawable, __FILE__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,11 +651,8 @@ spine_render_command spine_skeleton_drawable_render(spine_skeleton_drawable draw
|
|||||||
if (!_drawable) return nullptr;
|
if (!_drawable) return nullptr;
|
||||||
if (!_drawable->skeleton) return nullptr;
|
if (!_drawable->skeleton) return nullptr;
|
||||||
|
|
||||||
while (_drawable->renderCommand) {
|
_drawable->allocator->compress();
|
||||||
_spine_render_command *cmd = _drawable->renderCommand;
|
_drawable->renderCommand = nullptr;
|
||||||
_drawable->renderCommand = cmd->next;
|
|
||||||
spine_render_command_dispose(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<unsigned short> quadIndices;
|
Vector<unsigned short> quadIndices;
|
||||||
quadIndices.add(0);
|
quadIndices.add(0);
|
||||||
@ -671,7 +743,7 @@ spine_render_command spine_skeleton_drawable_render(spine_skeleton_drawable draw
|
|||||||
indicesCount = (int32_t) (clipper.getClippedTriangles().size());
|
indicesCount = (int32_t) (clipper.getClippedTriangles().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
_spine_render_command *cmd = spine_render_command_create(verticesCount, indicesCount, (spine_blend_mode) slot.getData().getBlendMode(), pageIndex);
|
_spine_render_command *cmd = spine_render_command_create(*_drawable->allocator, verticesCount, indicesCount, (spine_blend_mode) slot.getData().getBlendMode(), pageIndex);
|
||||||
|
|
||||||
memcpy(cmd->positions, vertices->buffer(), (verticesCount << 1) * sizeof(float));
|
memcpy(cmd->positions, vertices->buffer(), (verticesCount << 1) * sizeof(float));
|
||||||
memcpy(cmd->uvs, uvs->buffer(), (verticesCount << 1) * sizeof(float));
|
memcpy(cmd->uvs, uvs->buffer(), (verticesCount << 1) * sizeof(float));
|
||||||
@ -1345,7 +1417,7 @@ spine_path_constraint spine_skeleton_find_path_constraint(spine_skeleton skeleto
|
|||||||
}
|
}
|
||||||
|
|
||||||
spine_bounds spine_skeleton_get_bounds(spine_skeleton skeleton) {
|
spine_bounds spine_skeleton_get_bounds(spine_skeleton skeleton) {
|
||||||
_spine_bounds *bounds = SpineExtension::calloc<_spine_bounds>(1, __FILE__, __LINE__);
|
_spine_bounds *bounds = (_spine_bounds*)malloc(sizeof(_spine_bounds));
|
||||||
if (skeleton == nullptr) return (spine_bounds) bounds;
|
if (skeleton == nullptr) return (spine_bounds) bounds;
|
||||||
Skeleton *_skeleton = (Skeleton *) skeleton;
|
Skeleton *_skeleton = (Skeleton *) skeleton;
|
||||||
Vector<float> vertices;
|
Vector<float> vertices;
|
||||||
|
|||||||
@ -169,6 +169,7 @@ typedef enum spine_rotate_mode {
|
|||||||
|
|
||||||
SPINE_FLUTTER_EXPORT int32_t spine_major_version();
|
SPINE_FLUTTER_EXPORT int32_t spine_major_version();
|
||||||
SPINE_FLUTTER_EXPORT int32_t spine_minor_version();
|
SPINE_FLUTTER_EXPORT int32_t spine_minor_version();
|
||||||
|
SPINE_FLUTTER_EXPORT void spine_enable_debug_extension(int enable);
|
||||||
SPINE_FLUTTER_EXPORT void spine_report_leaks();
|
SPINE_FLUTTER_EXPORT void spine_report_leaks();
|
||||||
|
|
||||||
SPINE_FLUTTER_EXPORT float spine_color_get_r(spine_color color);
|
SPINE_FLUTTER_EXPORT float spine_color_get_r(spine_color color);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user