Formatting

This commit is contained in:
Mario Zechner 2026-03-14 15:39:56 +01:00
parent 9ec6ead094
commit e5bc9b709e
13 changed files with 584 additions and 581 deletions

View File

@ -140,7 +140,8 @@ public class SkeletonRenderer {
}
command.vertices.setSize(command.vertices.size + verticesLength);
region.computeWorldVertices(slot, sequence.getOffsets(sequenceIndex), command.vertices.items, vertexStart, vertexSize);
region.computeWorldVertices(slot, sequence.getOffsets(sequenceIndex), command.vertices.items, vertexStart,
vertexSize);
uvs = sequence.getUVs(sequenceIndex);
indices = quadTriangles;
color = region.getColor();

View File

@ -5,6 +5,5 @@
import FlutterMacOS
import Foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
}

View File

@ -65,53 +65,53 @@ int main() {
{
int atlas_length = 0;
uint8_t *atlas_bytes = read_file("data/dragon-pma.atlas", &atlas_length);
spine_atlas_result atlas_result = spine_atlas_load_callback((const char *) atlas_bytes, "data/", load_texture, unload_texture);
spine_atlas atlas = spine_atlas_result_get_atlas(atlas_result);
spine_atlas_result_dispose(atlas_result);
int atlas_length = 0;
uint8_t *atlas_bytes = read_file("data/dragon-pma.atlas", &atlas_length);
spine_atlas_result atlas_result = spine_atlas_load_callback((const char *) atlas_bytes, "data/", load_texture, unload_texture);
spine_atlas atlas = spine_atlas_result_get_atlas(atlas_result);
spine_atlas_result_dispose(atlas_result);
int skeleton_length = 0;
uint8_t *skeleton_bytes = read_file("data/dragon-ess.skel", &skeleton_length);
spine_skeleton_data_result skeleton_result = spine_skeleton_data_load_binary(atlas, skeleton_bytes, skeleton_length, "data/dragon-ess.skel");
spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(skeleton_result);
spine_skeleton_data_result_dispose(skeleton_result);
int skeleton_length = 0;
uint8_t *skeleton_bytes = read_file("data/dragon-ess.skel", &skeleton_length);
spine_skeleton_data_result skeleton_result = spine_skeleton_data_load_binary(atlas, skeleton_bytes, skeleton_length, "data/dragon-ess.skel");
spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(skeleton_result);
spine_skeleton_data_result_dispose(skeleton_result);
spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data);
spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable);
spine_skeleton_set_position(skeleton, width / 2.0f, height / 2.0f);
spine_skeleton_set_scale(skeleton, 0.5f, 0.5f);
spine_skeleton_setup_pose(skeleton);
spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data);
spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable);
spine_skeleton_set_position(skeleton, width / 2.0f, height / 2.0f);
spine_skeleton_set_scale(skeleton, 0.5f, 0.5f);
spine_skeleton_setup_pose(skeleton);
spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable);
spine_animation_state_set_animation_1(animation_state, 0, "flying", true);
spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable);
spine_animation_state_set_animation_1(animation_state, 0, "flying", true);
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
double currTime = glfwGetTime();
float delta = (float) (currTime - lastTime);
lastTime = currTime;
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
double currTime = glfwGetTime();
float delta = (float) (currTime - lastTime);
lastTime = currTime;
spine_animation_state_update(animation_state, delta);
spine_animation_state_apply(animation_state, skeleton);
spine_skeleton_update(skeleton, delta);
spine_skeleton_update_world_transform(skeleton, SPINE_PHYSICS_UPDATE);
spine_animation_state_update(animation_state, delta);
spine_animation_state_apply(animation_state, skeleton);
spine_skeleton_update(skeleton, delta);
spine_skeleton_update_world_transform(skeleton, SPINE_PHYSICS_UPDATE);
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
renderer_draw_c(renderer, skeleton, true);
glfwSwapBuffers(window);
glfwPollEvents();
}
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
renderer_draw_c(renderer, skeleton, true);
glfwSwapBuffers(window);
glfwPollEvents();
}
renderer_dispose(renderer);
spine_skeleton_drawable_dispose(drawable);
spine_skeleton_data_dispose(skeleton_data);
spine_atlas_dispose(atlas);
free(atlas_bytes);
free(skeleton_bytes);
renderer_dispose(renderer);
spine_skeleton_drawable_dispose(drawable);
spine_skeleton_data_dispose(skeleton_data);
spine_atlas_dispose(atlas);
free(atlas_bytes);
free(skeleton_bytes);
}
spine_report_leaks();

View File

@ -65,53 +65,53 @@ int main() {
{
int atlas_length = 0;
uint8_t *atlas_bytes = read_file("data/dragon-pma.atlas", &atlas_length);
spine_atlas_result atlas_result = spine_atlas_load_callback((const char *) atlas_bytes, "data/", load_texture, unload_texture);
spine_atlas atlas = spine_atlas_result_get_atlas(atlas_result);
spine_atlas_result_dispose(atlas_result);
int atlas_length = 0;
uint8_t *atlas_bytes = read_file("data/dragon-pma.atlas", &atlas_length);
spine_atlas_result atlas_result = spine_atlas_load_callback((const char *) atlas_bytes, "data/", load_texture, unload_texture);
spine_atlas atlas = spine_atlas_result_get_atlas(atlas_result);
spine_atlas_result_dispose(atlas_result);
int skeleton_length = 0;
uint8_t *skeleton_bytes = read_file("data/dragon-ess.json", &skeleton_length);
spine_skeleton_data_result skeleton_result = spine_skeleton_data_load_json(atlas, (const char *) skeleton_bytes, "data/dragon-ess.json");
spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(skeleton_result);
spine_skeleton_data_result_dispose(skeleton_result);
int skeleton_length = 0;
uint8_t *skeleton_bytes = read_file("data/dragon-ess.json", &skeleton_length);
spine_skeleton_data_result skeleton_result = spine_skeleton_data_load_json(atlas, (const char *) skeleton_bytes, "data/dragon-ess.json");
spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(skeleton_result);
spine_skeleton_data_result_dispose(skeleton_result);
spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data);
spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable);
spine_skeleton_set_position(skeleton, width / 2.0f, height / 2.0f);
spine_skeleton_set_scale(skeleton, 0.5f, 0.5f);
spine_skeleton_setup_pose(skeleton);
spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data);
spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable);
spine_skeleton_set_position(skeleton, width / 2.0f, height / 2.0f);
spine_skeleton_set_scale(skeleton, 0.5f, 0.5f);
spine_skeleton_setup_pose(skeleton);
spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable);
spine_animation_state_set_animation_1(animation_state, 0, "flying", true);
spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable);
spine_animation_state_set_animation_1(animation_state, 0, "flying", true);
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
double currTime = glfwGetTime();
float delta = (float) (currTime - lastTime);
lastTime = currTime;
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
double currTime = glfwGetTime();
float delta = (float) (currTime - lastTime);
lastTime = currTime;
spine_animation_state_update(animation_state, delta);
spine_animation_state_apply(animation_state, skeleton);
spine_skeleton_update(skeleton, delta);
spine_skeleton_update_world_transform(skeleton, SPINE_PHYSICS_UPDATE);
spine_animation_state_update(animation_state, delta);
spine_animation_state_apply(animation_state, skeleton);
spine_skeleton_update(skeleton, delta);
spine_skeleton_update_world_transform(skeleton, SPINE_PHYSICS_UPDATE);
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
renderer_draw_c(renderer, skeleton, true);
glfwSwapBuffers(window);
glfwPollEvents();
}
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
renderer_draw_c(renderer, skeleton, true);
glfwSwapBuffers(window);
glfwPollEvents();
}
renderer_dispose(renderer);
spine_skeleton_drawable_dispose(drawable);
spine_skeleton_data_dispose(skeleton_data);
spine_atlas_dispose(atlas);
free(atlas_bytes);
free(skeleton_bytes);
renderer_dispose(renderer);
spine_skeleton_drawable_dispose(drawable);
spine_skeleton_data_dispose(skeleton_data);
spine_atlas_dispose(atlas);
free(atlas_bytes);
free(skeleton_bytes);
}
spine_report_leaks();

View File

@ -67,50 +67,50 @@ int main() {
{
GlTextureLoader textureLoader;
Atlas *atlas = new Atlas("data/dragon-pma.atlas", &textureLoader);
GlTextureLoader textureLoader;
Atlas *atlas = new Atlas("data/dragon-pma.atlas", &textureLoader);
SkeletonJson json(*atlas);
SkeletonData *skeletonData = json.readSkeletonDataFile("data/dragon-ess.json");
if (!skeletonData) {
std::cerr << "Failed to load dragon: " << json.getError().buffer() << std::endl;
return -1;
}
SkeletonJson json(*atlas);
SkeletonData *skeletonData = json.readSkeletonDataFile("data/dragon-ess.json");
if (!skeletonData) {
std::cerr << "Failed to load dragon: " << json.getError().buffer() << std::endl;
return -1;
}
Skeleton skeleton(*skeletonData);
skeleton.setPosition(width / 2, height / 2);
skeleton.setScaleX(0.5f);
skeleton.setScaleY(0.5f);
skeleton.setupPose();
Skeleton skeleton(*skeletonData);
skeleton.setPosition(width / 2, height / 2);
skeleton.setScaleX(0.5f);
skeleton.setScaleY(0.5f);
skeleton.setupPose();
AnimationStateData animationStateData(*skeletonData);
AnimationState animationState(animationStateData);
animationState.setAnimation(0, "flying", true);
AnimationStateData animationStateData(*skeletonData);
AnimationState animationState(animationStateData);
animationState.setAnimation(0, "flying", true);
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
double currTime = glfwGetTime();
float delta = currTime - lastTime;
lastTime = currTime;
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
double currTime = glfwGetTime();
float delta = currTime - lastTime;
lastTime = currTime;
animationState.update(delta);
animationState.apply(skeleton);
skeleton.update(delta);
skeleton.updateWorldTransform(spine::Physics_Update);
animationState.update(delta);
animationState.apply(skeleton);
skeleton.update(delta);
skeleton.updateWorldTransform(spine::Physics_Update);
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
renderer_draw(renderer, &skeleton, true);
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
renderer_draw(renderer, &skeleton, true);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwSwapBuffers(window);
glfwPollEvents();
}
renderer_dispose(renderer);
delete skeletonData;
delete atlas;
renderer_dispose(renderer);
delete skeletonData;
delete atlas;
}
spine_report_leaks();

View File

@ -67,50 +67,50 @@ int main() {
{
GlTextureLoader textureLoader;
Atlas *atlas = new Atlas("data/dragon-pma.atlas", &textureLoader);
GlTextureLoader textureLoader;
Atlas *atlas = new Atlas("data/dragon-pma.atlas", &textureLoader);
SkeletonBinary binary(*atlas);
SkeletonData *skeletonData = binary.readSkeletonDataFile("data/dragon-ess.skel");
if (!skeletonData) {
std::cerr << "Failed to load dragon: " << binary.getError().buffer() << std::endl;
return -1;
}
SkeletonBinary binary(*atlas);
SkeletonData *skeletonData = binary.readSkeletonDataFile("data/dragon-ess.skel");
if (!skeletonData) {
std::cerr << "Failed to load dragon: " << binary.getError().buffer() << std::endl;
return -1;
}
Skeleton skeleton(*skeletonData);
skeleton.setPosition(width / 2, height / 2);
skeleton.setScaleX(0.5);
skeleton.setScaleY(0.5);
skeleton.setupPose();
Skeleton skeleton(*skeletonData);
skeleton.setPosition(width / 2, height / 2);
skeleton.setScaleX(0.5);
skeleton.setScaleY(0.5);
skeleton.setupPose();
AnimationStateData animationStateData(*skeletonData);
AnimationState animationState(animationStateData);
animationState.setAnimation(0, "flying", true);
AnimationStateData animationStateData(*skeletonData);
AnimationState animationState(animationStateData);
animationState.setAnimation(0, "flying", true);
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
double currTime = glfwGetTime();
float delta = currTime - lastTime;
lastTime = currTime;
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
double currTime = glfwGetTime();
float delta = currTime - lastTime;
lastTime = currTime;
animationState.update(delta);
animationState.apply(skeleton);
skeleton.update(delta);
skeleton.updateWorldTransform(spine::Physics_Update);
animationState.update(delta);
animationState.apply(skeleton);
skeleton.update(delta);
skeleton.updateWorldTransform(spine::Physics_Update);
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
renderer_draw(renderer, &skeleton, true);
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
renderer_draw(renderer, &skeleton, true);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwSwapBuffers(window);
glfwPollEvents();
}
renderer_dispose(renderer);
delete skeletonData;
delete atlas;
renderer_dispose(renderer);
delete skeletonData;
delete atlas;
}
spine_report_leaks();

View File

@ -73,67 +73,68 @@ int main() {
{
int atlas_length = 0;
uint8_t *atlas_bytes = read_file("data/spineboy-pma.atlas", &atlas_length);
spine_atlas_result atlas_result = spine_atlas_load_callback((const char *) atlas_bytes, "data/", load_texture, unload_texture);
spine_atlas atlas = spine_atlas_result_get_atlas(atlas_result);
spine_atlas_result_dispose(atlas_result);
int atlas_length = 0;
uint8_t *atlas_bytes = read_file("data/spineboy-pma.atlas", &atlas_length);
spine_atlas_result atlas_result = spine_atlas_load_callback((const char *) atlas_bytes, "data/", load_texture, unload_texture);
spine_atlas atlas = spine_atlas_result_get_atlas(atlas_result);
spine_atlas_result_dispose(atlas_result);
int skeleton_length = 0;
uint8_t *skeleton_bytes = read_file("data/spineboy-pro.skel", &skeleton_length);
spine_skeleton_data_result skeleton_result = spine_skeleton_data_load_binary(atlas, skeleton_bytes, skeleton_length, "data/spineboy-pro.skel");
spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(skeleton_result);
spine_skeleton_data_result_dispose(skeleton_result);
int skeleton_length = 0;
uint8_t *skeleton_bytes = read_file("data/spineboy-pro.skel", &skeleton_length);
spine_skeleton_data_result skeleton_result = spine_skeleton_data_load_binary(atlas, skeleton_bytes, skeleton_length,
"data/spineboy-pro.skel");
spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(skeleton_result);
spine_skeleton_data_result_dispose(skeleton_result);
spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data);
spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable);
spine_skeleton_set_scale(skeleton, 0.5f, 0.5f);
spine_skeleton_setup_pose(skeleton);
spine_skeleton_set_position(skeleton, 200.0f, height / 2.0f + 150.0f);
spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data);
spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable);
spine_skeleton_set_scale(skeleton, 0.5f, 0.5f);
spine_skeleton_setup_pose(skeleton);
spine_skeleton_set_position(skeleton, 200.0f, height / 2.0f + 150.0f);
spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable);
spine_animation_state_set_animation_1(animation_state, 0, "walk", true);
spine_animation_state_set_animation_1(animation_state, 1, "aim", true);
spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable);
spine_animation_state_set_animation_1(animation_state, 0, "walk", true);
spine_animation_state_set_animation_1(animation_state, 1, "aim", true);
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
double currTime = glfwGetTime();
float delta = (float) (currTime - lastTime);
lastTime = currTime;
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
double currTime = glfwGetTime();
float delta = (float) (currTime - lastTime);
lastTime = currTime;
spine_animation_state_update(animation_state, delta);
spine_animation_state_apply(animation_state, skeleton);
spine_skeleton_update(skeleton, delta);
spine_animation_state_update(animation_state, delta);
spine_animation_state_apply(animation_state, skeleton);
spine_skeleton_update(skeleton, delta);
spine_bone crosshair_bone = spine_skeleton_find_bone(skeleton, "crosshair");
if (crosshair_bone != nullptr) {
spine_bone parent = spine_bone_get_parent(crosshair_bone);
if (parent != nullptr) {
float localX = 0, localY = 0;
spine_bone_pose parent_pose = spine_bone_get_applied_pose(parent);
spine_bone_pose_world_to_local(parent_pose, (float) mouseX, (float) mouseY, &localX, &localY);
spine_bone_pose crosshair_pose = spine_bone_get_applied_pose(crosshair_bone);
spine_bone_pose_set_x(crosshair_pose, localX);
spine_bone_pose_set_y(crosshair_pose, localY);
spine_bone crosshair_bone = spine_skeleton_find_bone(skeleton, "crosshair");
if (crosshair_bone != nullptr) {
spine_bone parent = spine_bone_get_parent(crosshair_bone);
if (parent != nullptr) {
float localX = 0, localY = 0;
spine_bone_pose parent_pose = spine_bone_get_applied_pose(parent);
spine_bone_pose_world_to_local(parent_pose, (float) mouseX, (float) mouseY, &localX, &localY);
spine_bone_pose crosshair_pose = spine_bone_get_applied_pose(crosshair_bone);
spine_bone_pose_set_x(crosshair_pose, localX);
spine_bone_pose_set_y(crosshair_pose, localY);
}
}
spine_skeleton_update_world_transform(skeleton, SPINE_PHYSICS_UPDATE);
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
renderer_draw_c(renderer, skeleton, true);
glfwSwapBuffers(window);
glfwPollEvents();
}
spine_skeleton_update_world_transform(skeleton, SPINE_PHYSICS_UPDATE);
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
renderer_draw_c(renderer, skeleton, true);
glfwSwapBuffers(window);
glfwPollEvents();
}
renderer_dispose(renderer);
spine_skeleton_drawable_dispose(drawable);
spine_skeleton_data_dispose(skeleton_data);
spine_atlas_dispose(atlas);
free(atlas_bytes);
free(skeleton_bytes);
renderer_dispose(renderer);
spine_skeleton_drawable_dispose(drawable);
spine_skeleton_data_dispose(skeleton_data);
spine_atlas_dispose(atlas);
free(atlas_bytes);
free(skeleton_bytes);
}
spine_report_leaks();

View File

@ -82,93 +82,93 @@ int main() {
{
// Load the atlas and the skeleton data
GlTextureLoader textureLoader;
Atlas *atlas = new Atlas("data/spineboy-pma.atlas", &textureLoader);
SkeletonBinary binary(*atlas);
SkeletonData *skeletonData = binary.readSkeletonDataFile("data/spineboy-pro.skel");
// Load the atlas and the skeleton data
GlTextureLoader textureLoader;
Atlas *atlas = new Atlas("data/spineboy-pma.atlas", &textureLoader);
SkeletonBinary binary(*atlas);
SkeletonData *skeletonData = binary.readSkeletonDataFile("data/spineboy-pro.skel");
// Create a skeleton from the data
Skeleton skeleton(*skeletonData);
skeleton.setScaleX(0.5);
skeleton.setScaleY(0.5);
skeleton.setupPose();
// Create a skeleton from the data
Skeleton skeleton(*skeletonData);
skeleton.setScaleX(0.5);
skeleton.setScaleY(0.5);
skeleton.setupPose();
// Position the skeleton on the left side like in the Flutter example
skeleton.setPosition(200, height / 2 + 150);
// Position the skeleton on the left side like in the Flutter example
skeleton.setPosition(200, height / 2 + 150);
// Set the global skeleton pointer for IK
ikSkeleton = &skeleton;
// Set the global skeleton pointer for IK
ikSkeleton = &skeleton;
// Create an AnimationState to drive animations on the skeleton
AnimationStateData animationStateData(*skeletonData);
AnimationState animationState(animationStateData);
// Create an AnimationState to drive animations on the skeleton
AnimationStateData animationStateData(*skeletonData);
AnimationState animationState(animationStateData);
// Set the walk animation on track 0 and aim animation on track 1
animationState.setAnimation(0, "walk", true);
animationState.setAnimation(1, "aim", true);
// Set the walk animation on track 0 and aim animation on track 1
animationState.setAnimation(0, "walk", true);
animationState.setAnimation(1, "aim", true);
// Create the renderer and set the viewport size to match the window size
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
// Create the renderer and set the viewport size to match the window size
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
// Rendering loop
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
// Calculate the delta time in seconds
double currTime = glfwGetTime();
float delta = currTime - lastTime;
lastTime = currTime;
// Rendering loop
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
// Calculate the delta time in seconds
double currTime = glfwGetTime();
float delta = currTime - lastTime;
lastTime = currTime;
// Update and apply the animation state to the skeleton
animationState.update(delta);
animationState.apply(skeleton);
// Update and apply the animation state to the skeleton
animationState.update(delta);
animationState.apply(skeleton);
// Update the skeleton time (used for physics)
skeleton.update(delta);
// Update the skeleton time (used for physics)
skeleton.update(delta);
// Update the crosshair bone position based on mouse position
Bone *crosshairBone = skeleton.findBone("crosshair");
if (crosshairBone != nullptr) {
Bone *parent = crosshairBone->getParent();
if (parent != nullptr) {
// Convert mouse position to world coordinates
float worldX = mouseX;
float worldY = mouseY;
// Update the crosshair bone position based on mouse position
Bone *crosshairBone = skeleton.findBone("crosshair");
if (crosshairBone != nullptr) {
Bone *parent = crosshairBone->getParent();
if (parent != nullptr) {
// Convert mouse position to world coordinates
float worldX = mouseX;
float worldY = mouseY;
// Convert world position to parent's local space
float localX, localY;
parent->getAppliedPose().worldToLocal(worldX, worldY, localX, localY);
// Convert world position to parent's local space
float localX, localY;
parent->getAppliedPose().worldToLocal(worldX, worldY, localX, localY);
// Set the crosshair bone position in its applied pose
crosshairBone->getAppliedPose().setX(localX);
crosshairBone->getAppliedPose().setY(localY);
// Set the crosshair bone position in its applied pose
crosshairBone->getAppliedPose().setX(localX);
crosshairBone->getAppliedPose().setY(localY);
}
}
// Calculate the new pose
skeleton.updateWorldTransform(spine::Physics_Update);
// Clear the screen
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
// Render the skeleton in its current pose
renderer_draw(renderer, &skeleton, true);
// Present the rendering results and poll for events
glfwSwapBuffers(window);
glfwPollEvents();
}
// Calculate the new pose
skeleton.updateWorldTransform(spine::Physics_Update);
// Clear the IK skeleton pointer
ikSkeleton = nullptr;
// Clear the screen
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
// Dispose everything
renderer_dispose(renderer);
delete skeletonData;
delete atlas;
// Render the skeleton in its current pose
renderer_draw(renderer, &skeleton, true);
// Present the rendering results and poll for events
glfwSwapBuffers(window);
glfwPollEvents();
}
// Clear the IK skeleton pointer
ikSkeleton = nullptr;
// Dispose everything
renderer_dispose(renderer);
delete skeletonData;
delete atlas;
// Kill the window and GLFW
// Kill the window and GLFW
}
spine_report_leaks();

View File

@ -102,80 +102,80 @@ int main() {
{
// Load the atlas and the skeleton data
int atlas_length = 0;
uint8_t *atlas_bytes = read_file("data/spineboy-pma.atlas", &atlas_length);
spine_atlas_result result = spine_atlas_load_callback((const char *) atlas_bytes, "data/", load_texture, unload_texture);
spine_atlas atlas = spine_atlas_result_get_atlas(result);
spine_atlas_result_dispose(result);
// Load the atlas and the skeleton data
int atlas_length = 0;
uint8_t *atlas_bytes = read_file("data/spineboy-pma.atlas", &atlas_length);
spine_atlas_result result = spine_atlas_load_callback((const char *) atlas_bytes, "data/", load_texture, unload_texture);
spine_atlas atlas = spine_atlas_result_get_atlas(result);
spine_atlas_result_dispose(result);
int skeleton_length = 0;
// uint8_t *skeleton_bytes = read_file("data/spineboy-pro.skel", &skeleton_length);
// spine_skeleton_data_result result = spine_skeleton_data_load_binary(atlas, skeleton_bytes, skeleton_length);
uint8_t *skeleton_bytes = read_file("data/spineboy-pro.json", &skeleton_length);
spine_skeleton_data_result result2 = spine_skeleton_data_load_json(atlas, (const char *) skeleton_bytes, "data/");
spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(result2);
spine_skeleton_data_result_dispose(result2);
int skeleton_length = 0;
// uint8_t *skeleton_bytes = read_file("data/spineboy-pro.skel", &skeleton_length);
// spine_skeleton_data_result result = spine_skeleton_data_load_binary(atlas, skeleton_bytes, skeleton_length);
uint8_t *skeleton_bytes = read_file("data/spineboy-pro.json", &skeleton_length);
spine_skeleton_data_result result2 = spine_skeleton_data_load_json(atlas, (const char *) skeleton_bytes, "data/");
spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(result2);
spine_skeleton_data_result_dispose(result2);
// Create a skeleton from the data, set the skeleton's position to the bottom center of
// the screen and scale it to make it smaller.
spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data);
spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable);
spine_skeleton_set_position(skeleton, width / 2, height - 100);
spine_skeleton_set_scale(skeleton, 0.3f, 0.3f);
// Create a skeleton from the data, set the skeleton's position to the bottom center of
// the screen and scale it to make it smaller.
spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data);
spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable);
spine_skeleton_set_position(skeleton, width / 2, height - 100);
spine_skeleton_set_scale(skeleton, 0.3f, 0.3f);
// Create an AnimationState to drive animations on the skeleton. Set the "portal" animation
// on track with index 0.
spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable);
spine_animation_state_data animation_state_data = spine_animation_state_get_data(animation_state);
spine_animation_state_data_set_default_mix(animation_state_data, 0.2f);
spine_animation_state_set_animation_1(animation_state, 0, "portal", true);
spine_track_entry entry = spine_animation_state_add_animation_1(animation_state, 0, "run", true, 0);
spine_track_entry_set_listener(entry, track_listener, NULL);
// Create an AnimationState to drive animations on the skeleton. Set the "portal" animation
// on track with index 0.
spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable);
spine_animation_state_data animation_state_data = spine_animation_state_get_data(animation_state);
spine_animation_state_data_set_default_mix(animation_state_data, 0.2f);
spine_animation_state_set_animation_1(animation_state, 0, "portal", true);
spine_track_entry entry = spine_animation_state_add_animation_1(animation_state, 0, "run", true, 0);
spine_track_entry_set_listener(entry, track_listener, NULL);
// Create the renderer and set the viewport size to match the window size. This sets up a
// pixel perfect orthogonal projection for 2D rendering.
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
// Create the renderer and set the viewport size to match the window size. This sets up a
// pixel perfect orthogonal projection for 2D rendering.
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
// Rendering loop
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
// Calculate the delta time in seconds
double currTime = glfwGetTime();
float delta = currTime - lastTime;
lastTime = currTime;
// Rendering loop
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
// Calculate the delta time in seconds
double currTime = glfwGetTime();
float delta = currTime - lastTime;
lastTime = currTime;
// Update and apply the animation state to the skeleton
spine_animation_state_update(animation_state, delta);
spine_animation_state_apply(animation_state, skeleton);
// Update and apply the animation state to the skeleton
spine_animation_state_update(animation_state, delta);
spine_animation_state_apply(animation_state, skeleton);
// Update the skeleton time (used for physics)
spine_skeleton_update(skeleton, delta);
// Update the skeleton time (used for physics)
spine_skeleton_update(skeleton, delta);
// Calculate the new pose
spine_skeleton_update_world_transform(skeleton, SPINE_PHYSICS_UPDATE);
// Calculate the new pose
spine_skeleton_update_world_transform(skeleton, SPINE_PHYSICS_UPDATE);
// Clear the screen
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
// Clear the screen
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
// Render the skeleton in its current pose
renderer_draw_c(renderer, skeleton, true);
// Render the skeleton in its current pose
renderer_draw_c(renderer, skeleton, true);
// Present the rendering results and poll for events
glfwSwapBuffers(window);
glfwPollEvents();
}
// Present the rendering results and poll for events
glfwSwapBuffers(window);
glfwPollEvents();
}
// Dispose everything
renderer_dispose(renderer);
spine_skeleton_drawable_dispose(drawable);
spine_skeleton_data_dispose(skeleton_data);
spine_atlas_dispose(atlas);
free(atlas_bytes);
free(skeleton_bytes);
// Dispose everything
renderer_dispose(renderer);
spine_skeleton_drawable_dispose(drawable);
spine_skeleton_data_dispose(skeleton_data);
spine_atlas_dispose(atlas);
free(atlas_bytes);
free(skeleton_bytes);
// Kill the window and GLFW
// Kill the window and GLFW
}
spine_report_leaks();

View File

@ -82,8 +82,7 @@ int main() {
skeleton.setupPose();
skeleton.updateWorldTransform(spine::Physics_None);
std::cout << "Loaded mix-and-match successfully. Bones=" << skeletonData->getBones().size()
<< ", slots=" << skeletonData->getSlots().size()
std::cout << "Loaded mix-and-match successfully. Bones=" << skeletonData->getBones().size() << ", slots=" << skeletonData->getSlots().size()
<< ", skins=" << skeletonData->getSkins().size() << std::endl;
delete skeletonData;

View File

@ -94,57 +94,57 @@ int main() {
{
int atlas_length = 0;
uint8_t *atlas_bytes = read_file("data/celestial-circus-pma.atlas", &atlas_length);
spine_atlas_result atlas_result = spine_atlas_load_callback((const char *) atlas_bytes, "data/", load_texture, unload_texture);
spine_atlas atlas = spine_atlas_result_get_atlas(atlas_result);
spine_atlas_result_dispose(atlas_result);
int atlas_length = 0;
uint8_t *atlas_bytes = read_file("data/celestial-circus-pma.atlas", &atlas_length);
spine_atlas_result atlas_result = spine_atlas_load_callback((const char *) atlas_bytes, "data/", load_texture, unload_texture);
spine_atlas atlas = spine_atlas_result_get_atlas(atlas_result);
spine_atlas_result_dispose(atlas_result);
int skeleton_length = 0;
uint8_t *skeleton_bytes = read_file("data/celestial-circus-pro.skel", &skeleton_length);
spine_skeleton_data_result skeleton_result = spine_skeleton_data_load_binary(atlas, skeleton_bytes, skeleton_length,
"data/celestial-circus-pro.skel");
spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(skeleton_result);
spine_skeleton_data_result_dispose(skeleton_result);
int skeleton_length = 0;
uint8_t *skeleton_bytes = read_file("data/celestial-circus-pro.skel", &skeleton_length);
spine_skeleton_data_result skeleton_result = spine_skeleton_data_load_binary(atlas, skeleton_bytes, skeleton_length,
"data/celestial-circus-pro.skel");
spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(skeleton_result);
spine_skeleton_data_result_dispose(skeleton_result);
spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data);
spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable);
spine_skeleton_set_scale(skeleton, 0.2f, 0.2f);
spine_skeleton_setup_pose(skeleton);
spine_skeleton_update(skeleton, 0);
spine_skeleton_update_world_transform(skeleton, SPINE_PHYSICS_UPDATE);
spine_skeleton_set_position(skeleton, width / 2.0f, height / 2.0f + 150.0f);
dragSkeleton = skeleton;
spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable);
spine_animation_state_set_animation_1(animation_state, 0, "eyeblink-long", true);
spine_animation_state_set_animation_1(animation_state, 1, "wind-idle", true);
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
double currTime = glfwGetTime();
float delta = (float) (currTime - lastTime);
lastTime = currTime;
spine_animation_state_update(animation_state, delta);
spine_animation_state_apply(animation_state, skeleton);
spine_skeleton_update(skeleton, delta);
spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data);
spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable);
spine_skeleton_set_scale(skeleton, 0.2f, 0.2f);
spine_skeleton_setup_pose(skeleton);
spine_skeleton_update(skeleton, 0);
spine_skeleton_update_world_transform(skeleton, SPINE_PHYSICS_UPDATE);
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
renderer_draw_c(renderer, skeleton, true);
glfwSwapBuffers(window);
glfwPollEvents();
}
spine_skeleton_set_position(skeleton, width / 2.0f, height / 2.0f + 150.0f);
dragSkeleton = skeleton;
dragSkeleton = nullptr;
renderer_dispose(renderer);
spine_skeleton_drawable_dispose(drawable);
spine_skeleton_data_dispose(skeleton_data);
spine_atlas_dispose(atlas);
free(atlas_bytes);
free(skeleton_bytes);
spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable);
spine_animation_state_set_animation_1(animation_state, 0, "eyeblink-long", true);
spine_animation_state_set_animation_1(animation_state, 1, "wind-idle", true);
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
double currTime = glfwGetTime();
float delta = (float) (currTime - lastTime);
lastTime = currTime;
spine_animation_state_update(animation_state, delta);
spine_animation_state_apply(animation_state, skeleton);
spine_skeleton_update(skeleton, delta);
spine_skeleton_update_world_transform(skeleton, SPINE_PHYSICS_UPDATE);
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
renderer_draw_c(renderer, skeleton, true);
glfwSwapBuffers(window);
glfwPollEvents();
}
dragSkeleton = nullptr;
renderer_dispose(renderer);
spine_skeleton_drawable_dispose(drawable);
spine_skeleton_data_dispose(skeleton_data);
spine_atlas_dispose(atlas);
free(atlas_bytes);
free(skeleton_bytes);
}
spine_report_leaks();

View File

@ -104,76 +104,76 @@ int main() {
{
// Load the atlas and the skeleton data
GlTextureLoader textureLoader;
Atlas *atlas = new Atlas("data/celestial-circus-pma.atlas", &textureLoader);
SkeletonBinary binary(*atlas);
binary.setScale(0.2f);
SkeletonData *skeletonData = binary.readSkeletonDataFile("data/celestial-circus-pro.skel");
// Load the atlas and the skeleton data
GlTextureLoader textureLoader;
Atlas *atlas = new Atlas("data/celestial-circus-pma.atlas", &textureLoader);
SkeletonBinary binary(*atlas);
binary.setScale(0.2f);
SkeletonData *skeletonData = binary.readSkeletonDataFile("data/celestial-circus-pro.skel");
// Create a skeleton from the data
Skeleton skeleton(*skeletonData);
skeleton.setupPose();
skeleton.update(0);
skeleton.updateWorldTransform(Physics_Update);
// Create a skeleton from the data
Skeleton skeleton(*skeletonData);
skeleton.setupPose();
skeleton.update(0);
skeleton.updateWorldTransform(Physics_Update);
// Center the skeleton on screen
skeleton.setPosition(width / 2, height / 2 + 150);
// Center the skeleton on screen
skeleton.setPosition(width / 2, height / 2 + 150);
// Set the global skeleton pointer for mouse dragging
dragSkeleton = &skeleton;
// Set the global skeleton pointer for mouse dragging
dragSkeleton = &skeleton;
// Create an AnimationState to drive animations on the skeleton
AnimationStateData animationStateData(*skeletonData);
AnimationState animationState(animationStateData);
// Create an AnimationState to drive animations on the skeleton
AnimationStateData animationStateData(*skeletonData);
AnimationState animationState(animationStateData);
// Set the "eyeblink-long" animation like in the web example
animationState.setAnimation(0, "eyeblink-long", true);
animationState.setAnimation(1, "wind-idle", true);
// Set the "eyeblink-long" animation like in the web example
animationState.setAnimation(0, "eyeblink-long", true);
animationState.setAnimation(1, "wind-idle", true);
// Create the renderer and set the viewport size to match the window size. This sets up a
// pixel perfect orthogonal projection for 2D rendering.
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
// Create the renderer and set the viewport size to match the window size. This sets up a
// pixel perfect orthogonal projection for 2D rendering.
renderer_t *renderer = renderer_create();
renderer_set_viewport_size(renderer, width, height);
// Rendering loop
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
// Calculate the delta time in seconds
double currTime = glfwGetTime();
float delta = currTime - lastTime;
lastTime = currTime;
// Rendering loop
double lastTime = glfwGetTime();
while (!glfwWindowShouldClose(window)) {
// Calculate the delta time in seconds
double currTime = glfwGetTime();
float delta = currTime - lastTime;
lastTime = currTime;
// Update and apply the animation state to the skeleton
animationState.update(delta);
animationState.apply(skeleton);
// Update and apply the animation state to the skeleton
animationState.update(delta);
animationState.apply(skeleton);
// Update the skeleton time (used for physics)
skeleton.update(delta);
// Update the skeleton time (used for physics)
skeleton.update(delta);
// Calculate the new pose
skeleton.updateWorldTransform(spine::Physics_Update);
// Calculate the new pose
skeleton.updateWorldTransform(spine::Physics_Update);
// Clear the screen
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
// Clear the screen
gl::glClear(gl::GL_COLOR_BUFFER_BIT);
// Render the skeleton in its current pose
renderer_draw(renderer, &skeleton, true);
// Render the skeleton in its current pose
renderer_draw(renderer, &skeleton, true);
// Present the rendering results and poll for events
glfwSwapBuffers(window);
glfwPollEvents();
}
// Present the rendering results and poll for events
glfwSwapBuffers(window);
glfwPollEvents();
}
// Clear the drag skeleton pointer
dragSkeleton = nullptr;
// Clear the drag skeleton pointer
dragSkeleton = nullptr;
// Dispose everything
renderer_dispose(renderer);
delete skeletonData;
delete atlas;
// Dispose everything
renderer_dispose(renderer);
delete skeletonData;
delete atlas;
// Kill the window and GLFW
// Kill the window and GLFW
}
spine_report_leaks();

View File

@ -68,7 +68,8 @@ func runSkeletonDrawableTestSwift() {
let boundsAfterPose = drawable.skeleton.bounds
print(
" Bounds after setupPose: x=\(boundsAfterPose.x), y=\(boundsAfterPose.y), width=\(boundsAfterPose.width), height=\(boundsAfterPose.height)")
" Bounds after setupPose: x=\(boundsAfterPose.x), y=\(boundsAfterPose.y), width=\(boundsAfterPose.width), height=\(boundsAfterPose.height)"
)
// Test position
let position = drawable.skeleton.getPosition()
@ -127,183 +128,185 @@ func runSkeletonDrawableTestSwift() {
drawable.update(0.5) // Update to middle of jump
let boundsAfterJump = drawable.skeleton.bounds
print(" Bounds during jump: x=\(boundsAfterJump.x), y=\(boundsAfterJump.y), width=\(boundsAfterJump.width), height=\(boundsAfterJump.height)")
print(
" Bounds during jump: x=\(boundsAfterJump.x), y=\(boundsAfterJump.y), width=\(boundsAfterJump.width), height=\(boundsAfterJump.height)"
)
// Test skin entries
print("\nTesting skin entries:")
// First, check available skins
let skins = skeletonData.skins
print(" Available skins: \(skins.count)")
if skins.count > 0 {
// List all skin names
for i in 0..<skins.count {
if let skin = skins[i] {
print(" Skin \(i): \(skin.name)")
// First, check available skins
let skins = skeletonData.skins
print(" Available skins: \(skins.count)")
if skins.count > 0 {
// List all skin names
for i in 0..<skins.count {
if let skin = skins[i] {
print(" Skin \(i): \(skin.name)")
}
}
// Set and test the first skin (or default skin)
if let defaultSkin = skins[0] {
// First get entries from the skin directly
let entriesFromData = defaultSkin.getEntries()
print(" Skin '\(defaultSkin.name)' from skeletonData has \(entriesFromData.count) entries")
// Count entries with attachments
let withAttachments = entriesFromData.filter { $0.attachment != nil }.count
print(" Entries with attachments: \(withAttachments)")
// Now set it on the skeleton
drawable.skeleton.setSkin2(defaultSkin)
drawable.skeleton.setupPoseSlots() // Update slots after setting skin
print(" Set skin on skeleton: \(defaultSkin.name)")
}
}
}
// Set and test the first skin (or default skin)
if let defaultSkin = skins[0] {
// First get entries from the skin directly
let entriesFromData = defaultSkin.getEntries()
print(" Skin '\(defaultSkin.name)' from skeletonData has \(entriesFromData.count) entries")
// Now test the skeleton's current skin
if let skin = drawable.skeleton.skin {
let entries = skin.getEntries()
print(" Skeleton's current skin has \(entries.count) entries")
// Count entries with attachments
let withAttachments = entriesFromData.filter { $0.attachment != nil }.count
print(" Entries with attachments: \(withAttachments)")
// Show first few entries (with or without attachments for debugging)
let entriesToShow = min(5, entries.count)
for i in 0..<entriesToShow {
let entry = entries[i]
if let attachment = entry.attachment {
let attachmentType = attachment.rtti.rttiClassName ?? "unknown"
let attachmentName = attachment.name
print(" Entry \(i): slot=\(entry.slotIndex), name=\(entry.name)")
print(" Attachment: name=\(attachmentName), type=\(attachmentType)")
} else {
print(" Entry \(i): slot=\(entry.slotIndex), name=\(entry.name), attachment=nil")
}
}
// Now set it on the skeleton
drawable.skeleton.setSkin2(defaultSkin)
drawable.skeleton.setupPoseSlots() // Update slots after setting skin
print(" Set skin on skeleton: \(defaultSkin.name)")
}
}
// Count total entries with attachments
let entriesWithAttachments = entries.filter { $0.attachment != nil }.count
print(" Total entries with attachments: \(entriesWithAttachments) out of \(entries.count)")
// Now test the skeleton's current skin
if let skin = drawable.skeleton.skin {
let entries = skin.getEntries()
print(" Skeleton's current skin has \(entries.count) entries")
// Show first few entries (with or without attachments for debugging)
let entriesToShow = min(5, entries.count)
for i in 0..<entriesToShow {
let entry = entries[i]
if let attachment = entry.attachment {
let attachmentType = attachment.rtti.rttiClassName ?? "unknown"
let attachmentName = attachment.name
print(" Entry \(i): slot=\(entry.slotIndex), name=\(entry.name)")
print(" Attachment: name=\(attachmentName), type=\(attachmentType)")
if entries.count > 3 {
print(" ... and \(entries.count - 3) more entries")
}
} else {
print(" Entry \(i): slot=\(entry.slotIndex), name=\(entry.name), attachment=nil")
print(" No skin is currently set")
}
}
// Count total entries with attachments
let entriesWithAttachments = entries.filter { $0.attachment != nil }.count
print(" Total entries with attachments: \(entriesWithAttachments) out of \(entries.count)")
// Test bone pose transformations
print("\nTesting bone pose transformations:")
if let rootBone = drawable.skeleton.rootBone {
// Test bone properties
let bonePose = rootBone.appliedPose
print(" Root bone: name=\(rootBone.data.name), x=\(bonePose.x), y=\(bonePose.y)")
if entries.count > 3 {
print(" ... and \(entries.count - 3) more entries")
}
} else {
print(" No skin is currently set")
}
// Get the bone's transform matrix from applied pose
let a = bonePose.a
let b = bonePose.b
let c = bonePose.c
let d = bonePose.d
let worldX = bonePose.worldX
let worldY = bonePose.worldY
print(" Root bone transform: a=\(a), b=\(b), c=\(c), d=\(d), worldX=\(worldX), worldY=\(worldY)")
// Test bone pose transformations
print("\nTesting bone pose transformations:")
if let rootBone = drawable.skeleton.rootBone {
// Test bone properties
let bonePose = rootBone.appliedPose
print(" Root bone: name=\(rootBone.data.name), x=\(bonePose.x), y=\(bonePose.y)")
// Use BonePose's built-in transformation methods
let worldPoint = Vector(x: 100, y: 100)
let localPoint = bonePose.worldToLocal(worldX: worldPoint.x, worldY: worldPoint.y)
print(" World point (100, 100) -> Local: (\(localPoint.x), \(localPoint.y))")
// Get the bone's transform matrix from applied pose
let a = bonePose.a
let b = bonePose.b
let c = bonePose.c
let d = bonePose.d
let worldX = bonePose.worldX
let worldY = bonePose.worldY
print(" Root bone transform: a=\(a), b=\(b), c=\(c), d=\(d), worldX=\(worldX), worldY=\(worldY)")
// Test local to world transformation
let backToWorld = bonePose.localToWorld(localX: localPoint.x, localY: localPoint.y)
print(" Local back to world: (\(backToWorld.x), \(backToWorld.y))")
// Use BonePose's built-in transformation methods
let worldPoint = Vector(x: 100, y: 100)
let localPoint = bonePose.worldToLocal(worldX: worldPoint.x, worldY: worldPoint.y)
print(" World point (100, 100) -> Local: (\(localPoint.x), \(localPoint.y))")
// Test rotation and scale from the pose
let rotation = bonePose.rotation
let scaleX = bonePose.scaleX
let scaleY = bonePose.scaleY
print(" Bone rotation: \(rotation), scale: (\(scaleX), \(scaleY))")
// Test local to world transformation
let backToWorld = bonePose.localToWorld(localX: localPoint.x, localY: localPoint.y)
print(" Local back to world: (\(backToWorld.x), \(backToWorld.y))")
// Test parent transformation if parent exists
if let parentBone = rootBone.parent {
let parentPose = parentBone.appliedPose
print(" Parent bone: name=\(parentBone.data.name), worldX=\(parentPose.worldX), worldY=\(parentPose.worldY)")
// Test rotation and scale from the pose
let rotation = bonePose.rotation
let scaleX = bonePose.scaleX
let scaleY = bonePose.scaleY
print(" Bone rotation: \(rotation), scale: (\(scaleX), \(scaleY))")
// Transform world to parent coordinates
let parentPoint = bonePose.worldToParent(worldX: worldPoint.x, worldY: worldPoint.y)
print(" World point (100, 100) -> Parent: (\(parentPoint.x), \(parentPoint.y))")
}
}
// Test parent transformation if parent exists
if let parentBone = rootBone.parent {
let parentPose = parentBone.appliedPose
print(" Parent bone: name=\(parentBone.data.name), worldX=\(parentPose.worldX), worldY=\(parentPose.worldY)")
// Test render command
print("\nTesting render command:")
if let renderCommand = drawable.render() {
print(" Got render command with blend mode: \(renderCommand.blendMode)")
// Note: atlasPage and vertices are accessed via getters, not properties
print(" Render command received successfully")
}
// Transform world to parent coordinates
let parentPoint = bonePose.worldToParent(worldX: worldPoint.x, worldY: worldPoint.y)
print(" World point (100, 100) -> Parent: (\(parentPoint.x), \(parentPoint.y))")
}
}
// Test constraint RTTI (similar to Dart test)
print("\nTesting constraint RTTI:")
let constraints = drawable.skeleton.constraints
print(" Total constraints: \(constraints.count)")
for i in 0..<constraints.count {
if let constraint = constraints[i] {
let rttiClassName = constraint.rtti.rttiClassName ?? "unknown"
print(" Constraint \(i) type: \(rttiClassName)")
// Test render command
print("\nTesting render command:")
if let renderCommand = drawable.render() {
print(" Got render command with blend mode: \(renderCommand.blendMode)")
// Note: atlasPage and vertices are accessed via getters, not properties
print(" Render command received successfully")
}
let data = constraint.data
let dataRttiClassName = data.rtti.rttiClassName ?? "unknown"
print(" Data type: \(dataRttiClassName)")
print(" Name: \(data.name)")
}
}
// Test constraint RTTI (similar to Dart test)
print("\nTesting constraint RTTI:")
let constraints = drawable.skeleton.constraints
print(" Total constraints: \(constraints.count)")
for i in 0..<constraints.count {
if let constraint = constraints[i] {
let rttiClassName = constraint.rtti.rttiClassName ?? "unknown"
print(" Constraint \(i) type: \(rttiClassName)")
// Test calling PosedActive methods on Bone instance
print("\nTesting PosedActive methods on Bone:")
if let bone = drawable.skeleton.findBone("rear-shin") {
print(" Found bone: \(bone.data.name)")
let data = constraint.data
let dataRttiClassName = data.rtti.rttiClassName ?? "unknown"
print(" Data type: \(dataRttiClassName)")
print(" Name: \(data.name)")
}
}
// Cast Bone to PosedActive and try to call PosedActive methods
let posedActive = bone as PosedActive
print(" Successfully cast Bone to PosedActive")
// Test calling PosedActive methods on Bone instance
print("\nTesting PosedActive methods on Bone:")
if let bone = drawable.skeleton.findBone("rear-shin") {
print(" Found bone: \(bone.data.name)")
// Try to access PosedActive properties/methods
// This should work if the pointer is correct, or crash if there's an offset issue
// Cast Bone to PosedActive and try to call PosedActive methods
let posedActive = bone as PosedActive
print(" Successfully cast Bone to PosedActive")
// Get the isActive property (this is a PosedActive method)
let isActiveFromPosed = posedActive.isActive
print(" isActive from PosedActive: \(isActiveFromPosed)")
// Try to access PosedActive properties/methods
// This should work if the pointer is correct, or crash if there's an offset issue
// Set active property through PosedActive
print(" Setting active to false through PosedActive...")
posedActive.active = false
print(" ✓ Set active property succeeded")
// Get the isActive property (this is a PosedActive method)
let isActiveFromPosed = posedActive.isActive
print(" isActive from PosedActive: \(isActiveFromPosed)")
// Check if it's actually false
let isStillActive = posedActive.isActive
print(" isActive after setting to false: \(isStillActive)")
// Set active property through PosedActive
print(" Setting active to false through PosedActive...")
posedActive.active = false
print(" ✓ Set active property succeeded")
// Restore it
posedActive.active = true
print(" Restored active to true")
// Check if it's actually false
let isStillActive = posedActive.isActive
print(" isActive after setting to false: \(isStillActive)")
// Now test the Update protocol
let updateProtocol = bone as Update
print(" Successfully cast Bone to Update protocol")
// Restore it
posedActive.active = true
print(" Restored active to true")
// Call update with required parameters
print(" Calling update() through Update protocol...")
updateProtocol.update(drawable.skeleton, Physics.none)
print(" ✓ update() call succeeded through Update protocol")
// Now test the Update protocol
let updateProtocol = bone as Update
print(" Successfully cast Bone to Update protocol")
// Test that we can still use Bone methods after casting
let appliedPose = bone.appliedPose
print(" Bone appliedPose still accessible: x=\(appliedPose.x), y=\(appliedPose.y)")
// Call update with required parameters
print(" Calling update() through Update protocol...")
updateProtocol.update(drawable.skeleton, Physics.none)
print(" ✓ update() call succeeded through Update protocol")
// Test that we can still use Bone methods after casting
let appliedPose = bone.appliedPose
print(" Bone appliedPose still accessible: x=\(appliedPose.x), y=\(appliedPose.y)")
// The fact that this all works suggests the pointer is being handled correctly
// even though we're not using cast functions in the constructor chain
print(" ✓ All PosedActive and Update methods work correctly on Bone instance")
} else {
print(" Could not find bone 'rear-shin'")
}
// The fact that this all works suggests the pointer is being handled correctly
// even though we're not using cast functions in the constructor chain
print(" ✓ All PosedActive and Update methods work correctly on Bone instance")
} else {
print(" Could not find bone 'rear-shin'")
}
// Clear listener before cleanup
// drawable.animationState.setListener(nil)