diff --git a/include/dungeon/dungeon.h b/include/dungeon/dungeon.h index affde29..c3d4389 100644 --- a/include/dungeon/dungeon.h +++ b/include/dungeon/dungeon.h @@ -21,6 +21,7 @@ #include #include #include "gfx/gl.h" +#include "plugin.h" struct page; struct dgn; @@ -51,6 +52,7 @@ struct camera { */ struct dungeon_context { + struct draw_plugin plugin; enum draw_dungeon_version version; int surface; bool loaded; @@ -68,7 +70,6 @@ struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version void dungeon_context_free(struct dungeon_context *ctx); bool dungeon_load(struct dungeon_context *ctx, int num); void dungeon_set_camera(int surface, float x, float y, float z, float angle, float angle_p); -void dungeon_render(struct dungeon_context *ctx); void dungeon_set_walked(int surface, int x, int y, int z, int flag); int dungeon_get_walked(int surface, int x, int y, int z); int dungeon_calc_conquer(int surface); @@ -76,6 +77,5 @@ bool dungeon_load_walk_data(int surface, int map, struct page **page); bool dungeon_save_walk_data(int surface, int map, struct page **page); struct dungeon_context *dungeon_get_context(int surface); -void dungeon_update(void); #endif /* SYSTEM4_DUNGEON_H */ diff --git a/include/plugin.h b/include/plugin.h new file mode 100644 index 0000000..ecb99a5 --- /dev/null +++ b/include/plugin.h @@ -0,0 +1,25 @@ +/* Copyright (C) 2022 kichikuou + * + * 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 SYSTEM4_PLUGIN_H +#define SYSTEM4_PLUGIN_H + +struct draw_plugin { + const char *name; + void (*update)(struct draw_plugin *); +}; + +#endif /* SYSTEM4_PLUGIN_H */ diff --git a/include/sprite.h b/include/sprite.h index da18bd8..a3efe3d 100644 --- a/include/sprite.h +++ b/include/sprite.h @@ -30,7 +30,7 @@ struct text_style; struct sact_sprite { struct sprite sp; - TAILQ_ENTRY(sact_sprite) entry; + LIST_ENTRY(sact_sprite) entry; // The sprite's texture (CG or solid color). Initialized lazily. struct texture texture; // If no CG is attached to the sprite, the solid color to fill with. @@ -51,6 +51,8 @@ struct sact_sprite { int no; // The CG number attached to the sprite. int cg_no; + // (optional) Draw plugin bound to this sprite. + struct draw_plugin *plugin; }; static inline void sprite_dirty(struct sact_sprite *sp) @@ -104,6 +106,8 @@ bool sprite_is_point_in(struct sact_sprite *sp, int x, int y); bool sprite_is_point_in_rect(struct sact_sprite *sp, int x, int y); int sprite_get_amap_value(struct sact_sprite *sp, int x, int y); void sprite_get_pixel_value(struct sact_sprite *sp, int x, int y, int *r, int *g, int *b); +void sprite_bind_plugin(struct sact_sprite *sp, struct draw_plugin *plugin); +void sprite_call_plugins(void); void print_sprite(struct sact_sprite *sp); diff --git a/src/dungeon/dungeon.c b/src/dungeon/dungeon.c index 2e3a484..b9b3b16 100644 --- a/src/dungeon/dungeon.c +++ b/src/dungeon/dungeon.c @@ -45,9 +45,13 @@ #define M_PI (3.14159265358979323846) #endif +static void dungeon_render(struct draw_plugin *plugin); + 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->version = version; ctx->surface = surface; struct sact_sprite *sp = sact_get_sprite(ctx->surface); @@ -56,6 +60,7 @@ struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version // Dungeon scene will be rendered to this texture. struct texture *texture = sprite_get_texture(sp); + sprite_bind_plugin(sp, &ctx->plugin); glGenRenderbuffers(1, &ctx->depth_buffer); glBindRenderbuffer(GL_RENDERBUFFER, ctx->depth_buffer); @@ -68,6 +73,10 @@ struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version void dungeon_context_free(struct dungeon_context *ctx) { + struct sact_sprite *sp = sact_try_get_sprite(ctx->surface); + if (sp) + sprite_bind_plugin(sp, NULL); + if (ctx->dgn) dgn_free(ctx->dgn); if (ctx->dtx) @@ -248,8 +257,11 @@ static void model_view_matrix(struct camera *camera, mat4 out) glm_lookat(eye, camera->pos, up, out); } -void dungeon_render(struct dungeon_context *ctx) +static void dungeon_render(struct draw_plugin *plugin) { + struct dungeon_context *ctx = (struct dungeon_context *)plugin; + if (!ctx->loaded || !ctx->draw_enabled) + return; struct sact_sprite *sp = sact_get_sprite(ctx->surface); sprite_dirty(sp); struct texture *texture = sprite_get_texture(sp); diff --git a/src/hll/DrawDungeon.c b/src/hll/DrawDungeon.c index 62695b9..6ecdd6e 100644 --- a/src/hll/DrawDungeon.c +++ b/src/hll/DrawDungeon.c @@ -46,12 +46,6 @@ struct dungeon_context *dungeon_get_context(int surface) return current_context; } -void dungeon_update(void) -{ - if (current_context && current_context->loaded && current_context->draw_enabled) - dungeon_render(current_context); -} - static struct dgn_cell *dungeon_get_cell(int surface, int x, int y, int z) { struct dungeon_context *ctx = dungeon_get_context(surface); diff --git a/src/hll/SACT2.c b/src/hll/SACT2.c index ee209bc..5f13b1d 100644 --- a/src/hll/SACT2.c +++ b/src/hll/SACT2.c @@ -151,7 +151,7 @@ int sact_GetMainSurfaceNumber(void) int sact_Update(void) { handle_events(); - dungeon_update(); + sprite_call_plugins(); if (scene_is_dirty) { scene_render(); gfx_swap(); diff --git a/src/sprite.c b/src/sprite.c index 8e6acf5..3a914c2 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 "plugin.h" #include "sprite.h" #include "vm.h" #include "vm/page.h" @@ -36,14 +37,16 @@ bool sact_dirty = true; -TAILQ_HEAD(listhead, sact_sprite) sprite_list = - TAILQ_HEAD_INITIALIZER(sprite_list); +LIST_HEAD(listhead, sact_sprite) sprites_with_plugins = + LIST_HEAD_INITIALIZER(sprites_with_plugins); void sprite_free(struct sact_sprite *sp) { scene_unregister_sprite(&sp->sp); gfx_delete_texture(&sp->texture); gfx_delete_texture(&sp->text.texture); + if (sp->plugin) + LIST_REMOVE(sp, entry); memset(sp, 0, sizeof(struct sact_sprite)); } @@ -322,6 +325,23 @@ void sprite_get_pixel_value(struct sact_sprite *sp, int x, int y, int *r, int *g *b = c.b; } +void sprite_bind_plugin(struct sact_sprite *sp, struct draw_plugin *plugin) +{ + if (!sp->plugin && plugin) + LIST_INSERT_HEAD(&sprites_with_plugins, sp, entry); + else if (sp->plugin && !plugin) + LIST_REMOVE(sp, entry); + sp->plugin = plugin; +} + +void sprite_call_plugins(void) +{ + struct sact_sprite *sp; + LIST_FOREACH(sp, &sprites_with_plugins, entry) { + sp->plugin->update(sp->plugin); + } +} + static void print_color(SDL_Color *c) { printf("(%d,%d,%d,%d)", c->r, c->g, c->b, c->a); @@ -380,6 +400,7 @@ void print_sprite(struct sact_sprite *sp) printf("\t\tpos = "); print_point(&sp->text.pos); printf(",\n"); printf("\t\tchar_space = %d,\n", sp->text.char_space); printf("\t\tline_space = %d,\n", sp->text.line_space); + printf("\t\tplugin = %s,\n", sp->plugin ? sp->plugin->name : "NULL"); printf("\t},\n"); printf("\tcg_no = %d\n", sp->cg_no); printf("}\n");