<commit_before>//------------------------------------------------------------------------------
//  spine-sapp.c
//  Simple sokol_spine.h sample
//------------------------------------------------------------------------------
#include "sokol_app.h"
#include "sokol_gfx.h"
#include "sokol_fetch.h"
#include "sokol_glue.h"
#include "util/fileutil.h"
#define SOKOL_SPINE_IMPL
#include "spine/spine.h"
#include "sokol_spine.h"
#include "stb/stb_image.h"
#include "dbgui/dbgui.h"
#define HANDMADE_MATH_IMPLEMENTATION
#define HANDMADE_MATH_NO_SSE
#include "HandmadeMath.h"

static struct {
    sspine_atlas atlas;
    sspine_skeleton skeleton;
    sspine_instance instance;
    sg_pass_action pass_action;
    struct {
        bool failed;
        int load_count;
        size_t atlas_data_size;
    } load_status;
    struct {
        uint8_t atlas[8 * 1024];
        uint8_t skeleton[256 * 1024];
        uint8_t image[256 * 1024];
    } buffers;
} state;

// sokol-fetch callback functions
static void setup_spine_objects(void);
static void atlas_loaded(const sfetch_response_t* response);
static void skeleton_loaded(const sfetch_response_t* response);
static void image_loaded(const sfetch_response_t* response);
static sspine_mat4 compute_transform(void);

static void init(void) {
    sg_setup(&(sg_desc){ .context = sapp_sgcontext() });
    __dbgui_setup(sapp_sample_count());

    // setup sokol-fetch for loading up to 2 files in parallel
    sfetch_setup(&(sfetch_desc_t){
        .max_requests = 3,
        .num_channels = 2,
        .num_lanes = 1,
    });

    // setup sokol-spine with default attributes
    sspine_setup(&(sspine_desc){0});

    state.pass_action = (sg_pass_action){
        .colors[0] = { .action = SG_ACTION_CLEAR, .value = { 0.0f, 0.5f, 0.7f, 1.0f} }
    };

    char path_buf[512];
    sfetch_send(&(sfetch_request_t){
        .path = fileutil_get_path("spineboy.atlas", path_buf, sizeof(path_buf)),
        .channel = 0,
        .buffer_ptr = state.buffers.atlas,
        .buffer_size = sizeof(state.buffers.atlas),
        .callback = atlas_loaded,
    });
    sfetch_send(&(sfetch_request_t){
        .path = fileutil_get_path("spineboy-pro.json", path_buf, sizeof(path_buf)),
        .channel = 1,
        .buffer_ptr = state.buffers.skeleton,
        // the skeleton file is text data, make sure we have room for a terminating zero
        .buffer_size = sizeof(state.buffers.skeleton) - 1,
        .callback = skeleton_loaded,
    });
}

static void frame(void) {
    sfetch_dowork();

    sspine_set_transform(compute_transform());
    sspine_draw_instance(state.instance);

    sg_begin_default_pass(&state.pass_action, sapp_width(), sapp_height());
    sspine_draw_frame();
    __dbgui_draw();
    sg_end_pass();
    sg_commit();
}

static void input(const sapp_event* ev) {
    __dbgui_event(ev);
}

static void cleanup(void) {
    __dbgui_shutdown();
    sspine_shutdown();
    sfetch_shutdown();
    sg_shutdown();
}

sapp_desc sokol_main(int argc, char* argv[]) {
    (void)argc; (void)argv;
    return (sapp_desc){
        .init_cb = init,
        .frame_cb = frame,
        .cleanup_cb = cleanup,
        .event_cb = input,
        .width = 800,
        .height = 600,
        .sample_count = 4,
        .window_title = "spine-sapp.c",
        .icon.sokol_default = true,
    };
}

sspine_mat4 compute_transform(void) {
    const float wh = sapp_widthf() * 0.5f;
    const float hh = sapp_heightf() * 0.5f;
    hmm_mat4 ortho = HMM_Orthographic(-wh, wh, -hh, hh, -1.0f, 1.0f);
    return *(sspine_mat4*)&ortho;
}

// called by sokol-fetch when atlas file has been loaded
static void atlas_loaded(const sfetch_response_t* response) {
    if (response->fetched) {
        state.load_status.atlas_data_size = response->fetched_size;
        // if both the atlas and skeleton file had been loaded, create
        // the atlas and skeleton spine objects
        if (++state.load_status.load_count == 2) {
            setup_spine_objects();
        }
    }
    else if (response->failed) {<commit_msg>spine-sapp.c: fix ortho matrix Y down<commit_after>//------------------------------------------------------------------------------
//  spine-sapp.c
//  Simple sokol_spine.h sample
//------------------------------------------------------------------------------
#include "sokol_app.h"
#include "sokol_gfx.h"
#include "sokol_fetch.h"
#include "sokol_glue.h"
#include "util/fileutil.h"
#define SOKOL_SPINE_IMPL
#include "spine/spine.h"
#include "sokol_spine.h"
#include "stb/stb_image.h"
#include "dbgui/dbgui.h"
#define HANDMADE_MATH_IMPLEMENTATION
#define HANDMADE_MATH_NO_SSE
#include "HandmadeMath.h"

static struct {
    sspine_atlas atlas;
    sspine_skeleton skeleton;
    sspine_instance instance;
    sg_pass_action pass_action;
    struct {
        bool failed;
        int load_count;
        size_t atlas_data_size;
    } load_status;
    struct {
        uint8_t atlas[8 * 1024];
        uint8_t skeleton[256 * 1024];
        uint8_t image[256 * 1024];
    } buffers;
} state;

// sokol-fetch callback functions
static void setup_spine_objects(void);
static void atlas_loaded(const sfetch_response_t* response);
static void skeleton_loaded(const sfetch_response_t* response);
static void image_loaded(const sfetch_response_t* response);
static sspine_mat4 compute_transform(void);

static void init(void) {
    sg_setup(&(sg_desc){ .context = sapp_sgcontext() });
    __dbgui_setup(sapp_sample_count());

    // setup sokol-fetch for loading up to 2 files in parallel
    sfetch_setup(&(sfetch_desc_t){
        .max_requests = 3,
        .num_channels = 2,
        .num_lanes = 1,
    });

    // setup sokol-spine with default attributes
    sspine_setup(&(sspine_desc){0});

    state.pass_action = (sg_pass_action){
        .colors[0] = { .action = SG_ACTION_CLEAR, .value = { 0.0f, 0.5f, 0.7f, 1.0f} }
    };

    char path_buf[512];
    sfetch_send(&(sfetch_request_t){
        .path = fileutil_get_path("spineboy.atlas", path_buf, sizeof(path_buf)),
        .channel = 0,
        .buffer_ptr = state.buffers.atlas,
        .buffer_size = sizeof(state.buffers.atlas),
        .callback = atlas_loaded,
    });
    sfetch_send(&(sfetch_request_t){
        .path = fileutil_get_path("spineboy-pro.json", path_buf, sizeof(path_buf)),
        .channel = 1,
        .buffer_ptr = state.buffers.skeleton,
        // the skeleton file is text data, make sure we have room for a terminating zero
        .buffer_size = sizeof(state.buffers.skeleton) - 1,
        .callback = skeleton_loaded,
    });
}

static void frame(void) {
    sfetch_dowork();

    sspine_set_transform(compute_transform());
    sspine_draw_instance(state.instance);

    sg_begin_default_pass(&state.pass_action, sapp_width(), sapp_height());
    sspine_draw_frame();
    __dbgui_draw();
    sg_end_pass();
    sg_commit();
}

static void input(const sapp_event* ev) {
    __dbgui_event(ev);
}

static void cleanup(void) {
    __dbgui_shutdown();
    sspine_shutdown();
    sfetch_shutdown();
    sg_shutdown();
}

sapp_desc sokol_main(int argc, char* argv[]) {
    (void)argc; (void)argv;
    return (sapp_desc){
        .init_cb = init,
        .frame_cb = frame,
        .cleanup_cb = cleanup,
        .event_cb = input,
        .width = 800,
        .height = 600,
        .sample_count = 4,
        .window_title = "spine-sapp.c",
        .icon.sokol_default = true,
    };
}

sspine_mat4 compute_transform(void) {
    const float wh = sapp_widthf() * 0.5f;
    const float hh = sapp_heightf() * 0.5f;
    hmm_mat4 ortho = HMM_Orthographic(-wh, wh, hh, -hh, -1.0f, 1.0f);
    return *(sspine_mat4*)&ortho;
}

// called by sokol-fetch when atlas file has been loaded
static void atlas_loaded(const sfetch_response_t* response) {
    if (response->fetched) {
        state.load_status.atlas_data_size = response->fetched_size;
        // if both the atlas and skeleton file had been loaded, create
        // the atlas and skeleton spine objects
        if (++state.load_status.load_count == 2) {
            setup_spine_objects();
        }
    }
    else if (response->failed) {
{'fraction_non_alphanumeric': 0.15358993338267948, 'fraction_numerical': 0.015297310634098199, 'mean_word_length': 2.6191964285714286, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4847270', 'n_tokens_mistral': 2932, 'n_tokens_neox': 2785, 'n_words': 577}