diff --git a/include/gfx/font.h b/include/gfx/font.h index 1663846..65ab5af 100644 --- a/include/gfx/font.h +++ b/include/gfx/font.h @@ -140,8 +140,6 @@ float gfx_size_text(struct text_style *ts, const char *text); float gfx_get_actual_font_size(unsigned face, float size); float gfx_get_actual_font_size_round_down(unsigned face, float size); -void gfx_print_text_style(struct text_style *style, int indent); - static inline float text_style_width(struct text_style *ts, const char *ch) { return (gfx_size_char(ts, ch) + (ts->bold_width * 2) + ts->edge_left + ts->edge_right) diff --git a/include/gfx/gfx.h b/include/gfx/gfx.h index 51b4041..fa0a5cf 100644 --- a/include/gfx/gfx.h +++ b/include/gfx/gfx.h @@ -164,10 +164,4 @@ void gfx_draw_glyph(Texture *dst, float dx, int dy, Texture *glyph, SDL_Color co void gfx_draw_glyph_to_pmap(Texture *dst, float dx, int dy, Texture *glyph, Rectangle glyph_pos, SDL_Color color, float scale_x); void gfx_draw_glyph_to_amap(Texture *dst, float dx, int dy, Texture *glyph, Rectangle glyph_pos, float scale_x); -// debug printing -void gfx_print_color(SDL_Color *c); -void gfx_print_rectangle(Rectangle *r); -void gfx_print_point(Point *p); -void gfx_print_texture(struct texture *t, int indent); - #endif /* SYSTEM4_SDL_CORE_H */ diff --git a/include/json.h b/include/json.h new file mode 100644 index 0000000..0fc38f3 --- /dev/null +++ b/include/json.h @@ -0,0 +1,89 @@ +/* Copyright (C) 2023 Nunuhara Cabbage + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef XSYSTEM4_JSON_H +#define XSYSTEM4_JSON_H + +#include +#include "gfx/types.h" + +typedef struct cJSON cJSON; +struct texture; +struct text_style; +struct sact_sprite; +struct sprite; + +cJSON *num2_to_json(double a, double b); +cJSON *num2_to_json_object(const char *a_name, double a, const char *b_name, double b); +cJSON *num3_to_json(double a, double b, double c); +cJSON *num3_to_json_object(const char *a_name, double a, const char *b_name, double b, + const char *c_name, double c); +cJSON *num4_to_json(double a, double b, double c, double d); +cJSON *num4_to_json_object(const char *a_name, double a, const char *b_name, double b, + const char *c_name, double c, const char *d_name, double d); +cJSON *texture_to_json(struct texture *t, bool verbose); +cJSON *text_style_to_json(struct text_style *ts, bool verbose); +cJSON *scene_sprite_to_json(struct sprite *sp, bool verbose); +cJSON *sprite_to_json(struct sact_sprite *sp, bool verbose); + +static inline cJSON *xy_to_json(double x, double y, bool verbose) +{ + if (!verbose) + return num2_to_json(x, y); + return num2_to_json_object("x", x, "y", y); +} + +static inline cJSON *wh_to_json(double w, double h, bool verbose) +{ + if (!verbose) + return num2_to_json(w, h); + return num2_to_json_object("w", w, "h", h); +} + +static inline cJSON *point_to_json(Point *p, bool verbose) +{ + return xy_to_json(p->x, p->y, verbose); +} + +static inline cJSON *rectangle_to_json(Rectangle *r, bool verbose) +{ + if (!verbose) + return num4_to_json(r->x, r->y, r->w, r->h); + return num4_to_json_object("x", r->x, "y", r->y, "w", r->w, "h", r->h); +} + +static inline cJSON *color_to_json(Color *c, bool verbose) +{ + if (!verbose) + return num4_to_json(c->r, c->g, c->b, c->a); + return num4_to_json_object("r", c->r, "g", c->g, "b", c->b, "a", c->a); +} + +static inline cJSON *vec3_point_to_json(vec3 v, bool verbose) +{ + if (!verbose) + return num3_to_json(v[0], v[1], v[2]); + return num3_to_json_object("x", v[0], "y", v[1], "z", v[2]); +} + +static inline cJSON *vec3_color_to_json(vec3 v, bool verbose) +{ + if (!verbose) + return num3_to_json(v[0], v[1], v[2]); + return num3_to_json_object("r", v[0], "g", v[1], "b", v[2]); +} + +#endif diff --git a/include/plugin.h b/include/plugin.h index 122aa2c..310f353 100644 --- a/include/plugin.h +++ b/include/plugin.h @@ -17,12 +17,15 @@ #ifndef SYSTEM4_PLUGIN_H #define SYSTEM4_PLUGIN_H +#include + +typedef struct cJSON cJSON; struct sact_sprite; struct draw_plugin { const char *name; void (*update)(struct sact_sprite *); - void (*debug_print)(struct sact_sprite *, int indent); + cJSON *(*to_json)(struct sact_sprite *, bool); }; #endif /* SYSTEM4_PLUGIN_H */ diff --git a/include/reign.h b/include/reign.h index a98e1f2..27edd76 100644 --- a/include/reign.h +++ b/include/reign.h @@ -25,6 +25,7 @@ #include "gfx/gfx.h" #include "plugin.h" +typedef struct cJSON cJSON; struct hash_table; enum RE_instance_type { @@ -270,6 +271,6 @@ bool RE_back_cg_set(struct RE_back_cg *bcg, int no); bool RE_back_cg_set_name(struct RE_back_cg *bcg, struct string *name, struct archive *aar); void RE_render(struct sact_sprite *sp); -void RE_debug_print(struct sact_sprite *sp, int indent); +cJSON *RE_to_json(struct sact_sprite *sp, bool verbose); #endif /* SYSTEM4_REIGN_H */ diff --git a/include/scene.h b/include/scene.h index 2519ee9..b202c06 100644 --- a/include/scene.h +++ b/include/scene.h @@ -20,6 +20,7 @@ #include #include "queue.h" +typedef struct cJSON cJSON; struct texture; struct sprite { @@ -40,7 +41,7 @@ struct sprite { // The rendering function. void (*render)(struct sprite*); // Debug printing function - void (*debug_print)(struct sprite*); + cJSON *(*to_json)(struct sprite*, bool); }; extern bool scene_is_dirty; diff --git a/include/sprite.h b/include/sprite.h index fdfa3c2..0ea31b6 100644 --- a/include/sprite.h +++ b/include/sprite.h @@ -133,6 +133,4 @@ void sprite_get_pixel_value(struct sact_sprite *sp, int x, int y, int *r, int *g void sprite_bind_plugin(struct sact_sprite *sp, struct draw_plugin *plugin); void sprite_call_plugins(void); -void sprite_print(struct sact_sprite *sp); - #endif /* SYSTEM4_SPRITE_H */ diff --git a/src/3d/debug.c b/src/3d/debug.c index 5958373..620bbc7 100644 --- a/src/3d/debug.c +++ b/src/3d/debug.c @@ -17,6 +17,8 @@ #include "system4/string.h" #include "3d_internal.h" +#include "cJSON.h" +#include "json.h" #include "reign.h" #include "sprite.h" #include "xsystem4.h" @@ -57,107 +59,141 @@ static const char *fog_type_name(enum RE_fog_type type) return "UNKNOWN"; } -static void print_motion(const char *name, struct motion *m, int indent) +static cJSON *motion_to_json(struct motion *m) { if (m->instance->type == RE_ITYPE_BILLBOARD) { - indent_message(indent, "%s = {state=%s, frame=%f, range=(%d,%d), loop_range=(%d,%d)},\n", - name, motion_state_name(m->state), m->current_frame, - (int)m->frame_begin, (int)m->frame_end, (int)m->loop_frame_begin, (int)m->loop_frame_end); - } else if (m->mot) { - indent_message(indent, "%s = {name=\"%s\", state=%s, frame=%f},\n", - name, m->mot->name, motion_state_name(m->state), m->current_frame); + cJSON *obj = cJSON_CreateObject(); + cJSON_AddStringToObject(obj, "state", motion_state_name(m->state)); + cJSON_AddNumberToObject(obj, "frame", m->current_frame); + cJSON_AddItemToObjectCS(obj, "range", num2_to_json(m->frame_begin, m->frame_end)); + cJSON_AddItemToObjectCS(obj, "loop_range", num2_to_json(m->loop_frame_begin, m->loop_frame_end)); + return obj; } + if (m->mot) { + cJSON *obj = cJSON_CreateObject(); + cJSON_AddStringToObject(obj, "name", m->mot->name); + cJSON_AddStringToObject(obj, "state", motion_state_name(m->state)); + cJSON_AddNumberToObject(obj, "frame", m->current_frame); + return obj; + } + return cJSON_CreateNull(); } -static void print_instance(struct RE_instance *inst, int index, int indent) +static cJSON *instance_to_json(struct RE_instance *inst, int index, bool verbose) { - if (!inst) - return; - indent_message(indent, "instance[%d] = {\n", index); - indent++; - - indent_message(indent, "type = %s,\n", instance_type_name(inst->type)); + cJSON *obj = cJSON_CreateObject(); + cJSON_AddNumberToObject(obj, "index", index); + cJSON_AddStringToObject(obj, "type", instance_type_name(inst->type)); if (inst->type == RE_ITYPE_DIRECTIONAL_LIGHT || inst->type == RE_ITYPE_SPECULAR_LIGHT) { - indent_message(indent, "vec = {x=%f, y=%f, z=%f},\n", SPREAD_VEC3(inst->vec)); - indent_message(indent, "diffuse = {r=%f, g=%f, b=%f},\n", SPREAD_VEC3(inst->diffuse)); - indent_message(indent, "globe_diffuse = {r=%f, g=%f, b=%f},\n", SPREAD_VEC3(inst->globe_diffuse)); + cJSON_AddItemToObjectCS(obj, "vec", vec3_point_to_json(inst->vec, verbose)); + cJSON_AddItemToObjectCS(obj, "diffuse", vec3_color_to_json(inst->diffuse, verbose)); + cJSON_AddItemToObjectCS(obj, "globe_diffuse", vec3_color_to_json(inst->globe_diffuse, verbose)); } else { - indent_message(indent, "draw = %d,\n", inst->draw); - indent_message(indent, "pos = {x=%f, y=%f, z=%f},\n", SPREAD_VEC3(inst->pos)); - indent_message(indent, "scale = {x=%f, y=%f, z=%f},\n", SPREAD_VEC3(inst->scale)); - indent_message(indent, "ambient = {r=%f, g=%f, b=%f},\n", SPREAD_VEC3(inst->ambient)); + cJSON_AddNumberToObject(obj, "draw", inst->draw); + cJSON_AddItemToObjectCS(obj, "pos", vec3_point_to_json(inst->pos, verbose)); + cJSON_AddItemToObjectCS(obj, "scale", vec3_point_to_json(inst->scale, verbose)); + cJSON_AddItemToObjectCS(obj, "ambient", vec3_color_to_json(inst->ambient, verbose)); } if (inst->model) { - indent_message(indent, "path = \"%s\",\n", inst->model->path); - indent_message(indent, "aabb = {min = {x=%f, y=%f, z=%f}, max = {x=%f, y=%f, z=%f}},\n", - SPREAD_VEC3(inst->model->aabb[0]), SPREAD_VEC3(inst->model->aabb[1])); + cJSON *tmp; + cJSON_AddStringToObject(obj, "path", inst->model->path); + cJSON_AddItemToObjectCS(obj, "aabb", tmp = cJSON_CreateObject()); + cJSON_AddItemToObjectCS(tmp, "min", vec3_point_to_json(inst->model->aabb[0], verbose)); + cJSON_AddItemToObjectCS(tmp, "max", vec3_point_to_json(inst->model->aabb[1], verbose)); } if (inst->motion) { - indent_message(indent, "fps = %f,\n", inst->fps); - print_motion("motion", inst->motion, indent); + cJSON_AddNumberToObject(obj, "fps", inst->fps); + cJSON_AddItemToObjectCS(obj, "motion", motion_to_json(inst->motion)); + } + if (inst->next_motion) { + cJSON_AddItemToObjectCS(obj, "next_motion", motion_to_json(inst->next_motion)); + } + if (inst->motion_blend) { + cJSON_AddNumberToObject(obj, "motion_blend_rate", inst->motion_blend_rate); + } + if (inst->effect) { + cJSON_AddStringToObject(obj, "path", inst->effect->pae->path); } - if (inst->next_motion) - print_motion("next_motion", inst->next_motion, indent); - if (inst->motion_blend) - indent_message(indent, "motion_blend_rate = %f,\n", inst->motion_blend_rate); - if (inst->effect) - indent_message(indent, "path = \"%s\",\n", inst->effect->pae->path); - indent--; - indent_message(indent, "},\n"); + return obj; } -static void print_back_cg(struct RE_back_cg *bcg, int index, int indent) +static cJSON *back_cg_to_json(struct RE_back_cg *bcg, int index, bool verbose) { - if (!bcg->name && !bcg->no) - return; - indent_message(indent, "backCG[%d] = {\n", index); - indent++; - - if (bcg->no) - indent_message(indent, "no = %d,\n", bcg->no); - if (bcg->name) - indent_message(indent, "name = \"%s\",\n", bcg->name ? bcg->name->text : ""); - indent_message(indent, "pos = {x=%f, y=%f},\n", bcg->x, bcg->y); - indent_message(indent, "blend_rate = %f,\n", bcg->blend_rate); - indent_message(indent, "mag = %f,\n", bcg->mag); - indent_message(indent, "show = %d,\n", bcg->show); - - indent--; - indent_message(indent, "},\n"); + cJSON *obj = cJSON_CreateObject(); + cJSON_AddNumberToObject(obj, "index", index); + if (bcg->no) { + cJSON_AddNumberToObject(obj, "no", bcg->no); + } + if (bcg->name) { + cJSON_AddStringToObject(obj, "name", bcg->name->text); + } + if (!verbose) { + cJSON_AddItemToObjectCS(obj, "pos", num2_to_json(bcg->x, bcg->y)); + } else { + cJSON *pos; + cJSON_AddItemToObjectCS(obj, "pos", pos = cJSON_CreateObject()); + cJSON_AddNumberToObject(pos, "x", bcg->x); + cJSON_AddNumberToObject(pos, "y", bcg->y); + } + cJSON_AddNumberToObject(obj, "blend_rate", bcg->blend_rate); + cJSON_AddNumberToObject(obj, "mag", bcg->mag); + cJSON_AddNumberToObject(obj, "show", bcg->show); + return obj; } -void RE_debug_print(struct sact_sprite *sp, int indent) +cJSON *RE_to_json(struct sact_sprite *sp, bool verbose) { - struct RE_plugin *p = (struct RE_plugin *)sp->plugin; + struct RE_plugin *p = (struct RE_plugin*)sp->plugin; + cJSON *obj, *cam, *a; - indent_message(indent, "name = \"%s\",\n", p->plugin.name); - indent_message(indent, "camera = {x=%f, y=%f, z=%f, pitch=%f, roll=%f, yaw=%f},\n", - SPREAD_VEC3(p->camera.pos), p->camera.pitch, p->camera.roll, p->camera.yaw); - indent_message(indent, "shadow_map_light_dir = {x=%f, y=%f, z=%f},\n", SPREAD_VEC3(p->shadow_map_light_dir)); - indent_message(indent, "shadow_bias = %f,\n", p->shadow_bias); - - indent_message(indent, "fog_type = %s,\n", fog_type_name(p->fog_type)); + obj = cJSON_CreateObject(); + cJSON_AddStringToObject(obj, "name", p->plugin.name); + cJSON_AddItemToObjectCS(obj, "camera", cam = cJSON_CreateObject()); + cJSON_AddItemToObjectCS(cam, "pos", vec3_point_to_json(p->camera.pos, verbose)); + cJSON_AddNumberToObject(cam, "pitch", p->camera.pitch); + cJSON_AddNumberToObject(cam, "roll", p->camera.roll); + cJSON_AddNumberToObject(cam, "yaw", p->camera.yaw); + cJSON_AddItemToObjectCS(obj, "shadow_map_light_dir", + vec3_point_to_json(p->shadow_map_light_dir, verbose)); + cJSON_AddNumberToObject(obj, "shadow_bias", p->shadow_bias); + cJSON_AddStringToObject(obj, "fog_type", fog_type_name(p->fog_type)); switch (p->fog_type) { case RE_FOG_NONE: break; case RE_FOG_LINEAR: - indent_message(indent, "fog_near = %f, fog_far = %f,\n", p->fog_near, p->fog_far); - indent_message(indent, "fog_color = {r=%f, g=%f, b=%f},\n", SPREAD_VEC3(p->fog_color)); + cJSON_AddNumberToObject(obj, "fog_near", p->fog_near); + cJSON_AddNumberToObject(obj, "fog_far", p->fog_far); break; case RE_FOG_LIGHT_SCATTERING: - indent_message(indent, "ls_beta_r = %f, ls_beta_m = %f,\n", p->ls_beta_r, p->ls_beta_m); - indent_message(indent, "ls_g = %f,\n", p->ls_g); - indent_message(indent, "ls_distance = %f,\n", p->ls_distance); - indent_message(indent, "ls_light_dir = {x=%f, y=%f, z=%f},\n", SPREAD_VEC3(p->ls_light_dir)); - indent_message(indent, "ls_light_color = {r=%f, g=%f, b=%f},\n", SPREAD_VEC3(p->ls_light_color)); - indent_message(indent, "ls_sun_color = {r=%f, g=%f, b=%f},\n", SPREAD_VEC3(p->ls_sun_color)); + cJSON_AddNumberToObject(obj, "ls_beta_r", p->ls_beta_r); + cJSON_AddNumberToObject(obj, "ls_beta_m", p->ls_beta_m); + cJSON_AddNumberToObject(obj, "ls_g", p->ls_g); + cJSON_AddNumberToObject(obj, "ls_distance", p->ls_distance); + cJSON_AddItemToObjectCS(obj, "ls_light_dir", + vec3_point_to_json(p->ls_light_dir, verbose)); + cJSON_AddItemToObjectCS(obj, "ls_light_color", + vec3_color_to_json(p->ls_light_color, verbose)); + cJSON_AddItemToObjectCS(obj, "ls_sun_color", + vec3_color_to_json(p->ls_sun_color, verbose)); break; } - for (int i = 0; i < p->nr_instances; i++) - print_instance(p->instances[i], i, indent); + cJSON_AddItemToObjectCS(obj, "instances", a = cJSON_CreateArray()); + for (int i = 0; i < p->nr_instances; i++) { + if (!p->instances[i]) + continue; + cJSON_AddItemToArray(a, instance_to_json(p->instances[i], i, verbose)); + + } - for (int i = 0; i < RE_NR_BACK_CGS; i++) - print_back_cg(&p->back_cg[i], i, indent); + cJSON_AddItemToObjectCS(obj, "back_cgs", a = cJSON_CreateArray()); + for (int i = 0; i < RE_NR_BACK_CGS; i++) { + struct RE_back_cg *bcg = &p->back_cg[i]; + if (!bcg->name && !bcg->no) + continue; + cJSON_AddItemToArray(a, back_cg_to_json(bcg, i, verbose)); + } + + return obj; } diff --git a/src/3d/reign.c b/src/3d/reign.c index ac56605..413deff 100644 --- a/src/3d/reign.c +++ b/src/3d/reign.c @@ -216,7 +216,7 @@ struct RE_plugin *RE_plugin_new(void) struct RE_plugin *plugin = xcalloc(1, sizeof(struct RE_plugin)); plugin->plugin.name = "ReignEngine"; plugin->plugin.update = RE_render; - plugin->plugin.debug_print = RE_debug_print; + plugin->plugin.to_json = RE_to_json; plugin->nr_instances = 16; plugin->instances = xcalloc(plugin->nr_instances, sizeof(struct RE_instance *)); plugin->aar = aar; diff --git a/src/debugger_dap.c b/src/debugger_dap.c index 5c1433f..b4fd811 100644 --- a/src/debugger_dap.c +++ b/src/debugger_dap.c @@ -77,7 +77,7 @@ static void send_response(cJSON *response, bool success) send_json(response); } -static void emit_event(const char *name, struct cJSON *body) +static void emit_event(const char *name, cJSON *body) { cJSON *event = cJSON_CreateObject(); cJSON_AddStringToObject(event, "type", "event"); diff --git a/src/dungeon/dungeon.c b/src/dungeon/dungeon.c index 68ec3e7..2652c6a 100644 --- a/src/dungeon/dungeon.c +++ b/src/dungeon/dungeon.c @@ -35,6 +35,8 @@ #include "dungeon/renderer.h" #include "dungeon/tes.h" #include "gfx/gfx.h" +#include "cJSON.h" +#include "json.h" #include "sact.h" #include "sprite.h" #include "vm.h" @@ -46,14 +48,14 @@ #endif static void dungeon_render(struct sact_sprite *sp); -static void dungeon_debug_print(struct sact_sprite *sp, int indent); +static cJSON *dungeon_to_json(struct sact_sprite *sp, bool verbose); struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version, int surface) { struct dungeon_context *ctx = xcalloc(1, sizeof(struct dungeon_context)); ctx->plugin.name = "DrawDungeon"; ctx->plugin.update = dungeon_render; - ctx->plugin.debug_print = dungeon_debug_print; + ctx->plugin.to_json = dungeon_to_json; ctx->version = version; ctx->surface = surface; struct sact_sprite *sp = sact_get_sprite(ctx->surface); @@ -451,12 +453,16 @@ bool dungeon_save_walk_data(int surface, int map, struct page **page) return true; } -#define SPREAD_VEC3(v) (v)[0], (v)[1], (v)[2] - -void dungeon_debug_print(struct sact_sprite *sp, int indent) +static cJSON *dungeon_to_json(struct sact_sprite *sp, bool verbose) { + cJSON *obj, *cam; struct dungeon_context *ctx = (struct dungeon_context *)sp->plugin; + obj = cJSON_CreateObject(); + cJSON_AddStringToObject(obj, "name", ctx->plugin.name); + cJSON_AddItemToObjectCS(obj, "camera", cam = cJSON_CreateObject()); + cJSON_AddItemToObjectCS(cam, "pos", vec3_point_to_json(ctx->camera.pos, verbose)); + cJSON_AddNumberToObject(cam, "angle", ctx->camera.angle); + cJSON_AddNumberToObject(cam, "angle_p", ctx->camera.angle_p); - indent_message(indent, "name = \"%s\",\n", ctx->plugin.name); - indent_message(indent, "camera = {x=%f, y=%f, z=%f, angle=%f, angle_p=%f},\n", SPREAD_VEC3(ctx->camera.pos), ctx->camera.angle, ctx->camera.angle_p); + return obj; } diff --git a/src/json.c b/src/json.c new file mode 100644 index 0000000..b472c35 --- /dev/null +++ b/src/json.c @@ -0,0 +1,198 @@ +/* Copyright (C) 2023 Nunuhara Cabbage + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include + +#include "cJSON.h" +#include "json.h" +#include "gfx/gfx.h" +#include "gfx/font.h" +#include "plugin.h" +#include "scene.h" +#include "sprite.h" + +cJSON *num2_to_json(double a, double b) +{ + cJSON *ar = cJSON_CreateArray(); + cJSON_AddItemToArray(ar, cJSON_CreateNumber(a)); + cJSON_AddItemToArray(ar, cJSON_CreateNumber(b)); + return ar; +} + +cJSON *num2_to_json_object(const char *a_name, double a, const char *b_name, double b) +{ + cJSON *obj = cJSON_CreateObject(); + cJSON_AddNumberToObject(obj, a_name, a); + cJSON_AddNumberToObject(obj, b_name, b); + return obj; +} + +cJSON *num3_to_json(double a, double b, double c) +{ + cJSON *ar = cJSON_CreateArray(); + cJSON_AddItemToArray(ar, cJSON_CreateNumber(a)); + cJSON_AddItemToArray(ar, cJSON_CreateNumber(b)); + cJSON_AddItemToArray(ar, cJSON_CreateNumber(c)); + return ar; +} + +cJSON *num3_to_json_object(const char *a_name, double a, const char *b_name, double b, + const char *c_name, double c) +{ + cJSON *obj = cJSON_CreateObject(); + cJSON_AddNumberToObject(obj, a_name, a); + cJSON_AddNumberToObject(obj, b_name, b); + cJSON_AddNumberToObject(obj, c_name, c); + return obj; +} + +cJSON *num4_to_json(double a, double b, double c, double d) +{ + cJSON *ar = cJSON_CreateArray(); + cJSON_AddItemToArray(ar, cJSON_CreateNumber(a)); + cJSON_AddItemToArray(ar, cJSON_CreateNumber(b)); + cJSON_AddItemToArray(ar, cJSON_CreateNumber(c)); + cJSON_AddItemToArray(ar, cJSON_CreateNumber(d)); + return ar; +} + +cJSON *num4_to_json_object(const char *a_name, double a, const char *b_name, double b, + const char *c_name, double c, const char *d_name, double d) +{ + cJSON *obj = cJSON_CreateObject(); + cJSON_AddNumberToObject(obj, a_name, a); + cJSON_AddNumberToObject(obj, b_name, b); + cJSON_AddNumberToObject(obj, c_name, c); + cJSON_AddNumberToObject(obj, d_name, d); + return obj; +} + +cJSON *texture_to_json(struct texture *t, bool verbose) +{ + if (!t->handle) + return cJSON_CreateNull(); + + cJSON *obj = cJSON_CreateObject(); + if (!verbose) { + cJSON_AddItemToObjectCS(obj, "size", num2_to_json(t->w, t->h)); + } else { + cJSON *size; + cJSON_AddItemToObjectCS(obj, "size", size = cJSON_CreateObject()); + cJSON_AddNumberToObject(size, "w", t->w); + cJSON_AddNumberToObject(size, "h", t->h); + } + cJSON_AddBoolToObject(obj, "has_alpha", t->has_alpha); + return obj; +} + +cJSON *text_style_to_json(struct text_style *ts, bool verbose) +{ + cJSON *obj; + obj = cJSON_CreateObject(); + cJSON_AddNumberToObject(obj, "face", ts->face); + cJSON_AddNumberToObject(obj, "size", ts->size); + cJSON_AddNumberToObject(obj, "bold_width", ts->bold_width); + cJSON_AddNumberToObject(obj, "weight", ts->weight); + cJSON_AddNumberToObject(obj, "edge_left", ts->edge_left); + cJSON_AddNumberToObject(obj, "edge_up", ts->edge_up); + cJSON_AddNumberToObject(obj, "edge_right", ts->edge_right); + cJSON_AddNumberToObject(obj, "edge_down", ts->edge_down); + cJSON_AddItemToObjectCS(obj, "color", color_to_json(&ts->color, verbose)); + cJSON_AddItemToObjectCS(obj, "edge_color", color_to_json(&ts->edge_color, verbose)); + cJSON_AddNumberToObject(obj, "scale_x", ts->scale_x); + cJSON_AddNumberToObject(obj, "space_scale_x", ts->space_scale_x); + cJSON_AddNumberToObject(obj, "font_spacing", ts->font_spacing); + return obj; +} + +cJSON *scene_sprite_to_json(struct sprite *sp, bool verbose) +{ + cJSON *obj = cJSON_CreateObject(); + cJSON_AddNumberToObject(obj, "z", sp->z); + cJSON_AddNumberToObject(obj, "z2", sp->z2); + cJSON_AddBoolToObject(obj, "has_pixel", sp->has_pixel); + cJSON_AddBoolToObject(obj, "has_alpha", sp->has_alpha); + cJSON_AddBoolToObject(obj, "hidden", sp->hidden); + cJSON_AddBoolToObject(obj, "in_scene", sp->in_scene); + return obj; +} + +static cJSON *draw_plugin_to_json(struct sact_sprite *sp, bool verbose) +{ + if (!sp->plugin) + return cJSON_CreateNull(); + if (sp->plugin->to_json) + return sp->plugin->to_json(sp, verbose); + cJSON *obj = cJSON_CreateObject(); + cJSON_AddStringToObject(obj, "name", sp->plugin->name); + return obj; +} + +static const char *draw_method_string(int draw_method) +{ + switch (draw_method) { + case DRAW_METHOD_NORMAL: return "normal"; + case DRAW_METHOD_SCREEN: return "screen"; + case DRAW_METHOD_MULTIPLY: return "multiply"; + case DRAW_METHOD_ADDITIVE: return "additive"; + default: return "unknown"; + } +} + +cJSON *sprite_to_json(struct sact_sprite *sp, bool verbose) +{ + cJSON *obj, *sprite; + + obj = cJSON_CreateObject(); + cJSON_AddItemToObjectCS (obj, "sprite", sprite = cJSON_CreateObject()); + cJSON_AddNumberToObject(sprite, "no", sp->no); + cJSON_AddNumberToObject(sprite, "z", sp->sp.z); + cJSON_AddNumberToObject(sprite, "z2", sp->sp.z2); + cJSON_AddBoolToObject(sprite, "has_pixel", sp->sp.has_pixel); + cJSON_AddBoolToObject(sprite, "has_alpha", sp->sp.has_alpha); + cJSON_AddBoolToObject(sprite, "hidden", sp->sp.hidden); + cJSON_AddBoolToObject(sprite, "in_scene", sp->sp.in_scene); + cJSON_AddItemToObjectCS(obj, "texture", texture_to_json(&sp->texture, verbose)); + cJSON_AddItemToObjectCS(obj, "color", color_to_json(&sp->color, verbose)); + if (verbose || sp->multiply_color.r != 255 || sp->multiply_color.g != 255 + || sp->multiply_color.b != 255) + cJSON_AddItemToObjectCS(obj, "mul_color", color_to_json(&sp->multiply_color, verbose)); + if (verbose || sp->add_color.r || sp->add_color.g || sp->add_color.b) + cJSON_AddItemToObjectCS(obj, "add_color", color_to_json(&sp->add_color, verbose)); + if (verbose || sp->blend_rate != 255) + cJSON_AddNumberToObject(obj, "blend_rate", sp->blend_rate); + if (verbose || sp->draw_method != DRAW_METHOD_NORMAL) + cJSON_AddStringToObject(obj, "draw_method", draw_method_string(sp->draw_method)); + cJSON_AddItemToObjectCS(obj, "rect", rectangle_to_json(&sp->rect, verbose)); + if (verbose || sp->cg_no) + cJSON_AddNumberToObject(obj, "cg_no", sp->cg_no); + if (verbose || sp->text.texture.handle) { + cJSON *text; + cJSON_AddItemToObjectCS(obj, "text", text = cJSON_CreateObject()); + cJSON_AddItemToObjectCS(text, "texture", texture_to_json(&sp->text.texture, verbose)); + if (verbose || sp->text.home.x || sp->text.home.y) + cJSON_AddItemToObjectCS(text, "home", point_to_json(&sp->text.home, verbose)); + cJSON_AddItemToObjectCS(text, "pos", point_to_json(&sp->text.pos, verbose)); + if (verbose || sp->text.char_space) + cJSON_AddNumberToObject(text, "char_space", sp->text.char_space); + if (verbose || sp->text.line_space) + cJSON_AddNumberToObject(text, "line_space", sp->text.line_space); + } + if (verbose || sp->plugin) + cJSON_AddItemToObjectCS(obj, "plugin", draw_plugin_to_json(sp, verbose)); + + return obj; +} diff --git a/src/meson.build b/src/meson.build index b8a4c53..e0769eb 100644 --- a/src/meson.build +++ b/src/meson.build @@ -20,6 +20,7 @@ xsystem4 = [version_h, 'heap.c', 'id_pool.c', 'input.c', + 'json.c', 'msgqueue.c', 'page.c', 'resume.c', diff --git a/src/parts/debug.c b/src/parts/debug.c index 5990271..01de856 100644 --- a/src/parts/debug.c +++ b/src/parts/debug.c @@ -17,202 +17,247 @@ #include "system4.h" #include "system4/cg.h" #include "system4/string.h" +#include "system4/utfsjis.h" #include "xsystem4.h" +#include "cJSON.h" +#include "json.h" #include "parts_internal.h" -static void parts_cg_print(struct parts_cg *cg, int indent) +static void cJSON_AddSjisToObject(cJSON *obj, const char *name, const char *sjis) { - indent_message(indent, "cg.no = %d,\n", cg->no); + // TODO: can avoid copy by implementing this as part of cJSON proper + char *utf = sjis2utf(sjis, 0); + cJSON_AddStringToObject(obj, name, utf); + free(utf); } -static void parts_text_print(struct parts_text *text, int indent) +static void parts_cg_to_json(struct parts_cg *cg, cJSON *out, bool verbose) { - indent_message(indent, "text.lines = {\n"); + cJSON_AddNumberToObject(out, "no", cg->no); +} + +static void parts_text_to_json(struct parts_text *text, cJSON *out, bool verbose) +{ + cJSON *lines; + + cJSON_AddItemToObjectCS(out, "lines", lines = cJSON_CreateArray()); for (unsigned i = 0; i < text->nr_lines; i++) { + cJSON *line; struct string *s = parts_text_line_get(&text->lines[i]); - indent_message(indent+1, "contents = \"%s\",\n", display_sjis0(s->text)); - indent_message(indent+1, "width = %u,\n", text->lines[i].width); - indent_message(indent+1, "height = %u,\n", text->lines[i].height); + cJSON_AddItemToArray(lines, line = cJSON_CreateObject()); + cJSON_AddSjisToObject(line, "contents", s->text); + cJSON_AddNumberToObject(line, "width", text->lines[i].width); + cJSON_AddNumberToObject(line, "height", text->lines[i].height); free_string(s); } - indent_message(indent, "},\n"); - indent_message(indent, "text.line_space = %u,\n", text->line_space); - indent_message(indent, "text.cursor = "); - gfx_print_point(&text->cursor); - sys_message(",\n"); - indent_message(indent, "text.ts = "); - gfx_print_text_style(&text->ts, indent); - sys_message("\n"); + cJSON_AddNumberToObject(out, "line_space", text->line_space); + cJSON_AddItemToObjectCS(out, "cursor", point_to_json(&text->cursor, verbose)); + cJSON_AddItemToObjectCS(out, "text_style", text_style_to_json(&text->ts, verbose)); } -static void parts_animation_print(struct parts_animation *anim, int indent) +static void parts_animation_to_json(struct parts_animation *anim, cJSON *out, bool verbose) { - indent_message(indent, "anim.start_no = %u,\n", anim->start_no); - indent_message(indent, "anim.frame_time = %u,\n", anim->frame_time); - indent_message(indent, "anim.elapsed = %u,\n", anim->elapsed); - indent_message(indent, "anim.current_frame = %u,\n", anim->current_frame); - indent_message(indent, "anim.frames = {\n"); + cJSON *frames; + + cJSON_AddNumberToObject(out, "start_no", anim->start_no); + cJSON_AddNumberToObject(out, "frame_time", anim->frame_time); + cJSON_AddNumberToObject(out, "elapsed", anim->elapsed); + cJSON_AddNumberToObject(out, "current_frame", anim->current_frame); + cJSON_AddItemToObjectCS(out, "frames", frames = cJSON_CreateArray()); for (unsigned i = 0; i < anim->nr_frames; i++) { - indent_message(indent+1, "[%u] = ", i); - gfx_print_texture(&anim->frames[i], indent+1); - indent_message(indent+1, ",\n"); + cJSON_AddItemToArray(frames, texture_to_json(&anim->frames[i], verbose)); } - indent_message(indent, "}\n"); } -static void parts_numeral_print(struct parts_numeral *num, int indent) +static void parts_numeral_to_json(struct parts_numeral *num, cJSON *out, bool verbose) { - indent_message(indent, "num.have_num = %s,\n", num->have_num ? "true" : "false"); - indent_message(indent, "num.num = %d,\n", num->num); - indent_message(indent, "num.space = %d,\n", num->space); - indent_message(indent, "num.show_comma = %d,\n", num->show_comma); - indent_message(indent, "num.length = %d,\n", num->length); - indent_message(indent, "num.cg_no = %d,\n", num->cg_no); - indent_message(indent, "num.cg = {\n"); + cJSON *cg; + + cJSON_AddBoolToObject(out, "have_num", num->have_num); + cJSON_AddNumberToObject(out, "num", num->num); + cJSON_AddNumberToObject(out, "space", num->space); + cJSON_AddBoolToObject(out, "show_comma", num->show_comma); + cJSON_AddNumberToObject(out, "length", num->length); + cJSON_AddNumberToObject(out, "cg_no", num->cg_no); + cJSON_AddItemToObjectCS(out, "cg", cg = cJSON_CreateArray()); for (int i = 0; i < 12; i++) { - indent_message(indent+1, "[%d] = ", i); - gfx_print_texture(&num->cg[i], indent+1); - indent_message(indent+1, ",\n"); + cJSON_AddItemToArray(cg, texture_to_json(&num->cg[i], verbose)); } - indent_message(indent, "}\n"); } -static void parts_gauge_print(struct parts_gauge *gauge, int indent) +static void parts_gauge_to_json(struct parts_gauge *gauge, cJSON *out, bool verbose) { - indent_message(indent, "gauge.cg = "); - gfx_print_texture(&gauge->cg, indent); + cJSON_AddItemToObject(out, "cg", texture_to_json(&gauge->cg, verbose)); } -static void parts_construction_process_print(struct parts_construction_process *cproc, int indent) +static void parts_construction_process_to_json(struct parts_construction_process *cproc, + cJSON *out, bool verbose) { static const char *type_names[PARTS_NR_CP_TYPES] = { - [PARTS_CP_CREATE] = "PARTS_CP_CREATE", - [PARTS_CP_CREATE_PIXEL_ONLY] = "PARTS_CP_CREATE_PIXEL_ONLY", - [PARTS_CP_CG] = "PARTS_CP_CG", - [PARTS_CP_FILL] = "PARTS_CP_FILL", - [PARTS_CP_FILL_ALPHA_COLOR] = "PARTS_CP_FILL_ALPHA_COLOR", - [PARTS_CP_FILL_AMAP] = "PARTS_CP_FILL_AMAP", - [PARTS_CP_DRAW_CUT_CG] = "PARTS_CP_DRAW_CUT_CG", - [PARTS_CP_COPY_CUT_CG] = "PARTS_CP_COPY_CUT_CG", - [PARTS_CP_DRAW_TEXT] = "PARTS_CP_DRAW_TEXT", - [PARTS_CP_COPY_TEXT] = "PARTS_CP_COPY_TEXT", + [PARTS_CP_CREATE] = "create", + [PARTS_CP_CREATE_PIXEL_ONLY] = "create_pixel_only", + [PARTS_CP_CG] = "cg", + [PARTS_CP_FILL] = "fill", + [PARTS_CP_FILL_ALPHA_COLOR] = "fill_alpha_color", + [PARTS_CP_FILL_AMAP] = "fill_amap", + [PARTS_CP_DRAW_CUT_CG] = "draw_cut_cg", + [PARTS_CP_COPY_CUT_CG] = "copy_cut_cg", + [PARTS_CP_DRAW_TEXT] = "draw_text", + [PARTS_CP_COPY_TEXT] = "copy_text", }; - indent_message(indent, "cproc.ops = {\n"); - indent++; + cJSON *ops, *tmp; + + cJSON_AddItemToObjectCS(out, "operations", ops = cJSON_CreateArray()); - int i = 0; struct parts_cp_op *op; TAILQ_FOREACH(op, &cproc->ops, entry) { - indent_message(indent, "[%d] = {\n", i++); - indent++; - - const char *type = "INVALID_CONSTRUCTION_PROCERSS_TYPE"; + const char *type = "invalid"; if (op->type >= 0 && op->type < PARTS_NR_CP_TYPES) type = type_names[op->type]; - indent_message(indent, "type = %s,\n", type); + cJSON *obj; + cJSON_AddItemToArray(ops, obj = cJSON_CreateObject()); + cJSON_AddStringToObject(obj, "type", type); switch (op->type) { case PARTS_CP_CREATE: case PARTS_CP_CREATE_PIXEL_ONLY: - indent_message(indent, "create = {w=%d,h=%d}\n", op->create.w, op->create.h); + cJSON_AddItemToObjectCS(obj, "size", tmp = cJSON_CreateObject()); + cJSON_AddNumberToObject(tmp, "w", op->create.w); + cJSON_AddNumberToObject(tmp, "h", op->create.h); break; case PARTS_CP_CG: - indent_message(indent, "cg.no = %d\n", op->cg.no); + cJSON_AddNumberToObject(obj, "no", op->cg.no); break; case PARTS_CP_FILL: case PARTS_CP_FILL_ALPHA_COLOR: case PARTS_CP_FILL_AMAP: - indent_message(indent, "fill.rect = {x=%d,y=%d,w=%d,h=%d},\n", - op->fill.x, op->fill.y, op->fill.w, op->fill.h); - indent_message(indent, "fill.color = (%d,%d,%d,%d)\n", - op->fill.r, op->fill.g, op->fill.b, op->fill.a); + cJSON_AddItemToObjectCS(obj, "rect", tmp = cJSON_CreateObject()); + cJSON_AddNumberToObject(tmp, "x", op->fill.x); + cJSON_AddNumberToObject(tmp, "y", op->fill.y); + cJSON_AddNumberToObject(tmp, "w", op->fill.w); + cJSON_AddNumberToObject(tmp, "h", op->fill.h); + cJSON_AddItemToObjectCS(obj, "color", tmp = cJSON_CreateObject()); + cJSON_AddNumberToObject(tmp, "r", op->fill.r); + cJSON_AddNumberToObject(tmp, "g", op->fill.g); + cJSON_AddNumberToObject(tmp, "b", op->fill.b); + cJSON_AddNumberToObject(tmp, "a", op->fill.a); break; case PARTS_CP_DRAW_CUT_CG: case PARTS_CP_COPY_CUT_CG: - indent_message(indent, "cut_cg.cg_no = %d,\n", op->cut_cg.cg_no); - indent_message(indent, "cut_cg.dst = {x=%d,y=%d,w=%d,h=%d},\n", - op->cut_cg.dx, op->cut_cg.dy, op->cut_cg.dw, op->cut_cg.dh); - indent_message(indent, "cut_cg.src = {x=%d,y=%d,w=%d,h=%d},\n", - op->cut_cg.sx, op->cut_cg.sy, op->cut_cg.sw, op->cut_cg.sh); - indent_message(indent, "cut_cg.interp_type = %d\n", op->cut_cg.interp_type); + cJSON_AddNumberToObject(obj, "no", op->cut_cg.cg_no); + cJSON_AddItemToObjectCS(obj, "dst", tmp = cJSON_CreateObject()); + cJSON_AddNumberToObject(tmp, "x", op->cut_cg.dx); + cJSON_AddNumberToObject(tmp, "y", op->cut_cg.dy); + cJSON_AddNumberToObject(tmp, "w", op->cut_cg.dw); + cJSON_AddNumberToObject(tmp, "h", op->cut_cg.dh); + cJSON_AddItemToObjectCS(obj, "src", tmp = cJSON_CreateObject()); + cJSON_AddNumberToObject(tmp, "x", op->cut_cg.sx); + cJSON_AddNumberToObject(tmp, "y", op->cut_cg.sy); + cJSON_AddNumberToObject(tmp, "w", op->cut_cg.sw); + cJSON_AddNumberToObject(tmp, "h", op->cut_cg.sh); + cJSON_AddNumberToObject(obj, "interp_type", op->cut_cg.interp_type); break; case PARTS_CP_DRAW_TEXT: case PARTS_CP_COPY_TEXT: - indent_message(indent, "text.text = \"%s\",\n", display_sjis0(op->text.text->text)); - indent_message(indent, "text.pos = {x=%d,y=%d},\n", op->text.x, op->text.y); - indent_message(indent, "text.line_space = %d,\n", op->text.line_space); - indent_message(indent, "text.style = "); - gfx_print_text_style(&op->text.style, indent); - sys_message("\n"); + cJSON_AddSjisToObject(obj, "text", op->text.text->text); + cJSON_AddItemToObjectCS(obj, "pos", tmp = cJSON_CreateObject()); + cJSON_AddNumberToObject(tmp, "x", op->text.x); + cJSON_AddNumberToObject(tmp, "y", op->text.y); + cJSON_AddNumberToObject(obj, "line_space", op->text.line_space); + cJSON_AddItemToObjectCS(obj, "style", text_style_to_json(&op->text.style, verbose)); break; } - indent--; - indent_message(indent, "},\n"); } - - indent--; - indent_message(indent, "}\n"); } -static void parts_print_state(struct parts_state *state, int indent) +static cJSON *parts_state_to_json(struct parts_state *state, bool verbose) { - if (state->type == PARTS_UNINITIALIZED) { - sys_message("UNINITIALIZED"); - return; - } - sys_message("{\n"); - indent++; + static const char *state_types[PARTS_NR_TYPES] = { + [PARTS_UNINITIALIZED] = "uninitialized", + [PARTS_CG] = "cg", + [PARTS_TEXT] = "text", + [PARTS_ANIMATION] = "animation", + [PARTS_NUMERAL] = "numeral", + [PARTS_HGAUGE] = "hgauge", + [PARTS_VGAUGE] = "vgauge", + [PARTS_CONSTRUCTION_PROCESS] = "construction_process" + }; + const char *type = "invalid"; + if (state->type >= 0 && state->type < PARTS_NR_TYPES) + type = state_types[state->type]; - struct parts_common *com = &state->common; + cJSON *obj = cJSON_CreateObject(); + cJSON_AddStringToObject(obj, "type", type); - indent_message(indent, "dims = {w=%d,h=%d},\n", state->common.w, state->common.h); - indent_message(indent, "origin_offset = "); gfx_print_point(&com->origin_offset); sys_message(",\n"); - indent_message(indent, "hitbox = "); gfx_print_rectangle(&com->hitbox); sys_message(",\n"); - indent_message(indent, "surface_area = "); gfx_print_rectangle(&com->surface_area); sys_message(",\n"); switch (state->type) { - case PARTS_UNINITIALIZED: - break; case PARTS_CG: - parts_cg_print(&state->cg, indent); + parts_cg_to_json(&state->cg, obj, verbose); break; case PARTS_TEXT: - parts_text_print(&state->text, indent); + parts_text_to_json(&state->text, obj, verbose); break; case PARTS_ANIMATION: - parts_animation_print(&state->anim, indent); + parts_animation_to_json(&state->anim, obj, verbose); break; case PARTS_NUMERAL: - parts_numeral_print(&state->num, indent); + parts_numeral_to_json(&state->num, obj, verbose); break; case PARTS_HGAUGE: case PARTS_VGAUGE: - parts_gauge_print(&state->gauge, indent); + parts_gauge_to_json(&state->gauge, obj, verbose); break; case PARTS_CONSTRUCTION_PROCESS: - parts_construction_process_print(&state->cproc, indent); + parts_construction_process_to_json(&state->cproc, obj, verbose); + break; + default: break; } - indent--; - indent_message(indent, "}"); + return obj; } -static void parts_print_motion_param(union parts_motion_param param, enum parts_motion_type type) +static cJSON *parts_params_to_json(struct parts_params *params, bool verbose) { + cJSON *obj, *tmp; + + obj = cJSON_CreateObject(); + cJSON_AddNumberToObject(obj, "z", params->z); + cJSON_AddItemToObjectCS(obj, "pos", point_to_json(¶ms->pos, verbose)); + cJSON_AddBoolToObject(obj, "show", params->show); + cJSON_AddNumberToObject(obj, "alpha", params->alpha); + cJSON_AddItemToObjectCS(obj, "scale", tmp = cJSON_CreateObject()); + cJSON_AddNumberToObject(tmp, "x", params->scale.x); + cJSON_AddNumberToObject(tmp, "y", params->scale.y); + cJSON_AddItemToObjectCS(obj, "rotation", tmp = cJSON_CreateObject()); + cJSON_AddNumberToObject(tmp, "x", params->rotation.x); + cJSON_AddNumberToObject(tmp, "y", params->rotation.y); + cJSON_AddNumberToObject(tmp, "z", params->rotation.z); + cJSON_AddItemToObjectCS(obj, "add_color", color_to_json(¶ms->add_color, verbose)); + cJSON_AddItemToObjectCS(obj, "mul_color", color_to_json(¶ms->multiply_color, verbose)); + return obj; +} + +static cJSON *parts_motion_param_to_json(union parts_motion_param param, enum parts_motion_type type) +{ + cJSON *obj; + switch (type) { case PARTS_MOTION_POS: - sys_message("{x=%d,y=%d}", param.x, param.y); - break; + obj = cJSON_CreateObject(); + cJSON_AddNumberToObject(obj, "x", param.x); + cJSON_AddNumberToObject(obj, "y", param.y); + return obj; case PARTS_MOTION_VIBRATION_SIZE: - sys_message("{w=%d,h=%d}", param.x, param.y); - break; + obj = cJSON_CreateObject(); + cJSON_AddNumberToObject(obj, "w", param.x); + cJSON_AddNumberToObject(obj, "h", param.y); + return obj; case PARTS_MOTION_ALPHA: case PARTS_MOTION_CG: case PARTS_MOTION_NUMERAL_NUMBER: - sys_message("%d", param.i); - break; + return cJSON_CreateNumber(param.i); case PARTS_MOTION_HGAUGE_RATE: case PARTS_MOTION_VGAUGE_RATE: case PARTS_MOTION_MAG_X: @@ -220,174 +265,105 @@ static void parts_print_motion_param(union parts_motion_param param, enum parts_ case PARTS_MOTION_ROTATE_X: case PARTS_MOTION_ROTATE_Y: case PARTS_MOTION_ROTATE_Z: - sys_message("%f", param.f); - break; + return cJSON_CreateNumber(param.f); } + return cJSON_CreateNull(); } -static void parts_print_motion(struct parts_motion *motion, int indent) +static cJSON *parts_motion_to_json(struct parts_motion *motion) { static const char *type_names[PARTS_NR_MOTION_TYPES] = { - [PARTS_MOTION_POS] = "PARTS_MOTION_POS", - [PARTS_MOTION_ALPHA] = "PARTS_MOTION_ALPHA", - [PARTS_MOTION_CG] = "PARTS_MOTION_CG", - [PARTS_MOTION_HGAUGE_RATE] = "PARTS_MOTION_HGAUGE_RATE", - [PARTS_MOTION_VGAUGE_RATE] = "PARTS_MOTION_VGAUGE_RATE", - [PARTS_MOTION_NUMERAL_NUMBER] = "PARTS_MOTION_NUMERAL_NUMBER", - [PARTS_MOTION_MAG_X] = "PARTS_MOTION_MAG_X", - [PARTS_MOTION_MAG_Y] = "PARTS_MOTION_MAG_Y", - [PARTS_MOTION_ROTATE_X] = "PARTS_MOTION_ROTATE_X", - [PARTS_MOTION_ROTATE_Y] = "PARTS_MOTION_ROTATE_Y", - [PARTS_MOTION_ROTATE_Z] = "PARTS_MOTION_ROTATE_Z", - [PARTS_MOTION_VIBRATION_SIZE] = "PARTS_MOTION_VIBRATION_SIZE" + [PARTS_MOTION_POS] = "pos", + [PARTS_MOTION_ALPHA] = "alpha", + [PARTS_MOTION_CG] = "cg", + [PARTS_MOTION_HGAUGE_RATE] = "hgauge_rate", + [PARTS_MOTION_VGAUGE_RATE] = "vgauge_rate", + [PARTS_MOTION_NUMERAL_NUMBER] = "numeral_number", + [PARTS_MOTION_MAG_X] = "mag_x", + [PARTS_MOTION_MAG_Y] = "mag_y", + [PARTS_MOTION_ROTATE_X] = "rotate_x", + [PARTS_MOTION_ROTATE_Y] = "rotate_y", + [PARTS_MOTION_ROTATE_Z] = "rotate_z", + [PARTS_MOTION_VIBRATION_SIZE] = "vibration_size" }; - const char *type = "INVALID_MOTION_TYPE"; + const char *type = "invalid"; if (motion->type >= 0 && motion->type < PARTS_NR_MOTION_TYPES) type = type_names[motion->type]; - sys_message("{\n"); - indent++; + cJSON *obj; - indent_message(indent, "type = %s,\n", type); - indent_message(indent, "begin = "); - parts_print_motion_param(motion->begin, motion->type); - sys_message(",\n"); - indent_message(indent, "end = "); - parts_print_motion_param(motion->end, motion->type); - sys_message(",\n"); - indent_message(indent, "begin_time = %d,\n", motion->begin_time); - indent_message(indent, "end_time = %d,\n", motion->end_time); - - indent--; - indent_message(indent, "}"); + obj = cJSON_CreateObject(); + cJSON_AddStringToObject(obj, "type", type); + cJSON_AddItemToObjectCS(obj, "begin", parts_motion_param_to_json(motion->begin, motion->type)); + cJSON_AddItemToObjectCS(obj, "end", parts_motion_param_to_json(motion->end, motion->type)); + cJSON_AddNumberToObject(obj, "begin_time", motion->begin_time); + cJSON_AddNumberToObject(obj, "end_time", motion->end_time); + return obj; } -static void parts_print_params(struct parts_params *global, struct parts_params *local, int indent) -{ - sys_message("{\n"); - indent++; - - indent_message(indent, "z = %d (%d),\n", global->z, local->z); - indent_message(indent, "pos = "); - gfx_print_point(&global->pos); - sys_message(" ("); - gfx_print_point(&local->pos); - sys_message("),\n"); - indent_message(indent, "show = %s (%s),\n", global->show ? "true" : "false", - local->show ? "true" : "false"); - indent_message(indent, "alpha = %u (%u),\n", (unsigned)global->alpha, (unsigned)local->alpha); - indent_message(indent, "scale = {x=%f,y=%f} ({x=%f,y=%f}),\n", global->scale.x, global->scale.y, - local->scale.x, local->scale.y); - indent_message(indent, "rotation = {x=%f,y=%f,z=%f} ({x=%f,y=%f,z=%f}),\n", - global->rotation.x, global->rotation.y, global->rotation.z, - local->rotation.x, local->rotation.y, local->rotation.z); - indent_message(indent, "add_color = "); - gfx_print_color(&global->add_color); - sys_message(" ("); - gfx_print_color(&local->add_color); - sys_message("),\n"); - indent_message(indent, "multiply_color = "); - gfx_print_color(&global->multiply_color); - sys_message(" ("); - gfx_print_color(&local->multiply_color); - sys_message("),\n"); - - indent--; - indent_message(indent, "}"); -} - -static void _parts_print(struct parts *parts, int indent) +cJSON *parts_to_json(struct parts *parts, bool verbose) { static const char *state_names[PARTS_NR_STATES] = { - [PARTS_STATE_DEFAULT] = "PARTS_STATE_DEFAULT", - [PARTS_STATE_HOVERED] = "PARTS_STATE_HOVERED", - [PARTS_STATE_CLICKED] = "PARTS_STATE_CLICKED" + [PARTS_STATE_DEFAULT] = "default", + [PARTS_STATE_HOVERED] = "hovered", + [PARTS_STATE_CLICKED] = "clicked" }; - const char *state = "INVALID_PARTS_STATE"; + const char *state = "invalid"; if (parts->state >= 0 && parts->state < PARTS_NR_STATES) state = state_names[parts->state]; - indent_message(indent, "parts %d = {\n", parts->no); - indent++; + cJSON *obj, *motions, *children; - // print states - indent_message(indent, "state = %s,\n", state); - for (int i = 0; i < PARTS_NR_STATES; i++) { - if (parts->states[i].type == PARTS_UNINITIALIZED && i != parts->state) - continue; - indent_message(indent, "state[%s] = ", state_names[i]); - parts_print_state(&parts->states[i], indent); - sys_message(",\n"); - } - - // print params - indent_message(indent, "local = "); - parts_print_params(&parts->global, &parts->local, indent); - sys_message(",\n"); - - // print misc. data + obj = cJSON_CreateObject(); + cJSON_AddNumberToObject(obj, "no", parts->no); + cJSON_AddStringToObject(obj, "state", state); + cJSON_AddItemToObjectCS(obj, "default", parts_state_to_json(&parts->states[PARTS_STATE_DEFAULT], verbose)); + cJSON_AddItemToObjectCS(obj, "hovered", parts_state_to_json(&parts->states[PARTS_STATE_HOVERED], verbose)); + cJSON_AddItemToObjectCS(obj, "clicked", parts_state_to_json(&parts->states[PARTS_STATE_CLICKED], verbose)); + cJSON_AddItemToObjectCS(obj, "local", parts_params_to_json(&parts->local, verbose)); + cJSON_AddItemToObjectCS(obj, "global", parts_params_to_json(&parts->global, verbose)); if (parts->delegate_index >= 0) - indent_message(indent, "delegate_index = %d,\n", parts->delegate_index); - indent_message(indent, "sprite_deform = %d,\n", parts->sprite_deform); - indent_message(indent, "clickable = %s,\n", parts->clickable ? "true" : "false"); + cJSON_AddNumberToObject(obj, "delegate_index", parts->delegate_index); + cJSON_AddNumberToObject(obj, "sprite_deform", parts->sprite_deform); + cJSON_AddBoolToObject(obj, "clickable", parts->clickable); if (parts->on_cursor_sound >= 0) - indent_message(indent, "on_cursor_sound = %d,\n", parts->on_cursor_sound); + cJSON_AddNumberToObject(obj, "on_cursor_sound", parts->on_cursor_sound); if (parts->on_click_sound >= 0) - indent_message(indent, "on_click_sound = %d,\n", parts->on_click_sound); - indent_message(indent, "origin_mode = %d,\n", parts->origin_mode); - indent_message(indent, "parent = %d,\n", parts->parent ? parts->parent->no : -1); + cJSON_AddNumberToObject(obj, "on_click_sound", parts->on_click_sound); + cJSON_AddNumberToObject(obj, "origin_mode", parts->origin_mode); + cJSON_AddNumberToObject(obj, "parent", parts->parent ? parts->parent->no : -1); if (parts->linked_to >= 0) - indent_message(indent, "linked_to = %d,\n", parts->linked_to); + cJSON_AddNumberToObject(obj, "linked_to", parts->linked_to); if (parts->linked_from >= 0) - indent_message(indent, "linked_from = %d,\n", parts->linked_from); - indent_message(indent, "draw_filter = %d,\n", parts->draw_filter); + cJSON_AddNumberToObject(obj, "linked_from", parts->linked_from); + cJSON_AddNumberToObject(obj, "draw_filter", parts->draw_filter); - // print motion data - if (TAILQ_EMPTY(&parts->motion)) { - indent_message(indent, "motion = {},\n"); - } else { - indent_message(indent, "motion = {\n"); - int i = 0; - struct parts_motion *motion; - TAILQ_FOREACH(motion, &parts->motion, entry) { - indent_message(indent+1, "[%d] = ", i++); - parts_print_motion(motion, indent+1); - sys_message(",\n"); - } - indent_message(indent, "},\n"); + cJSON_AddItemToObjectCS(obj, "motions", motions = cJSON_CreateArray()); + struct parts_motion *motion; + TAILQ_FOREACH(motion, &parts->motion, entry) { + cJSON_AddItemToArray(motions, parts_motion_to_json(motion)); } - // print children - if (TAILQ_EMPTY(&parts->children)) { - - } else { - indent_message(indent, "children = {\n"); - struct parts *child; - PARTS_FOREACH_CHILD(child, parts) { - _parts_print(child, indent+1); - sys_message(",\n"); - } - indent_message(indent, "},\n"); + cJSON_AddItemToObjectCS(obj, "children", children = cJSON_CreateArray()); + struct parts *child; + PARTS_FOREACH_CHILD(child, parts) { + cJSON_AddItemToArray(children, parts_to_json(child, verbose)); } - indent--; - indent_message(indent, "}"); + return obj; } -void parts_print(struct parts *parts) +cJSON *parts_engine_to_json(bool verbose) { - _parts_print(parts, 0); - putchar('\n'); -} + cJSON *a = cJSON_CreateArray(); -void parts_engine_print(void) -{ struct parts *parts; PARTS_LIST_FOREACH(parts) { if (!parts->parent) - parts_print(parts); + cJSON_AddItemToArray(a, parts_to_json(parts, verbose)); } + return a; } #ifdef DEBUGGER_ENABLED @@ -408,7 +384,13 @@ static void parts_cmd_parts(unsigned nr_args, char **args) if (!parts) return; - parts_print(parts); + cJSON *json = parts_to_json(parts, true); + char *text = cJSON_Print(json); + + sys_message("%s\n", text); + + free(text); + cJSON_Delete(json); } static void parts_list_print(struct parts *parts, int indent) diff --git a/src/parts/parts_internal.h b/src/parts/parts_internal.h index a733bfa..a8dfba5 100644 --- a/src/parts/parts_internal.h +++ b/src/parts/parts_internal.h @@ -21,6 +21,7 @@ #include "gfx/font.h" #include "queue.h" +typedef struct cJSON cJSON; struct string; // NOTE: actual value is +1 @@ -95,6 +96,7 @@ enum parts_type { PARTS_HGAUGE, PARTS_VGAUGE, PARTS_CONSTRUCTION_PROCESS, +#define PARTS_NR_TYPES (PARTS_CONSTRUCTION_PROCESS+1) }; struct parts_common { @@ -328,8 +330,7 @@ bool parts_build_construction_process(struct parts *parts, // debug.c void parts_debug_init(void); -void parts_print(struct parts *parts); -void parts_engine_print(void); +cJSON *parts_engine_to_json(bool verbose); static inline bool parts_state_valid(int state) { diff --git a/src/parts/render.c b/src/parts/render.c index cde4eeb..ccebf49 100644 --- a/src/parts/render.c +++ b/src/parts/render.c @@ -146,9 +146,9 @@ void parts_dirty(possibly_unused struct parts *parts) parts_engine_dirty(); } -static void _parts_engine_print(possibly_unused struct sprite *_) +static cJSON *_parts_engine_to_json(struct sprite *_, bool verbose) { - parts_engine_print(); + return parts_engine_to_json(verbose); } void parts_render_init(void) @@ -158,7 +158,7 @@ void parts_render_init(void) goat_sprite.has_pixel = true; goat_sprite.has_alpha = true; goat_sprite.render = parts_engine_render; - goat_sprite.debug_print = _parts_engine_print; + goat_sprite.to_json = _parts_engine_to_json; scene_register_sprite(&goat_sprite); gfx_load_shader(&parts_shader.shader, "shaders/render.v.glsl", "shaders/parts.f.glsl"); diff --git a/src/scene.c b/src/scene.c index 98f4e77..62d5ac9 100644 --- a/src/scene.c +++ b/src/scene.c @@ -22,7 +22,9 @@ #include "system4/cg.h" #include "asset_manager.h" +#include "cJSON.h" #include "gfx/gfx.h" +#include "json.h" #include "queue.h" #include "scene.h" #include "xsystem4.h" @@ -137,30 +139,14 @@ void scene_set_sprite_z2(struct sprite *sp, int z, int z2) } } -void scene_print_sprite(struct sprite *sp, int indent) -{ - sys_message("{\n"); - indent++; - indent_message(indent, "z = (%d,%d),\n", sp->z, sp->z2); - indent_message(indent, "has_pixel = %s,\n", sp->has_pixel ? "true" : "false"); - indent_message(indent, "has_alpha = %s,\n", sp->has_alpha ? "true" : "false"); - indent_message(indent, "hidden = %s,\n", sp->hidden ? "true" : "false"); - indent_message(indent, "in_scene = %s,\n", sp->in_scene ? "true" : "false"); - indent--; - sys_message("}"); - -} - void scene_print(void) { struct sprite *p; TAILQ_FOREACH(p, &sprite_list, entry) { - if (p->debug_print) { - p->debug_print(p); - } else { - sys_message("unknown_scene_entity "); - scene_print_sprite(p, 0); - putchar('\n'); - } + cJSON *json = p->to_json ? p->to_json(p, false) : scene_sprite_to_json(p, false); + char *text = cJSON_Print(json); + sys_message("%s\n", text); + free(text); + cJSON_Delete(json); } } diff --git a/src/sprite.c b/src/sprite.c index 400c5cc..87a00ad 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -29,6 +29,7 @@ #include "input.h" #include "gfx/gfx.h" #include "gfx/font.h" +#include "json.h" #include "plugin.h" #include "sprite.h" #include "vm.h" @@ -175,9 +176,9 @@ struct texture *sprite_get_texture(struct sact_sprite *sp) return &sp->texture; } -static void _sprite_print(struct sprite *sp) +static cJSON *_sprite_to_json(struct sprite *sp, bool verbose) { - sprite_print((struct sact_sprite*)sp); + return sprite_to_json((struct sact_sprite*)sp, verbose); } void sprite_set_cg(struct sact_sprite *sp, struct cg *cg) @@ -189,7 +190,7 @@ void sprite_set_cg(struct sact_sprite *sp, struct cg *cg) sp->sp.has_pixel = true; sp->sp.has_alpha = cg->metrics.has_alpha; sp->sp.render = sprite_render; - sp->sp.debug_print = _sprite_print; + sp->sp.to_json = _sprite_to_json; sprite_dirty(sp); } @@ -218,7 +219,7 @@ void sprite_set_cg_2x(struct sact_sprite *sp, struct cg *cg) sp->sp.has_pixel = true; sp->sp.has_alpha = cg->metrics.has_alpha; sp->sp.render = sprite_render; - sp->sp.debug_print = _sprite_print; + sp->sp.to_json = _sprite_to_json; sprite_dirty(sp); gfx_delete_texture(&tmp); } @@ -283,7 +284,7 @@ void sprite_init_color(struct sact_sprite *sp, int w, int h, int r, int g, int b sp->sp.has_pixel = true; sp->sp.has_alpha = a >= 0; sp->sp.render = sprite_render; - sp->sp.debug_print = _sprite_print; + sp->sp.to_json = _sprite_to_json; sprite_dirty(sp); } @@ -465,82 +466,3 @@ void sprite_call_plugins(void) sp->plugin->update(sp); } } - -void gfx_print_color(SDL_Color *c) -{ - sys_message("(%d,%d,%d,%d)", c->r, c->g, c->b, c->a); -} - -void gfx_print_rectangle(Rectangle *r) -{ - sys_message("{x=%d,y=%d,w=%d,h=%d}", r->x, r->y, r->w, r->h); -} - -void gfx_print_point(Point *p) -{ - sys_message("{x=%d,y=%d}", p->x, p->y); -} - -void gfx_print_texture(struct texture *t, int indent) -{ - sys_message("{\n"); - indent_message(indent+1, "initialized = %s,\n", t->handle ? "true" : "false"); - indent_message(indent+1, "size = (%d,%d),\n", t->w, t->h); - indent_message(indent+1, "has_alpha = %s,\n", t->has_alpha ? "true" : "false"); - indent_message(indent, "}"); -} - -void sprite_print(struct sact_sprite *sp) -{ - int indent = 0; - indent_message(indent, "sprite %d = {\n", sp->no); - indent++; - - indent_message(indent, "sp = {\n"); - indent++; - indent_message(indent, "z = (%d,%d),\n", sp->sp.z, sp->sp.z2); - indent_message(indent, "has_pixel = %s,\n", sp->sp.has_pixel ? "true" : "false"); - indent_message(indent, "has_alpha = %s,\n", sp->sp.has_alpha ? "true" : "false"); - indent_message(indent, "hidden = %s,\n", sp->sp.hidden ? "true" : "false"); - indent_message(indent, "in_scene = %s,\n", sp->sp.in_scene ? "true" : "false"); - indent--; - indent_message(indent, "},\n"); - - indent_message(indent, "texture = "); gfx_print_texture(&sp->texture, 1); sys_message(",\n"); - indent_message(indent, "color = "); gfx_print_color(&sp->color); sys_message(",\n"); - indent_message(indent, "blend_rate = %d,\n", sp->blend_rate); - indent_message(indent, "multiply_color = "); gfx_print_color(&sp->multiply_color); sys_message(",\n"); - indent_message(indent, "add_color = "); gfx_print_color(&sp->add_color); sys_message(",\n"); - switch (sp->draw_method) { - case DRAW_METHOD_NORMAL: indent_message(indent, "draw_method = normal,\n"); break; - case DRAW_METHOD_SCREEN: indent_message(indent, "draw_method = screen,\n"); break; - case DRAW_METHOD_MULTIPLY: indent_message(indent, "draw_method = multiply,\n"); break; - case DRAW_METHOD_ADDITIVE: indent_message(indent, "draw_method = additive,\n"); break; - default: indent_message(indent, "draw_method = unknown,\n"); break; - } - indent_message(indent, "rect = "); gfx_print_rectangle(&sp->rect); sys_message(",\n"); - - indent_message(indent, "text = {\n"); - indent++; - indent_message(indent, "texture = "); gfx_print_texture(&sp->text.texture, 2); sys_message(",\n"); - indent_message(indent, "home = "); gfx_print_point(&sp->text.home); sys_message(",\n"); - indent_message(indent, "pos = "); gfx_print_point(&sp->text.pos); sys_message(",\n"); - indent_message(indent, "char_space = %d,\n", sp->text.char_space); - indent_message(indent, "line_space = %d,\n", sp->text.line_space); - if (sp->plugin) { - if (sp->plugin->debug_print) { - indent_message(indent, "plugin = {\n"); - sp->plugin->debug_print(sp, indent + 1); - indent_message(indent, "},\n"); - } else { - indent_message(indent, "plugin = %s,\n", sp->plugin->name); - } - } - indent--; - indent_message(indent, "},\n"); - - indent_message(indent, "cg_no = %d\n", sp->cg_no); - indent--; - - indent_message(indent, "}\n"); -} diff --git a/src/text.c b/src/text.c index aa55f23..0a1e9cc 100644 --- a/src/text.c +++ b/src/text.c @@ -452,24 +452,3 @@ void gfx_set_font_name(const char *name) WARNING("Unhandled font name: \"%s\"", display_sjis0(name)); } } - -void gfx_print_text_style(struct text_style *style, int indent) -{ - sys_message("{\n"); - indent++; - - indent_message(indent, "face = %u,\n", style->face); - indent_message(indent, "size = %f,\n", style->size); - indent_message(indent, "bold_width = %f,\n", style->bold_width); - indent_message(indent, "weight = %u,\n", style->weight); - indent_message(indent, "edge_weight = {l=%f,u=%f,r=%f,d=%f},\n", - style->edge_left, style->edge_up, style->edge_right, style->edge_down); - indent_message(indent, "color = "); gfx_print_color(&style->color); sys_message(",\n"); - indent_message(indent, "edge_color = "); gfx_print_color(&style->edge_color); sys_message(",\n"); - indent_message(indent, "scale_x = %f,\n", style->scale_x); - indent_message(indent, "space_scale_x = %f,\n", style->space_scale_x); - indent_message(indent, "font_spacing = %f,\n", style->font_spacing); - - indent--; - indent_message(indent, "}"); -} diff --git a/subprojects/libsys4 b/subprojects/libsys4 index 29d7356..010cf28 160000 --- a/subprojects/libsys4 +++ b/subprojects/libsys4 @@ -1 +1 @@ -Subproject commit 29d73563ecc9fac4716e5ffdb8bf0796cff37ccb +Subproject commit 010cf28e197093fd400a2c67665e91d02a3fe533