mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-13 01:38:19 +03:00
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:
+3
-3
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ xsystem4 = ['audio.c',
|
||||
'page.c',
|
||||
'resume.c',
|
||||
'savedata.c',
|
||||
'scene.c',
|
||||
'sprite.c',
|
||||
'system4.c',
|
||||
'text.c',
|
||||
|
||||
+139
@@ -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
@@ -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 };
|
||||
|
||||
Reference in New Issue
Block a user