Refactor sprite/scene management code

Create a separate interface for managing the scene. The sact_sprite
interface is implemented on top of this, as is GoatGUIEngine (which is
now independent of sact_sprite).

This will allow more specialized graphics interfaces to be implemented
without adding to the complexity of the sact_sprite interace. (For
example, GoatGUIEngine needs to store multiple textures per sprite for
button states; this is not supported by sact_sprite.)
This commit is contained in:
Nunuhara Cabbage
2021-05-21 18:56:33 -07:00
parent b1c55d6f03
commit dd985a3769
9 changed files with 316 additions and 222 deletions
+3 -3
View File
@@ -25,8 +25,8 @@ struct sact_sprite *sact_try_get_sprite(int sp);
struct sact_sprite *sact_create_sprite(int sp_no, int width, int height, int r, int g, int b, int a);
void sact_ModuleFini(void);
int sact_Init(void *_, int cg_cache_size);
#define sact_SetWP sprite_set_wp
#define sact_SetWP_Color sprite_set_wp_color
#define sact_SetWP scene_set_wp
#define sact_SetWP_Color scene_set_wp_color
int sact_GetScreenWidth(void);
int sact_GetScreenHeight(void);
int sact_GetMainSurfaceNumber(void);
@@ -35,7 +35,7 @@ int sact_Effect(int type, int time, int key);
int sact_SP_GetUnuseNum(int min);
int sact_SP_Count(void);
int sact_SP_Enum(struct page **array);
#define sact_SP_GetMaxZ sprite_get_max_z
#define sact_SP_GetMaxZ scene_get_max_z
int sact_SP_SetCG(int sp, int cg);
int sact_SP_Create(int sp, int width, int height, int r, int g, int b, int a);
int sact_SP_CreatePixelOnly(int sp, int width, int height);
+82
View File
@@ -0,0 +1,82 @@
/* Copyright (C) 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
*
* 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 <http://gnu.org/licenses/>.
*/
#ifndef SYSTEM4_SCENE_H
#define SYSTEM4_SCENE_H
#include <stdbool.h>
#include "queue.h"
struct sprite {
TAILQ_ENTRY(sprite) entry;
// The Z-layer of the sprite within the scene
int z;
// The secondary Z-layer (for GoatGUIEngine)
int z2;
// If a sprite does not have pixel data, it will not be added to the scene.
bool has_pixel;
bool has_alpha;
// When a sprite is hidden, it is removed from the scene.
bool hidden;
// This flag indicates whether or not the sprite is included in the
// the current scene. A sprite should be in the scene if there is pixel
// or text data attached to it and it is not hidden.
bool in_scene;
// The rendering function.
void (*render)(struct sprite*);
};
extern bool scene_is_dirty;
void scene_register_sprite(struct sprite *sp);
void scene_unregister_sprite(struct sprite *sp);
void scene_render(void);
void scene_flip(void);
int scene_set_wp(int cg_no);
int scene_set_wp_color(int r, int g, int b);
int scene_get_max_z(void);
void scene_set_sprite_z(struct sprite *sp, int z);
void scene_set_sprite_z2(struct sprite *sp, int z, int z2);
static inline void scene_sprite_dirty(struct sprite *sp)
{
if (!sp)
return;
scene_is_dirty = true;
if (sp->hidden) {
scene_unregister_sprite(sp);
} else if (sp->has_pixel) {
scene_register_sprite(sp);
}
}
static inline void scene_dirty(void)
{
scene_is_dirty = true;
}
static inline void scene_set_sprite_show(struct sprite *sp, bool show)
{
sp->hidden = !show;
scene_sprite_dirty(sp);
}
static inline bool scene_get_sprite_show(struct sprite *sp)
{
return !sp->hidden;
}
#endif /* SYSTEM4_SCENE_H */
+10 -47
View File
@@ -21,12 +21,14 @@
#include <SDL.h>
#include "queue.h"
#include "gfx/gfx.h"
#include "scene.h"
struct string;
struct page;
union vm_value;
struct sact_sprite {
struct sprite sp;
TAILQ_ENTRY(sact_sprite) entry;
// The sprite's texture (CG or solid color). Initialized lazily.
struct texture texture;
@@ -44,79 +46,40 @@ struct sact_sprite {
int char_space;
int line_space;
} text;
// The Z-layer of the sprite within the scene.
int z;
// The secondary Z-layer (for GoatGUIEngine)
int z2;
// This flag indicates that pixel data has been attached to a sprite; it
// does NOT guarantee that the texture is initialized.
bool has_pixel;
bool has_alpha;
// This flag indicates whether or not the sprite is included in the
// the current scene. A sprite should be in the scene if there is pixel
// or text data attached to it and it is not hidden.
bool in_scene;
// When a sprite is hidden, it is removed from the scene. Attaching new
// pixel data does not alter the state of this flag.
bool hidden;
// The sprite handle
int no;
// The CG number attached to the sprite.
int cg_no;
// The rendering function
void (*render)(struct sact_sprite*);
};
extern bool sact_dirty;
void sprite_register(struct sact_sprite *sp);
void sprite_unregister(struct sact_sprite *sp);
static inline void sprite_dirty(struct sact_sprite *sp)
{
if (!sp)
return;
sact_dirty = true;
if (sp->hidden) {
sprite_unregister(sp);
} else if (sp->has_pixel || sp->text.texture.handle) {
sprite_register(sp);
}
}
static inline void scene_dirty(void)
{
sact_dirty = true;
scene_sprite_dirty(&sp->sp);
}
void sprite_free(struct sact_sprite *sp);
void sprite_render_scene(void);
void sprite_flip(void);
struct texture *sprite_get_texture(struct sact_sprite *sp);
int sprite_set_wp(int cg_no);
int sprite_set_wp_color(int r, int g, int b);
int sprite_set_cg(struct sact_sprite *sp, int cg_no);
int sprite_set_cg_from_file(struct sact_sprite *sp, const char *path);
void sprite_init(struct sact_sprite *sp, int w, int h, int r, int g, int b, int a);
int sprite_get_max_z(void);
void sprite_set_pos(struct sact_sprite *sp, int x, int y);
void sprite_set_x(struct sact_sprite *sp, int x);
void sprite_set_y(struct sact_sprite *sp, int y);
void sprite_set_z(struct sact_sprite *sp, int z);
void sprite_set_z2(struct sact_sprite *sp, int z, int z2);
static inline void sprite_set_z(struct sact_sprite *sp, int z) { scene_set_sprite_z(&sp->sp, z); }
static inline void sprite_set_z2(struct sact_sprite *sp, int z, int z2) { scene_set_sprite_z2(&sp->sp, z, z2); }
int sprite_get_blend_rate(struct sact_sprite *sp);
void sprite_set_blend_rate(struct sact_sprite *sp, int rate);
void sprite_set_show(struct sact_sprite *sp, bool show);
static inline void sprite_set_show(struct sact_sprite *sp, bool show) { scene_set_sprite_show(&sp->sp, show); }
int sprite_set_draw_method(struct sact_sprite *sp, int method);
int sprite_get_draw_method(struct sact_sprite *sp);
int sprite_exists_alpha(struct sact_sprite *sp);
static inline int sprite_exists_alpha(struct sact_sprite *sp) { return sp->sp.has_alpha; }
static inline int sprite_get_pos_x(struct sact_sprite *sp) { return sp->rect.x; }
static inline int sprite_get_pos_y(struct sact_sprite *sp) { return sp->rect.y; }
static inline int sprite_get_width(struct sact_sprite *sp) { return sp->rect.w; }
static inline int sprite_get_height(struct sact_sprite *sp) { return sp->rect.h; }
static inline int sprite_get_z(struct sact_sprite *sp) { return sp->z; }
static inline int sprite_get_z2(struct sact_sprite *sp) { return sp->z2; }
static inline int sprite_get_show(struct sact_sprite *sp) { return !sp->hidden; }
static inline int sprite_get_z(struct sact_sprite *sp) { return sp->sp.z; }
static inline int sprite_get_z2(struct sact_sprite *sp) { return sp->sp.z2; }
static inline int sprite_get_show(struct sact_sprite *sp) { return !sp->sp.hidden; }
void sprite_set_text_home(struct sact_sprite *sp, int x, int y);
void sprite_set_text_line_space(struct sact_sprite *sp, int px);
void sprite_set_text_char_space(struct sact_sprite *sp, int px);
+2 -2
View File
@@ -105,7 +105,7 @@ int sact_Effect(int type, possibly_unused int time, possibly_unused int key)
// get old & new scene textures
Texture old, new;
gfx_copy_main_surface(&old);
sprite_render_scene();
scene_render();
gfx_copy_main_surface(&new);
effect_callback effect = effects[type];
@@ -143,7 +143,7 @@ int sact_TRANS_Begin(int type)
trans.on = true;
trans.type = type;
gfx_copy_main_surface(&trans.old);
sprite_render_scene();
scene_render();
gfx_copy_main_surface(&trans.new);
return 1;
}
+57 -37
View File
@@ -16,13 +16,15 @@
#include <assert.h>
#include "system4/cg.h"
#include "system4/hashtable.h"
#include <cglm/cglm.h>
#include "asset_manager.h"
#include "gfx/gfx.h"
#include "input.h"
#include "queue.h"
#include "sprite.h"
#include "scene.h"
#include "xsystem4.h"
#include "hll.h"
@@ -71,7 +73,9 @@ struct parts_motion {
};
struct parts {
struct sact_sprite sp;
struct sprite sp;
Texture texture;
unsigned cg_no;
TAILQ_ENTRY(parts) parts_list_entry;
int no;
int sprite_deform;
@@ -80,6 +84,7 @@ struct parts {
int on_cursor_sound;
int on_click_sound;
int origin_mode;
Rectangle rect;
// The actual hitbox of the sprite (accounting for origin-mode, scale, etc)
Rectangle pos;
struct { float x, y; } scale;
@@ -87,7 +92,7 @@ struct parts {
TAILQ_HEAD(, parts_motion) motion;
};
static void parts_render(struct sact_sprite *sp);
static void parts_render(struct sprite *sp);
static struct hash_table *parts_table = NULL;
static TAILQ_HEAD(listhead, parts) parts_list = TAILQ_HEAD_INITIALIZER(parts_list);
@@ -167,7 +172,8 @@ static void parts_clear_motion(struct parts *parts)
static void parts_clear(struct parts *parts)
{
parts_clear_motion(parts);
sprite_free(&parts->sp);
scene_unregister_sprite(&parts->sp);
gfx_delete_texture(&parts->texture);
}
static void parts_release(int parts_no)
@@ -285,48 +291,56 @@ static void origin_mode_translate(mat4 dst, int mode, int w, int h)
static void parts_recalculate_pos(struct parts *parts)
{
int x, y;
origin_mode_offset(parts->origin_mode, parts->sp.rect.w, parts->sp.rect.h, &x, &y);
origin_mode_offset(parts->origin_mode, parts->rect.w, parts->rect.h, &x, &y);
parts->pos = (Rectangle) {
.x = parts->sp.rect.x + x,
.y = parts->sp.rect.y + y,
.w = parts->sp.rect.w,
.h = parts->sp.rect.h,
.x = parts->rect.x + x,
.y = parts->rect.y + y,
.w = parts->rect.w,
.h = parts->rect.h,
};
}
static void parts_set_pos(struct parts *parts, Point pos)
{
sprite_set_pos(&parts->sp, pos.x, pos.y);
parts->rect.x = pos.x;
parts->rect.y = pos.y;
parts_recalculate_pos(parts);
scene_sprite_dirty(&parts->sp);
}
static void parts_set_scale_x(struct parts *parts, float mag)
{
parts->scale.x = mag;
parts_recalculate_pos(parts);
sprite_dirty(&parts->sp);
scene_sprite_dirty(&parts->sp);
}
static void parts_set_scale_y(struct parts *parts, float mag)
{
parts->scale.y = mag;
parts_recalculate_pos(parts);
sprite_dirty(&parts->sp);
scene_sprite_dirty(&parts->sp);
}
static void parts_set_rotation_z(struct parts *parts, float rot)
{
parts->rotation.z = rot;
sprite_dirty(&parts->sp);
scene_sprite_dirty(&parts->sp);
}
static void parts_render(struct sact_sprite *sp)
static void parts_set_alpha(struct parts *parts, int alpha)
{
parts->texture.alpha_mod = max(0, min(255, alpha));
scene_sprite_dirty(&parts->sp);
}
static void parts_render(struct sprite *sp)
{
struct parts *parts = (struct parts*)sp;
if (!parts->sp.cg_no)
if (!parts->cg_no)
return;
Rectangle *d = &parts->sp.rect;
Rectangle *d = &parts->rect;
mat4 mw_transform = GLM_MAT4_IDENTITY_INIT;
glm_translate(mw_transform, (vec3) { d->x, d->y, 0 });
// FIXME: need perspective for 3D rotate
@@ -341,10 +355,10 @@ static void parts_render(struct sact_sprite *sp)
struct gfx_render_job job = {
.shader = NULL, // default shader
.texture = parts->sp.texture.handle,
.texture = parts->texture.handle,
.world_transform = mw_transform[0],
.view_transform = wv_transform[0],
.data = &parts->sp.texture,
.data = &parts->texture,
};
gfx_render(&job);
@@ -357,7 +371,7 @@ static void parts_update_with_motion(struct parts *parts, struct parts_motion *m
parts_set_pos(parts, motion_calculate_point(motion, motion_t));
break;
case PARTS_MOTION_ALPHA:
sprite_set_blend_rate(&parts->sp, motion_calculate_i(motion, motion_t));
parts_set_alpha(parts, motion_calculate_i(motion, motion_t));
break;
case PARTS_MOTION_MAG_X:
parts_set_scale_x(parts, motion_calculate_f(motion, motion_t));
@@ -472,15 +486,26 @@ static void GoatGUIEngine_Update(possibly_unused int passed_time, possibly_unuse
static bool GoatGUIEngine_SetPartsCG(int parts_no, int cg_no, possibly_unused int sprite_deform, possibly_unused int state)
{
struct parts *parts = parts_get(parts_no);
if (!sprite_set_cg(&parts->sp, cg_no))
struct cg *cg = asset_cg_load(cg_no);
if (!cg)
return false;
gfx_delete_texture(&parts->texture);
gfx_init_texture_with_cg(&parts->texture, cg);
parts->rect.w = cg->metrics.w;
parts->rect.h = cg->metrics.h;
parts->cg_no = cg_no;
parts->sp.has_pixel = true;
parts->sp.has_alpha = cg->metrics.has_alpha;
parts->sp.render = parts_render;
parts_recalculate_pos(parts);
scene_sprite_dirty(&parts->sp);
cg_free(cg);
return true;
}
static int GoatGUIEngine_GetPartsCGNumber(int parts_no, possibly_unused int state)
{
return parts_get(parts_no)->sp.cg_no;
return parts_get(parts_no)->cg_no;
}
bool GoatGUIEngine_SetLoopCG(int PartsNumber, int CGNumber, int NumofCG, int TimePerCG, int State);
@@ -548,9 +573,7 @@ static void GoatGUIEngine_ReleaseAllPartsWithoutSystem(void)
static void GoatGUIEngine_SetPos(int parts_no, int x, int y)
{
struct parts *parts = parts_get(parts_no);
sprite_set_pos(&parts->sp, x, y);
parts_recalculate_pos(parts);
parts_set_pos(parts_get(parts_no), (Point){ x, y });
}
/*
@@ -561,52 +584,49 @@ static void GoatGUIEngine_SetPos(int parts_no, int x, int y)
*/
static void GoatGUIEngine_SetZ(int parts_no, int z)
{
sprite_set_z2(&parts_get(parts_no)->sp, 0, z+1);
scene_set_sprite_z2(&parts_get(parts_no)->sp, 0, z+1);
}
static void GoatGUIEngine_SetShow(int parts_no, bool show)
{
struct parts *parts = parts_get(parts_no);
sprite_set_show(&parts->sp, show);
scene_set_sprite_show(&parts_get(parts_no)->sp, show);
}
static void GoatGUIEngine_SetAlpha(int parts_no, int alpha)
{
struct parts *parts = parts_get(parts_no);
sprite_set_blend_rate(&parts->sp, alpha);
parts_set_alpha(parts_get(parts_no), alpha);
}
void GoatGUIEngine_SetPartsDrawFilter(int PartsNumber, int DrawFilter);
static void GoatGUIEngine_SetClickable(int parts_no, bool clickable)
{
struct parts *parts = parts_get(parts_no);
parts->clickable = !!clickable;
parts_get(parts_no)->clickable = !!clickable;
}
static int GoatGUIEngine_GetPartsX(int parts_no)
{
return sprite_get_pos_x(&parts_get(parts_no)->sp);
return parts_get(parts_no)->rect.x;
}
static int GoatGUIEngine_GetPartsY(int parts_no)
{
return sprite_get_pos_y(&parts_get(parts_no)->sp);
return parts_get(parts_no)->rect.y;
}
static int GoatGUIEngine_GetPartsZ(int parts_no)
{
return sprite_get_z2(&parts_get(parts_no)->sp) - 1;
return parts_get(parts_no)->sp.z2 - 1;
}
static bool GoatGUIEngine_GetPartsShow(int parts_no)
{
return sprite_get_show(&parts_get(parts_no)->sp);
return scene_get_sprite_show(&parts_get(parts_no)->sp);
}
static int GoatGUIEngine_GetPartsAlpha(int parts_no)
{
return sprite_get_blend_rate(&parts_get(parts_no)->sp);
return parts_get(parts_no)->texture.alpha_mod;
}
static bool GoatGUIEngine_GetPartsClickable(int parts_no)
@@ -619,7 +639,7 @@ static void GoatGUIEngine_SetPartsOriginPosMode(int parts_no, int origin_pos_mod
struct parts *parts = parts_get(parts_no);
parts->origin_mode = origin_pos_mode;
parts_recalculate_pos(parts);
sprite_dirty(&parts->sp);
scene_sprite_dirty(&parts->sp);
}
static int GoatGUIEngine_GetPartsOriginPosMode(int parts_no)
+5 -4
View File
@@ -29,6 +29,7 @@
#include "queue.h"
#include "gfx/gfx.h"
#include "sact.h"
#include "scene.h"
#include "vm/page.h"
#include "dungeon/dungeon.h"
#include "xsystem4.h"
@@ -135,9 +136,9 @@ int sact_Update(void)
{
handle_events();
dungeon_update();
if (sact_dirty) {
sprite_render_scene();
sprite_flip();
if (scene_is_dirty) {
scene_render();
scene_flip();
}
return 1;
}
@@ -577,7 +578,7 @@ int sact_SP_GetAMapValue(int sp_no, int x, int y)
if (!sp) return -1;
if (x < 0 || x >= sp->rect.w || y < 0 || y >= sp->rect.h)
return -1;
if (!sp->has_alpha)
if (!sp->sp.has_alpha)
return -1;
return sprite_get_amap_value(sp, x, y);
}
+1
View File
@@ -12,6 +12,7 @@ xsystem4 = ['audio.c',
'page.c',
'resume.c',
'savedata.c',
'scene.c',
'sprite.c',
'system4.c',
'text.c',
+139
View File
@@ -0,0 +1,139 @@
/* Copyright (C) 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
*
* 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 <http://gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <stddef.h>
#include "system4.h"
#include "system4/cg.h"
#include "asset_manager.h"
#include "gfx/gfx.h"
#include "queue.h"
#include "scene.h"
bool scene_is_dirty = true;
static TAILQ_HEAD(listhead, sprite) sprite_list = TAILQ_HEAD_INITIALIZER(sprite_list);
static Texture wp = {0};
void scene_register_sprite(struct sprite *sp)
{
if (sp->in_scene)
return;
struct sprite *p;
TAILQ_FOREACH(p, &sprite_list, entry) {
if (p->z == sp->z) {
if (p->z2 > sp->z2) {
TAILQ_INSERT_BEFORE(p, sp, entry);
sp->in_scene = true;
return;
}
} else if (p->z > sp->z) {
TAILQ_INSERT_BEFORE(p, sp, entry);
sp->in_scene = true;
return;
}
}
TAILQ_INSERT_TAIL(&sprite_list, sp, entry);
sp->in_scene = true;
scene_dirty();
}
void scene_unregister_sprite(struct sprite *sp)
{
if (!sp->in_scene)
return;
TAILQ_REMOVE(&sprite_list, sp, entry);
sp->in_scene = false;
scene_dirty();
}
void scene_render(void)
{
gfx_clear();
if (wp.handle) {
Rectangle r = RECT(0, 0, wp.w, wp.h);
gfx_render_texture(&wp, &r);
}
struct sprite *sp;
TAILQ_FOREACH(sp, &sprite_list, entry) {
if (sp->render)
sp->render(sp);
else
WARNING("sprite in scene without render function");
}
}
void scene_flip(void)
{
gfx_swap();
scene_is_dirty = false;
}
int scene_set_wp(int cg_no) {
if (!cg_no) {
gfx_delete_texture(&wp);
scene_dirty();
return 1;
}
struct cg *cg = asset_cg_load(cg_no);
if (!cg)
return 0;
gfx_delete_texture(&wp);
gfx_init_texture_with_cg(&wp, cg);
cg_free(cg);
scene_dirty();
return 1;
}
int scene_set_wp_color(int r, int g, int b)
{
gfx_set_clear_color(r, g, b, 255);
scene_dirty();
return 1;
}
int scene_get_max_z(void)
{
if (TAILQ_EMPTY(&sprite_list))
return 0;
return TAILQ_LAST(&sprite_list, listhead)->z;
}
void scene_set_sprite_z(struct sprite *sp, int z)
{
sp->z = z;
if (sp->in_scene) {
scene_unregister_sprite(sp);
scene_register_sprite(sp);
}
}
void scene_set_sprite_z2(struct sprite *sp, int z, int z2)
{
sp->z = z;
sp->z2 = z2;
if (sp->in_scene) {
scene_unregister_sprite(sp);
scene_register_sprite(sp);
}
}
+17 -129
View File
@@ -33,47 +33,12 @@
bool sact_dirty = true;
static struct sact_sprite wp;
TAILQ_HEAD(listhead, sact_sprite) sprite_list =
TAILQ_HEAD_INITIALIZER(sprite_list);
void sprite_register(struct sact_sprite *sp)
{
if (sp->in_scene)
return;
struct sact_sprite *p;
TAILQ_FOREACH(p, &sprite_list, entry) {
if (p->z == sp->z) {
if (p->z2 > sp->z2) {
TAILQ_INSERT_BEFORE(p, sp, entry);
sp->in_scene = true;
return;
}
} else if (p->z > sp->z) {
TAILQ_INSERT_BEFORE(p, sp, entry);
sp->in_scene = true;
return;
}
}
TAILQ_INSERT_TAIL(&sprite_list, sp, entry);
sp->in_scene = true;
scene_dirty();
}
void sprite_unregister(struct sact_sprite *sp)
{
if (!sp->in_scene)
return;
TAILQ_REMOVE(&sprite_list, sp, entry);
sp->in_scene = false;
scene_dirty();
}
void sprite_free(struct sact_sprite *sp)
{
sprite_unregister(sp);
scene_unregister_sprite(&sp->sp);
gfx_delete_texture(&sp->texture);
gfx_delete_texture(&sp->text.texture);
memset(sp, 0, sizeof(struct sact_sprite));
@@ -82,38 +47,21 @@ void sprite_free(struct sact_sprite *sp)
static void sprite_init_texture(struct sact_sprite *sp)
{
if (!sp->texture.handle) {
if (sp->has_alpha)
if (sp->sp.has_alpha)
gfx_init_texture_rgba(&sp->texture, sp->rect.w, sp->rect.h, sp->color);
else
gfx_init_texture_rgb(&sp->texture, sp->rect.w, sp->rect.h, sp->color);
}
}
void sprite_render_scene(void)
static void sprite_render(struct sprite *_sp)
{
gfx_clear();
if (wp.texture.handle) {
Rectangle r = RECT(0, 0, wp.texture.w, wp.texture.h);
gfx_render_texture(&wp.texture, &r);
struct sact_sprite *sp = (struct sact_sprite*)_sp;
sprite_init_texture(sp);
gfx_render_texture(&sp->texture, &sp->rect);
if (sp->text.texture.handle) {
gfx_render_texture(&sp->text.texture, &sp->rect);
}
struct sact_sprite *p;
TAILQ_FOREACH(p, &sprite_list, entry) {
if (p->render) {
p->render(p);
} else {
sprite_init_texture(p);
gfx_render_texture(&p->texture, &p->rect);
if (p->text.texture.handle) {
gfx_render_texture(&p->text.texture, &p->rect);
}
}
}
}
void sprite_flip(void)
{
gfx_swap();
sact_dirty = false;
}
struct texture *sprite_get_texture(struct sact_sprite *sp)
@@ -122,32 +70,6 @@ struct texture *sprite_get_texture(struct sact_sprite *sp)
return &sp->texture;
}
int sprite_set_wp(int cg_no)
{
if (!cg_no) {
gfx_delete_texture(&wp.texture);
return 1;
}
struct cg *cg = asset_cg_load(cg_no);
if (!cg)
return 0;
gfx_delete_texture(&wp.texture);
gfx_init_texture_with_cg(&wp.texture, cg);
cg_free(cg);
scene_dirty();
return 1;
}
int sprite_set_wp_color(int r, int g, int b)
{
gfx_set_clear_color(r, g, b, 255);
scene_dirty();
return 1;
}
int sprite_set_cg(struct sact_sprite *sp, int cg_no)
{
struct cg *cg = asset_cg_load(cg_no);
@@ -158,8 +80,9 @@ int sprite_set_cg(struct sact_sprite *sp, int cg_no)
sp->rect.w = cg->metrics.w;
sp->rect.h = cg->metrics.h;
sp->cg_no = cg_no;
sp->has_pixel = true;
sp->has_alpha = cg->metrics.has_alpha;
sp->sp.has_pixel = true;
sp->sp.has_alpha = cg->metrics.has_alpha;
sp->sp.render = sprite_render;
sprite_dirty(sp);
cg_free(cg);
return 1;
@@ -174,8 +97,9 @@ int sprite_set_cg_from_file(struct sact_sprite *sp, const char *path)
gfx_init_texture_with_cg(&sp->texture, cg);
sp->rect.w = cg->metrics.w;
sp->rect.h = cg->metrics.h;
sp->has_pixel = true;
sp->has_alpha = cg->metrics.has_alpha;
sp->sp.has_pixel = true;
sp->sp.has_alpha = cg->metrics.has_alpha;
sp->sp.render = sprite_render;
sprite_dirty(sp);
cg_free(cg);
return 1;
@@ -191,18 +115,12 @@ void sprite_init(struct sact_sprite *sp, int w, int h, int r, int g, int b, int
sp->rect.h = h;
gfx_delete_texture(&sp->texture);
sp->has_pixel = true;
sp->has_alpha = a >= 0;
sp->sp.has_pixel = true;
sp->sp.has_alpha = a >= 0;
sp->sp.render = sprite_render;
sprite_dirty(sp);
}
int sprite_get_max_z(void)
{
if (TAILQ_EMPTY(&sprite_list))
return 0;
return TAILQ_LAST(&sprite_list, listhead)->z;
}
void sprite_set_pos(struct sact_sprite *sp, int x, int y)
{
sp->rect.x = x;
@@ -222,25 +140,6 @@ void sprite_set_y(struct sact_sprite *sp, int y)
sprite_dirty(sp);
}
void sprite_set_z(struct sact_sprite *sp, int z)
{
sp->z = z;
if (sp->in_scene) {
sprite_unregister(sp);
sprite_register(sp);
}
}
void sprite_set_z2(struct sact_sprite *sp, int z, int z2)
{
sp->z = z;
sp->z2 = z2;
if (sp->in_scene) {
sprite_unregister(sp);
sprite_register(sp);
}
}
int sprite_get_blend_rate(struct sact_sprite *sp)
{
return sprite_get_texture(sp)->alpha_mod;
@@ -252,12 +151,6 @@ void sprite_set_blend_rate(struct sact_sprite *sp, int rate)
sprite_dirty(sp);
}
void sprite_set_show(struct sact_sprite *sp, bool show)
{
sp->hidden = !show;
sprite_dirty(sp);
}
int sprite_set_draw_method(struct sact_sprite *sp, int method)
{
if (method < 0 || method >= NR_DRAW_METHODS) {
@@ -274,11 +167,6 @@ int sprite_get_draw_method(struct sact_sprite *sp)
return sprite_get_texture(sp)->draw_method;
}
int sprite_exists_alpha(struct sact_sprite *sp)
{
return sp->has_alpha;
}
void sprite_set_text_home(struct sact_sprite *sp, int x, int y)
{
sp->text.home = (Point) { .x = x, .y = y };