mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-11 08:48:16 +03:00
draw_plugin: Add free() method
It is called when the plugin is unbound from a sprite, or when the sprite to which the plugin is bound is released. This prevents memory leaks when sprites are destroyed without the plugin being released, and simplifies lifetime management of the DrawDungeon plugin.
This commit is contained in:
@@ -67,8 +67,7 @@ struct dungeon_context {
|
||||
GLuint depth_buffer;
|
||||
};
|
||||
|
||||
struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version, int surface);
|
||||
void dungeon_context_free(struct dungeon_context *ctx);
|
||||
struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version, int width, int height);
|
||||
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_set_walked(int surface, int x, int y, int z, int flag);
|
||||
|
||||
@@ -24,6 +24,7 @@ struct sact_sprite;
|
||||
|
||||
struct draw_plugin {
|
||||
const char *name;
|
||||
void (*free)(struct draw_plugin *);
|
||||
void (*update)(struct sact_sprite *);
|
||||
void (*render)(struct sact_sprite *); // for custom sprites
|
||||
cJSON *(*to_json)(struct sact_sprite *, bool);
|
||||
|
||||
+18
-15
@@ -47,39 +47,42 @@
|
||||
#define M_PI (3.14159265358979323846)
|
||||
#endif
|
||||
|
||||
static const char plugin_name[] = "DrawDungeon";
|
||||
|
||||
static void dungeon_render(struct sact_sprite *sp);
|
||||
static cJSON *dungeon_to_json(struct sact_sprite *sp, bool verbose);
|
||||
static void dungeon_context_free(struct draw_plugin *plugin);
|
||||
|
||||
struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version, int surface)
|
||||
struct dungeon_context *dungeon_get_context(int surface)
|
||||
{
|
||||
struct sact_sprite *sp = sact_try_get_sprite(surface);
|
||||
if (!sp || !sp->plugin || sp->plugin->name != plugin_name)
|
||||
return NULL;
|
||||
return (struct dungeon_context *)sp->plugin;
|
||||
}
|
||||
|
||||
struct dungeon_context *dungeon_context_create(enum draw_dungeon_version version, int width, int height)
|
||||
{
|
||||
struct dungeon_context *ctx = xcalloc(1, sizeof(struct dungeon_context));
|
||||
ctx->plugin.name = "DrawDungeon";
|
||||
ctx->plugin.name = plugin_name;
|
||||
ctx->plugin.free = dungeon_context_free;
|
||||
ctx->plugin.update = dungeon_render;
|
||||
ctx->plugin.to_json = dungeon_to_json;
|
||||
ctx->version = version;
|
||||
ctx->surface = surface;
|
||||
struct sact_sprite *sp = sact_get_sprite(ctx->surface);
|
||||
if (!sp)
|
||||
VM_ERROR("DrawDungeon.Init: invalid surface %d", surface);
|
||||
|
||||
sprite_bind_plugin(sp, &ctx->plugin);
|
||||
|
||||
gfx_init_texture_blank(&ctx->texture, sp->rect.w, sp->rect.h);
|
||||
gfx_init_texture_blank(&ctx->texture, width, height);
|
||||
glGenRenderbuffers(1, &ctx->depth_buffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, ctx->depth_buffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, sp->rect.w, sp->rect.h);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
ctx->map = dungeon_map_create(version);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void dungeon_context_free(struct dungeon_context *ctx)
|
||||
static void dungeon_context_free(struct draw_plugin *plugin)
|
||||
{
|
||||
struct sact_sprite *sp = sact_try_get_sprite(ctx->surface);
|
||||
if (sp)
|
||||
sprite_bind_plugin(sp, NULL);
|
||||
|
||||
struct dungeon_context *ctx = (struct dungeon_context *)plugin;
|
||||
if (ctx->dgn)
|
||||
dgn_free(ctx->dgn);
|
||||
if (ctx->dtx)
|
||||
|
||||
+8
-26
@@ -25,25 +25,18 @@
|
||||
#include "dungeon/map.h"
|
||||
#include "dungeon/renderer.h"
|
||||
#include "dungeon/tes.h"
|
||||
#include "sact.h"
|
||||
#include "hll.h"
|
||||
|
||||
static struct dungeon_context *current_context = NULL;
|
||||
|
||||
static int dungeon_init(enum draw_dungeon_version version, int surface)
|
||||
{
|
||||
if (current_context)
|
||||
VM_ERROR("Dungeon is already associated with surface %d", current_context->surface);
|
||||
if (surface < 0)
|
||||
struct sact_sprite *sp = sact_get_sprite(surface);
|
||||
if (!sp)
|
||||
return 0;
|
||||
current_context = dungeon_context_create(version, surface);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct dungeon_context *dungeon_get_context(int surface)
|
||||
{
|
||||
if (!current_context || surface != current_context->surface)
|
||||
return NULL;
|
||||
return current_context;
|
||||
struct dungeon_context *ctx = dungeon_context_create(version, sp->rect.w, sp->rect.h);
|
||||
sprite_bind_plugin(sp, &ctx->plugin);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct dgn_cell *dungeon_get_cell(int surface, int x, int y, int z)
|
||||
@@ -54,14 +47,6 @@ static struct dgn_cell *dungeon_get_cell(int surface, int x, int y, int z)
|
||||
return dgn_cell_at(ctx->dgn, x, y, z);
|
||||
}
|
||||
|
||||
static void DrawDungeon_ModuleFini(void)
|
||||
{
|
||||
if (current_context) {
|
||||
dungeon_context_free(current_context);
|
||||
current_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int DrawDungeon_Init(int surface)
|
||||
{
|
||||
return dungeon_init(DRAW_DUNGEON_1, surface);
|
||||
@@ -74,11 +59,9 @@ static int DrawDungeon14_Init(int surface)
|
||||
|
||||
static void DrawDungeon_Release(int surface)
|
||||
{
|
||||
struct dungeon_context *ctx = dungeon_get_context(surface);
|
||||
if (!ctx)
|
||||
if (!dungeon_get_context(surface))
|
||||
return;
|
||||
dungeon_context_free(ctx);
|
||||
current_context = NULL;
|
||||
sprite_bind_plugin(sact_get_sprite(surface), NULL);
|
||||
}
|
||||
|
||||
static void DrawDungeon_SetDrawFlag(int surface, int flag)
|
||||
@@ -284,7 +267,6 @@ HLL_QUIET_UNIMPLEMENTED( , void, DrawDungeon, StopTimer, void);
|
||||
HLL_QUIET_UNIMPLEMENTED( , void, DrawDungeon, RestartTimer, void);
|
||||
|
||||
#define DRAW_DUNGEON_EXPORTS \
|
||||
HLL_EXPORT(_ModuleFini, DrawDungeon_ModuleFini), \
|
||||
HLL_EXPORT(Release, DrawDungeon_Release), \
|
||||
HLL_EXPORT(SetDrawFlag, DrawDungeon_SetDrawFlag), \
|
||||
HLL_EXPORT(BeginLoad, DrawDungeon_BeginLoad), \
|
||||
|
||||
+7
-3
@@ -45,6 +45,11 @@ static struct draw_rain_plugin *get_draw_rain_plugin(int surface)
|
||||
return (struct draw_rain_plugin *)sp->plugin;
|
||||
}
|
||||
|
||||
static void DrawRain_free(struct draw_plugin *plugin)
|
||||
{
|
||||
free(plugin);
|
||||
}
|
||||
|
||||
static void DrawRain_update(struct sact_sprite *sp)
|
||||
{
|
||||
struct draw_rain_plugin *plugin = (struct draw_rain_plugin *)sp->plugin;
|
||||
@@ -95,6 +100,7 @@ static int DrawRain_Init(int surface)
|
||||
}
|
||||
struct draw_rain_plugin *plugin = xcalloc(1, sizeof(struct draw_rain_plugin));
|
||||
plugin->p.name = plugin_name;
|
||||
plugin->p.free = DrawRain_free;
|
||||
plugin->p.update = DrawRain_update;
|
||||
plugin->p.to_json = DrawRain_to_json;
|
||||
plugin->nr_lines = 1000;
|
||||
@@ -107,11 +113,9 @@ static int DrawRain_Init(int surface)
|
||||
|
||||
static void DrawRain_Release(int surface)
|
||||
{
|
||||
struct draw_rain_plugin *plugin = get_draw_rain_plugin(surface);
|
||||
if (!plugin)
|
||||
if (!get_draw_rain_plugin(surface))
|
||||
return;
|
||||
sprite_bind_plugin(sact_get_sprite(surface), NULL);
|
||||
free(plugin);
|
||||
}
|
||||
|
||||
static void DrawRain_SetNumofLine(int surface, int line)
|
||||
|
||||
@@ -52,6 +52,13 @@ static struct draw_ripple_plugin *get_draw_ripple_plugin(int surface)
|
||||
return (struct draw_ripple_plugin *)sp->plugin;
|
||||
}
|
||||
|
||||
static void DrawRipple_free(struct draw_plugin *_plugin)
|
||||
{
|
||||
struct draw_ripple_plugin *plugin = (struct draw_ripple_plugin *)_plugin;
|
||||
free(plugin->ripples);
|
||||
free(plugin);
|
||||
}
|
||||
|
||||
static void draw_point(uint32_t *pixels, int w, int h, int x, int y)
|
||||
{
|
||||
if (x < 0 || x >= w || y < 0 || y >= h)
|
||||
@@ -163,6 +170,7 @@ static int DrawRipple_Init(int surface)
|
||||
}
|
||||
struct draw_ripple_plugin *plugin = xcalloc(1, sizeof(struct draw_ripple_plugin));
|
||||
plugin->p.name = plugin_name;
|
||||
plugin->p.free = DrawRipple_free;
|
||||
plugin->p.update = DrawRipple_update;
|
||||
plugin->p.to_json = DrawRipple_to_json;
|
||||
plugin->width = 6;
|
||||
@@ -175,12 +183,9 @@ static int DrawRipple_Init(int surface)
|
||||
|
||||
static void DrawRipple_Release(int surface)
|
||||
{
|
||||
struct draw_ripple_plugin *plugin = get_draw_ripple_plugin(surface);
|
||||
if (!plugin)
|
||||
if (!get_draw_ripple_plugin(surface))
|
||||
return;
|
||||
sprite_bind_plugin(sact_get_sprite(surface), NULL);
|
||||
free(plugin->ripples);
|
||||
free(plugin);
|
||||
}
|
||||
|
||||
static void DrawRipple_SetNumof(int surface, int numof)
|
||||
|
||||
+9
-4
@@ -70,6 +70,13 @@ static struct draw_snow_plugin *get_draw_snow_plugin(int sprite)
|
||||
return (struct draw_snow_plugin *)sp->plugin;
|
||||
}
|
||||
|
||||
static void DrawSnow_free(struct draw_plugin *_plugin)
|
||||
{
|
||||
struct draw_snow_plugin *plugin = (struct draw_snow_plugin *)_plugin;
|
||||
free(plugin->particles);
|
||||
free(plugin);
|
||||
}
|
||||
|
||||
static void DrawSnow_update(struct sact_sprite *sp)
|
||||
{
|
||||
struct draw_snow_plugin *plugin = (struct draw_snow_plugin *)sp->plugin;
|
||||
@@ -131,6 +138,7 @@ static void DrawSnow_Init(int sprite, int width, int height)
|
||||
{
|
||||
struct draw_snow_plugin *plugin = xcalloc(1, sizeof(struct draw_snow_plugin));
|
||||
plugin->p.name = plugin_name;
|
||||
plugin->p.free = DrawSnow_free;
|
||||
plugin->p.update = DrawSnow_update;
|
||||
plugin->p.render = DrawSnow_render;
|
||||
plugin->p.to_json = DrawSnow_to_json;
|
||||
@@ -147,12 +155,9 @@ static void DrawSnow_Init(int sprite, int width, int height)
|
||||
|
||||
static void DrawSnow_Release(int sprite)
|
||||
{
|
||||
struct draw_snow_plugin *plugin = get_draw_snow_plugin(sprite);
|
||||
if (!plugin)
|
||||
if (!get_draw_snow_plugin(sprite))
|
||||
return;
|
||||
sprite_bind_plugin(sact_get_sprite(sprite), NULL);
|
||||
free(plugin->particles);
|
||||
free(plugin);
|
||||
}
|
||||
|
||||
static void DrawSnow_Start(int sprite)
|
||||
|
||||
+5
-1
@@ -54,8 +54,10 @@ 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)
|
||||
if (sp->plugin && sp->plugin->free) {
|
||||
sp->plugin->free(sp->plugin);
|
||||
LIST_REMOVE(sp, entry);
|
||||
}
|
||||
// restore to initial state
|
||||
memset(sp, 0, sizeof(struct sact_sprite));
|
||||
sprite_init(sp);
|
||||
@@ -470,6 +472,8 @@ void sprite_bind_plugin(struct sact_sprite *sp, struct draw_plugin *plugin)
|
||||
LIST_INSERT_HEAD(&sprites_with_plugins, sp, entry);
|
||||
else if (sp->plugin && !plugin)
|
||||
LIST_REMOVE(sp, entry);
|
||||
if (sp->plugin != plugin && sp->plugin && sp->plugin->free)
|
||||
sp->plugin->free(sp->plugin);
|
||||
sp->plugin = plugin;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user