mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-09-22 22:48:08 +03:00
Refactor sdl_fader.c
Restructured the code in an object-oriented style to make it easier to add new kinds of faders.
This commit is contained in:
+139
-74
@@ -27,11 +27,7 @@
|
||||
#include "sdl_core.h"
|
||||
#include "sdl_private.h"
|
||||
|
||||
struct sdl_fader {
|
||||
SDL_Texture *tx_old, *tx_new, *tx_tmp;
|
||||
SDL_Rect dst_rect;
|
||||
enum sdl_effect effect;
|
||||
};
|
||||
#define HAS_SDL_RenderGeometry SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
|
||||
enum sdl_effect from_nact_effect(enum nact_effect effect) {
|
||||
switch (effect) {
|
||||
@@ -61,7 +57,102 @@ enum sdl_effect from_sact_effect(enum sact_effect effect) {
|
||||
}
|
||||
}
|
||||
|
||||
#define HAS_SDL_RenderGeometry SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
struct sdl_fader {
|
||||
void (*step)(struct sdl_fader *this, int step);
|
||||
void (*finish)(struct sdl_fader *this);
|
||||
enum sdl_effect effect;
|
||||
SDL_Rect dst_rect;
|
||||
SDL_Texture *tx_old, *tx_new;
|
||||
};
|
||||
|
||||
static void fader_init(struct sdl_fader *fader, int sx, int sy, int w, int h, int dx, int dy, enum sdl_effect effect) {
|
||||
fader->effect = effect;
|
||||
fader->dst_rect.x = dx;
|
||||
fader->dst_rect.y = dy;
|
||||
fader->dst_rect.w = w;
|
||||
fader->dst_rect.h = h;
|
||||
|
||||
SDL_Surface *sf_old = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_RGB888);
|
||||
SDL_Surface *sf_new = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_RGB888);
|
||||
|
||||
SDL_Rect src_rect = { sx, sy, w, h };
|
||||
SDL_BlitSurface(sdl_display, &fader->dst_rect, sf_old, NULL);
|
||||
SDL_BlitSurface(sdl_dib, &src_rect, sf_new, NULL);
|
||||
|
||||
fader->tx_old = SDL_CreateTextureFromSurface(sdl_renderer, sf_old);
|
||||
fader->tx_new = SDL_CreateTextureFromSurface(sdl_renderer, sf_new);
|
||||
|
||||
SDL_FreeSurface(sf_old);
|
||||
SDL_FreeSurface(sf_new);
|
||||
|
||||
sdl_copyArea(sx, sy, w, h, dx, dy);
|
||||
}
|
||||
|
||||
static void fader_finish(struct sdl_fader *fader) {
|
||||
SDL_RenderCopy(sdl_renderer, fader->tx_new, NULL, &fader->dst_rect);
|
||||
SDL_RenderPresent(sdl_renderer);
|
||||
|
||||
SDL_DestroyTexture(fader->tx_old);
|
||||
SDL_DestroyTexture(fader->tx_new);
|
||||
}
|
||||
|
||||
// EFFECT_CROSSFADE
|
||||
|
||||
static void crossfade_step(struct sdl_fader *fader, int step);
|
||||
static void crossfade_free(struct sdl_fader *fader);
|
||||
|
||||
static struct sdl_fader *crossfade_new(int sx, int sy, int w, int h, int dx, int dy) {
|
||||
struct sdl_fader *fader = calloc(1, sizeof(struct sdl_fader));
|
||||
if (!fader)
|
||||
NOMEMERR();
|
||||
fader_init(fader, sx, sy, w, h, dx, dy, EFFECT_CROSSFADE);
|
||||
fader->step = crossfade_step;
|
||||
fader->finish = crossfade_free;
|
||||
return fader;
|
||||
}
|
||||
|
||||
static void crossfade_step(struct sdl_fader *fader, int step) {
|
||||
SDL_RenderCopy(sdl_renderer, fader->tx_old, NULL, &fader->dst_rect);
|
||||
SDL_SetTextureBlendMode(fader->tx_new, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureAlphaMod(fader->tx_new, step * 255 / SDL_FADER_MAXSTEP);
|
||||
SDL_RenderCopy(sdl_renderer, fader->tx_new, NULL, &fader->dst_rect);
|
||||
SDL_SetTextureBlendMode(fader->tx_new, SDL_BLENDMODE_NONE);
|
||||
SDL_RenderPresent(sdl_renderer);
|
||||
}
|
||||
|
||||
static void crossfade_free(struct sdl_fader *fader) {
|
||||
fader_finish(fader);
|
||||
free(fader);
|
||||
}
|
||||
|
||||
// EFFECT_PENTAGRAM_*, EFFECT_HEXAGRAM_*, EFFECT_WINDMILL*
|
||||
|
||||
struct polygon_mask_fader {
|
||||
struct sdl_fader f;
|
||||
SDL_Texture *tx_tmp;
|
||||
};
|
||||
|
||||
static void polygon_mask_step(struct sdl_fader *fader, int step);
|
||||
static void polygon_mask_free(struct sdl_fader *fader);
|
||||
|
||||
static struct sdl_fader *polygon_mask_new(int sx, int sy, int w, int h, int dx, int dy, enum sdl_effect effect) {
|
||||
#if HAS_SDL_RenderGeometry
|
||||
if (SDL_RenderTargetSupported(sdl_renderer)) {
|
||||
struct polygon_mask_fader *pmf = calloc(1, sizeof(struct polygon_mask_fader));
|
||||
if (!pmf)
|
||||
NOMEMERR();
|
||||
fader_init(&pmf->f, sx, sy, w, h, dx, dy, effect);
|
||||
pmf->tx_tmp = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w, h);
|
||||
pmf->f.step = polygon_mask_step;
|
||||
pmf->f.finish = polygon_mask_free;
|
||||
return &pmf->f;
|
||||
}
|
||||
#endif // HAS_SDL_RenderGeometry
|
||||
|
||||
WARNING("Effect %d is not supported in this system. Falling back to crossfade.\n", effect);
|
||||
return crossfade_new(sx, sy, w, h, dx, dy);
|
||||
}
|
||||
|
||||
#if HAS_SDL_RenderGeometry
|
||||
|
||||
static void draw_pentagram(int center_x, int center_y, double radius, double rotate) {
|
||||
@@ -248,11 +339,12 @@ static void draw_windmill_360(int w, int h, double theta) {
|
||||
SDL_RenderGeometry(sdl_renderer, NULL, v, 10, indices, i);
|
||||
}
|
||||
|
||||
static void step_polygon_mask(struct sdl_fader *fader, int step) {
|
||||
static void polygon_mask_step(struct sdl_fader *fader, int step) {
|
||||
struct polygon_mask_fader *this = (struct polygon_mask_fader *)fader;
|
||||
int w = fader->dst_rect.w;
|
||||
int h = fader->dst_rect.h;
|
||||
double t = (double)step / SDL_FADER_MAXSTEP;
|
||||
SDL_SetRenderTarget(sdl_renderer, fader->tx_tmp);
|
||||
SDL_SetRenderTarget(sdl_renderer, this->tx_tmp);
|
||||
SDL_RenderCopy(sdl_renderer, fader->tx_old, NULL, NULL);
|
||||
switch (fader->effect) {
|
||||
case EFFECT_PENTAGRAM_IN_OUT:
|
||||
@@ -281,23 +373,36 @@ static void step_polygon_mask(struct sdl_fader *fader, int step) {
|
||||
}
|
||||
SDL_SetRenderTarget(sdl_renderer, NULL);
|
||||
SDL_RenderCopy(sdl_renderer, fader->tx_new, NULL, &fader->dst_rect);
|
||||
SDL_SetTextureBlendMode(fader->tx_tmp, SDL_BLENDMODE_BLEND);
|
||||
SDL_RenderCopy(sdl_renderer, fader->tx_tmp, NULL, &fader->dst_rect);
|
||||
SDL_SetTextureBlendMode(this->tx_tmp, SDL_BLENDMODE_BLEND);
|
||||
SDL_RenderCopy(sdl_renderer, this->tx_tmp, NULL, &fader->dst_rect);
|
||||
SDL_RenderPresent(sdl_renderer);
|
||||
}
|
||||
|
||||
static void polygon_mask_free(struct sdl_fader *fader) {
|
||||
struct polygon_mask_fader *this = (struct polygon_mask_fader *)fader;
|
||||
SDL_DestroyTexture(this->tx_tmp);
|
||||
fader_finish(&this->f);
|
||||
free(this);
|
||||
}
|
||||
|
||||
#endif // HAS_SDL_RenderGeometry
|
||||
|
||||
static void step_crossfade(struct sdl_fader *fader, int step) {
|
||||
SDL_RenderCopy(sdl_renderer, fader->tx_old, NULL, &fader->dst_rect);
|
||||
SDL_SetTextureBlendMode(fader->tx_new, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetTextureAlphaMod(fader->tx_new, step * 255 / SDL_FADER_MAXSTEP);
|
||||
SDL_RenderCopy(sdl_renderer, fader->tx_new, NULL, &fader->dst_rect);
|
||||
SDL_SetTextureBlendMode(fader->tx_new, SDL_BLENDMODE_NONE);
|
||||
SDL_RenderPresent(sdl_renderer);
|
||||
// EFFECT_ROTATE_*
|
||||
|
||||
static void rotate_step(struct sdl_fader *fader, int step);
|
||||
static void rotate_free(struct sdl_fader *fader);
|
||||
|
||||
static struct sdl_fader *rotate_new(int sx, int sy, int w, int h, int dx, int dy, enum sdl_effect effect) {
|
||||
struct sdl_fader *fader = calloc(1, sizeof(struct sdl_fader));
|
||||
if (!fader)
|
||||
NOMEMERR();
|
||||
fader_init(fader, sx, sy, w, h, dx, dy, effect);
|
||||
fader->step = rotate_step;
|
||||
fader->finish = rotate_free;
|
||||
return fader;
|
||||
}
|
||||
|
||||
static void step_rotate(struct sdl_fader *fader, int step) {
|
||||
static void rotate_step(struct sdl_fader *fader, int step) {
|
||||
SDL_Texture *bg_texture, *fg_texture;
|
||||
double angle = step * 360.0 / SDL_FADER_MAXSTEP;
|
||||
double scale = step / (double)SDL_FADER_MAXSTEP;
|
||||
@@ -335,49 +440,16 @@ static void step_rotate(struct sdl_fader *fader, int step) {
|
||||
SDL_RenderPresent(sdl_renderer);
|
||||
}
|
||||
|
||||
struct sdl_fader *sdl_fader_init(int sx, int sy, int w, int h, int dx, int dy, enum sdl_effect effect) {
|
||||
if (EFFECT_PENTAGRAM_IN_OUT <= effect && effect <= EFFECT_WINDMILL_360 &&
|
||||
(!SDL_RenderTargetSupported(sdl_renderer) || !HAS_SDL_RenderGeometry)) {
|
||||
WARNING("Effect %d is not supported in this system. Falling back to crossfade.\n", effect);
|
||||
effect = EFFECT_CROSSFADE;
|
||||
}
|
||||
|
||||
struct sdl_fader *fader = calloc(1, sizeof(struct sdl_fader));
|
||||
if (!fader)
|
||||
NOMEMERR();
|
||||
|
||||
fader->dst_rect.x = dx;
|
||||
fader->dst_rect.y = dy;
|
||||
fader->dst_rect.w = w;
|
||||
fader->dst_rect.h = h;
|
||||
fader->effect = effect;
|
||||
|
||||
SDL_Surface *sf_old = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_RGB888);
|
||||
SDL_Surface *sf_new = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_RGB888);
|
||||
|
||||
SDL_Rect src_rect = { sx, sy, w, h };
|
||||
SDL_BlitSurface(sdl_display, &fader->dst_rect, sf_old, NULL);
|
||||
SDL_BlitSurface(sdl_dib, &src_rect, sf_new, NULL);
|
||||
|
||||
fader->tx_old = SDL_CreateTextureFromSurface(sdl_renderer, sf_old);
|
||||
fader->tx_new = SDL_CreateTextureFromSurface(sdl_renderer, sf_new);
|
||||
|
||||
SDL_FreeSurface(sf_old);
|
||||
SDL_FreeSurface(sf_new);
|
||||
|
||||
if (effect != EFFECT_CROSSFADE)
|
||||
fader->tx_tmp = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w, h);
|
||||
|
||||
sdl_copyArea(sx, sy, w, h, dx, dy);
|
||||
return fader;
|
||||
static void rotate_free(struct sdl_fader *fader) {
|
||||
fader_finish(fader);
|
||||
free(fader);
|
||||
}
|
||||
|
||||
void sdl_fader_step(struct sdl_fader *fader, int step) {
|
||||
switch (fader->effect) {
|
||||
|
||||
struct sdl_fader *sdl_fader_init(int sx, int sy, int w, int h, int dx, int dy, enum sdl_effect effect) {
|
||||
switch (effect) {
|
||||
case EFFECT_CROSSFADE:
|
||||
step_crossfade(fader, step);
|
||||
break;
|
||||
#if HAS_SDL_RenderGeometry
|
||||
return crossfade_new(sx, sy, w, h, dx, dy);
|
||||
case EFFECT_PENTAGRAM_IN_OUT:
|
||||
case EFFECT_PENTAGRAM_OUT_IN:
|
||||
case EFFECT_HEXAGRAM_IN_OUT:
|
||||
@@ -385,29 +457,22 @@ void sdl_fader_step(struct sdl_fader *fader, int step) {
|
||||
case EFFECT_WINDMILL:
|
||||
case EFFECT_WINDMILL_180:
|
||||
case EFFECT_WINDMILL_360:
|
||||
step_polygon_mask(fader, step);
|
||||
break;
|
||||
#endif
|
||||
return polygon_mask_new(sx, sy, w, h, dx, dy, effect);
|
||||
case EFFECT_ROTATE_OUT:
|
||||
case EFFECT_ROTATE_IN:
|
||||
case EFFECT_ROTATE_OUT_CW:
|
||||
case EFFECT_ROTATE_IN_CW:
|
||||
step_rotate(fader, step);
|
||||
break;
|
||||
return rotate_new(sx, sy, w, h, dx, dy, effect);
|
||||
default:
|
||||
if (step == 0)
|
||||
WARNING("Unknown effect %d\n", fader->effect);
|
||||
break;
|
||||
WARNING("Unknown effect %d\n", effect);
|
||||
return crossfade_new(sx, sy, w, h, dx, dy);
|
||||
}
|
||||
}
|
||||
|
||||
void sdl_fader_step(struct sdl_fader *fader, int step) {
|
||||
fader->step(fader, step);
|
||||
}
|
||||
|
||||
void sdl_fader_finish(struct sdl_fader *fader) {
|
||||
SDL_RenderCopy(sdl_renderer, fader->tx_new, NULL, &fader->dst_rect);
|
||||
SDL_RenderPresent(sdl_renderer);
|
||||
|
||||
SDL_DestroyTexture(fader->tx_old);
|
||||
SDL_DestroyTexture(fader->tx_new);
|
||||
if (fader->tx_tmp)
|
||||
SDL_DestroyTexture(fader->tx_tmp);
|
||||
free(fader);
|
||||
fader->finish(fader);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user