mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-09-24 23:48:04 +03:00
sdl_effect: PF (fade in/out) and PW (white in/out) commands
In 256-color games, it uses alpha-blending instead of palette animation.
This commit is contained in:
@@ -545,36 +545,74 @@ void ags_runEffect(int duration_ms, boolean cancelable, ags_EffectStepFunc step,
|
||||
step(arg, 1.0);
|
||||
}
|
||||
|
||||
void ags_fadeIn(int rate, boolean flag) {
|
||||
if (!need_update)
|
||||
rate = 0;
|
||||
fade_outed = FALSE;
|
||||
static void fade(int duration, boolean cancelable, enum sdl_effect_type type) {
|
||||
nact->waitcancel_key = 0;
|
||||
ags_runEffect(rate * 16 * 1000 / 60, flag, sdl_fadeIn, NULL);
|
||||
|
||||
SDL_Rect rect = {0, 0, nact->sys_view_area.w, nact->sys_view_area.h};
|
||||
struct sdl_effect *eff = sdl_effect_init(
|
||||
&rect, NULL, 0, 0,
|
||||
sdl_getDIB(), nact->sys_view_area.x, nact->sys_view_area.y,
|
||||
type);
|
||||
ags_runEffect(duration, cancelable, (ags_EffectStepFunc)sdl_effect_step, eff);
|
||||
sdl_effect_finish(eff);
|
||||
}
|
||||
|
||||
void ags_fadeIn(int rate, boolean flag) {
|
||||
int duration = rate * 16 * 1000 / 60;
|
||||
if (!need_update)
|
||||
duration = 0;
|
||||
fade_outed = FALSE;
|
||||
|
||||
if (nact->sys_world_depth == 8)
|
||||
sdl_setPalette(nact->sys_pal, 0, 256);
|
||||
|
||||
fade(duration, flag, nact->sys_world_depth == 8 ? EFFECT_FADEIN : EFFECT_DITHERING_FADEIN);
|
||||
|
||||
sdl_updateAll();
|
||||
}
|
||||
|
||||
void ags_fadeOut(int rate, boolean flag) {
|
||||
int duration = rate * 16 * 1000 / 60;
|
||||
if (!need_update || fade_outed)
|
||||
rate = 0;
|
||||
duration = 0;
|
||||
fade_outed = TRUE;
|
||||
nact->waitcancel_key = 0;
|
||||
ags_runEffect(rate * 16 * 1000 / 60, flag, sdl_fadeOut, NULL);
|
||||
|
||||
fade(duration, flag, nact->sys_world_depth == 8 ? EFFECT_FADEOUT : EFFECT_DITHERING_FADEOUT);
|
||||
|
||||
if (nact->sys_world_depth == 8) {
|
||||
Palette256 pal;
|
||||
memset(&pal, 0, sizeof(pal));
|
||||
sdl_setPalette(&pal, 0, 256);
|
||||
}
|
||||
}
|
||||
|
||||
void ags_whiteIn(int rate, boolean flag) {
|
||||
int duration = rate * 16 * 1000 / 60;
|
||||
if (!need_update)
|
||||
rate = 0;
|
||||
duration = 0;
|
||||
fade_outed = FALSE;
|
||||
nact->waitcancel_key = 0;
|
||||
ags_runEffect(rate * 16 * 1000 / 60, flag, sdl_whiteIn, NULL);
|
||||
|
||||
if (nact->sys_world_depth == 8)
|
||||
sdl_setPalette(nact->sys_pal, 0, 256);
|
||||
|
||||
fade(duration, flag, nact->sys_world_depth == 8 ? EFFECT_WHITEIN : EFFECT_DITHERING_WHITEIN);
|
||||
|
||||
sdl_updateAll();
|
||||
}
|
||||
|
||||
void ags_whiteOut(int rate, boolean flag) {
|
||||
int duration = rate * 16 * 1000 / 60;
|
||||
if (!need_update || fade_outed)
|
||||
rate = 0;
|
||||
duration = 0;
|
||||
fade_outed = TRUE;
|
||||
nact->waitcancel_key = 0;
|
||||
ags_runEffect(rate * 16 * 1000 / 60, flag, sdl_whiteOut, NULL);
|
||||
|
||||
fade(duration, flag, nact->sys_world_depth == 8 ? EFFECT_WHITEIN : EFFECT_DITHERING_WHITEOUT);
|
||||
|
||||
if (nact->sys_world_depth == 8) {
|
||||
Palette256 pal;
|
||||
memset(&pal, 255, sizeof(pal));
|
||||
sdl_setPalette(&pal, 0, 256);
|
||||
}
|
||||
}
|
||||
|
||||
void ags_setFont(int type, int size) {
|
||||
|
||||
@@ -107,6 +107,10 @@ enum sdl_effect_type {
|
||||
EFFECT_WHITEOUT,
|
||||
EFFECT_WHITEOUT_FROM_NEW,
|
||||
EFFECT_WHITEIN,
|
||||
EFFECT_DITHERING_FADEOUT,
|
||||
EFFECT_DITHERING_FADEIN,
|
||||
EFFECT_DITHERING_WHITEOUT,
|
||||
EFFECT_DITHERING_WHITEIN,
|
||||
EFFECT_BLIND_DOWN,
|
||||
EFFECT_BLIND_UP,
|
||||
EFFECT_BLIND_LR,
|
||||
|
||||
+3
-7
@@ -50,6 +50,7 @@ extern void sdl_setIntegerScaling(boolean enable);
|
||||
|
||||
/* 画面更新 */
|
||||
extern void sdl_updateArea(MyRectangle *src, MyPoint *dst);
|
||||
extern void sdl_updateAll(void);
|
||||
extern void sdl_updateScreen(void);
|
||||
|
||||
/* パレット関係 */
|
||||
@@ -83,14 +84,9 @@ extern SDL_Surface *com2surface(agsurface_t *s);
|
||||
|
||||
/* Effects */
|
||||
struct sdl_effect;
|
||||
|
||||
struct sdl_effect *sdl_effect_init(SDL_Rect *rect, agsurface_t *old, int ox, int oy, agsurface_t *new, int nx, int ny, enum sdl_effect_type effect);
|
||||
void sdl_effect_step(struct sdl_effect *fader, double progress);
|
||||
void sdl_effect_finish(struct sdl_effect *fader);
|
||||
extern void sdl_fadeIn(void *arg, double progress);
|
||||
extern void sdl_fadeOut(void *arg, double progress);
|
||||
extern void sdl_whiteIn(void *arg, double progress);
|
||||
extern void sdl_whiteOut(void *arg, double progress);
|
||||
void sdl_effect_step(struct sdl_effect *eff, double progress);
|
||||
void sdl_effect_finish(struct sdl_effect *eff);
|
||||
|
||||
/* key/pointer 関係 */
|
||||
extern void sdl_setJoyDeviceIndex(int index);
|
||||
|
||||
+1
-143
@@ -42,24 +42,6 @@
|
||||
#include "nact.h"
|
||||
#include "debugger.h"
|
||||
|
||||
static const int fadeX[16] = {0,2,2,0,1,3,3,1,1,3,3,1,0,2,2,0};
|
||||
static const int fadeY[16] = {0,2,0,2,1,3,1,3,0,2,0,2,1,3,1,3};
|
||||
|
||||
static int fadestep[256] =
|
||||
{0,1,3,4,6,7,9,10,12,14,15,17,18,20,21,23,25,26,28,29,31,32,34,36,37,39,40,
|
||||
42,43,45,46,48,49,51,53,54,56,57,59,60,62,63,65,66,68,69,71,72,74,75,77,78,
|
||||
80,81,83,84,86,87,89,90,92,93,95,96,97,99,100,102,103,105,106,108,109,110,
|
||||
112,113,115,116,117,119,120,122,123,124,126,127,128,130,131,132,134,135,136,
|
||||
138,139,140,142,143,144,146,147,148,149,151,152,153,155,156,157,158,159,161,
|
||||
162,163,164,166,167,168,169,170,171,173,174,175,176,177,178,179,181,182,183,
|
||||
184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,
|
||||
203,204,205,206,207,208,209,210,211,211,212,213,214,215,216,217,217,218,219,
|
||||
220,221,221,222,223,224,225,225,226,227,227,228,229,230,230,231,232,232,233,
|
||||
234,234,235,235,236,237,237,238,238,239,239,240,241,241,242,242,243,243,244,
|
||||
244,244,245,245,246,246,247,247,247,248,248,249,249,249,250,250,250,251,251,
|
||||
251,251,252,252,252,252,253,253,253,253,254,254,254,254,254,254,255,255,255,
|
||||
255,255,255,255,255,255,255,255,255,255,255};
|
||||
|
||||
static void sdl_pal_check(void) {
|
||||
if (nact->sys_pal_changed) {
|
||||
nact->sys_pal_changed = FALSE;
|
||||
@@ -121,7 +103,7 @@ void sdl_updateArea(MyRectangle *src, MyPoint *dst) {
|
||||
}
|
||||
|
||||
/* 全画面更新 */
|
||||
static void sdl_updateAll() {
|
||||
void sdl_updateAll(void) {
|
||||
SDL_Rect rect = {0, 0, view_w, view_h};
|
||||
|
||||
SDL_BlitSurface(sdl_dib, &sdl_view, sdl_display, &rect);
|
||||
@@ -341,130 +323,6 @@ SDL_Rect sdl_drawString(int x, int y, const char *str_utf8, BYTE col) {
|
||||
return font_draw_glyph(x, y, str_utf8, col);
|
||||
}
|
||||
|
||||
static void setBligtness(SDL_Surface *s, int val) {
|
||||
int i;
|
||||
Palette256 *pal = nact->sys_pal;
|
||||
Uint8 *r = pal->red, *g = pal->green, *b = pal->blue;
|
||||
SDL_Color *cl = sdl_col;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
cl->r = (val * (*(r++))) / 255;
|
||||
cl->g = (val * (*(g++))) / 255;
|
||||
cl->b = (val * (*(b++))) / 255;
|
||||
cl++;
|
||||
}
|
||||
SDL_SetPaletteColors(s->format->palette, sdl_col, 0, 256);
|
||||
}
|
||||
|
||||
static void setWhiteness(SDL_Surface *s, int val) {
|
||||
int i;
|
||||
Palette256 *pal = nact->sys_pal;
|
||||
Uint8 *r = pal->red, *g = pal->green, *b = pal->blue;
|
||||
SDL_Color *cl = sdl_col;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
cl->r = (((255- *r) * val) / 256) + *r; r++;
|
||||
cl->g = (((255- *g) * val) / 256) + *g; g++;
|
||||
cl->b = (((255- *b) * val) / 256) + *b; b++;
|
||||
cl++;
|
||||
}
|
||||
SDL_SetPaletteColors(s->format->palette, sdl_col, 0, 256);
|
||||
}
|
||||
|
||||
static void fader_in(int n) {
|
||||
static SDL_Surface *src;
|
||||
|
||||
if (n == 0) {
|
||||
src = SDL_CreateRGBSurfaceWithFormat(0, sdl_display->w, sdl_display->h, 32, SDL_PIXELFORMAT_RGB888);
|
||||
SDL_Rect r_src = {view_x, view_y, view_w, view_h};
|
||||
SDL_Rect r_dst = {0, 0, view_w, view_h};
|
||||
SDL_BlitSurface(sdl_dib, &r_src, src, &r_dst);
|
||||
}
|
||||
|
||||
if (n == 255) {
|
||||
SDL_FreeSurface(src);
|
||||
sdl_updateAll();
|
||||
return;
|
||||
}
|
||||
|
||||
int lv = n / 16;
|
||||
for (int y = 0; y < src->h; y += 4) {
|
||||
DWORD *yls = PIXEL_AT(src, 0, y + fadeY[lv]);
|
||||
DWORD *yld = PIXEL_AT(sdl_display, 0, y + fadeY[lv]);
|
||||
for (int x = 0; x < src->w; x += 4) {
|
||||
*(yld + fadeX[lv]) = *(yls + fadeX[lv]);
|
||||
yls += 4; yld += 4;
|
||||
}
|
||||
}
|
||||
|
||||
sdl_dirty = TRUE;
|
||||
}
|
||||
|
||||
static void fader_out(int n, Uint32 c) {
|
||||
if (n == 255) {
|
||||
SDL_FillRect(sdl_display, NULL, c);
|
||||
return;
|
||||
}
|
||||
|
||||
int lv = (255 - n) / 16;
|
||||
for (int y = 0; y < sdl_display->h; y += 4) {
|
||||
DWORD *yld = PIXEL_AT(sdl_display, 0, y + fadeY[lv]);
|
||||
for (int x = 0; x < sdl_display->w; x += 4) {
|
||||
*(yld + fadeX[lv]) = c;
|
||||
yld += 4;
|
||||
}
|
||||
}
|
||||
|
||||
sdl_dirty = TRUE;
|
||||
}
|
||||
|
||||
static __inline void sdl_fade_blit(void) {
|
||||
SDL_Rect r_dst = {0, 0, view_w, view_h};
|
||||
|
||||
SDL_BlitSurface(sdl_dib, &sdl_view, sdl_display, &r_dst);
|
||||
sdl_dirty = TRUE;
|
||||
}
|
||||
|
||||
void sdl_fadeIn(void *arg, double progress) {
|
||||
int step = progress * 255;
|
||||
if (sdl_dib->format->BitsPerPixel == 8) {
|
||||
setBligtness(sdl_dib, fadestep[step]);
|
||||
sdl_fade_blit();
|
||||
} else {
|
||||
fader_in(step);
|
||||
}
|
||||
}
|
||||
|
||||
void sdl_fadeOut(void *arg, double progress) {
|
||||
int step = progress * 255;
|
||||
if (sdl_dib->format->BitsPerPixel == 8) {
|
||||
setBligtness(sdl_dib, fadestep[255 - step]);
|
||||
sdl_fade_blit();
|
||||
} else {
|
||||
fader_out(step, SDL_MapRGB(sdl_display->format, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void sdl_whiteIn(void *arg, double progress) {
|
||||
int step = progress * 255;
|
||||
if (sdl_dib->format->BitsPerPixel == 8) {
|
||||
setWhiteness(sdl_dib, fadestep[255 - step]); /* ??? */
|
||||
sdl_fade_blit();
|
||||
} else {
|
||||
fader_in(step);
|
||||
}
|
||||
}
|
||||
|
||||
void sdl_whiteOut(void *arg, double progress) {
|
||||
int step = progress * 255;
|
||||
if (sdl_dib->format->BitsPerPixel == 8) {
|
||||
setWhiteness(sdl_dib, fadestep[step]); /* ??? */
|
||||
sdl_fade_blit();
|
||||
} else {
|
||||
fader_out(step, SDL_MapRGB(sdl_display->format, 255, 255, 255));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 指定範囲にパレット col を rate の割合で重ねる CK1
|
||||
*/
|
||||
|
||||
@@ -461,6 +461,95 @@ static void brightness_free(struct sdl_effect *eff) {
|
||||
free(eff);
|
||||
}
|
||||
|
||||
// EFFECT_DITHERING_{FADE,WHITE}{OUT,IN}
|
||||
|
||||
static void dithering_fade_step(struct sdl_effect *eff, double progress);
|
||||
static void dithering_fade_free(struct sdl_effect *eff);
|
||||
|
||||
static SDL_Texture *create_dither_pattern_texture(int w, int h, int val) {
|
||||
SDL_PixelFormat *fmt = SDL_AllocFormat(SDL_PIXELFORMAT_ARGB8888);
|
||||
Uint32 col = SDL_MapRGBA(fmt, val, val, val, SDL_ALPHA_OPAQUE);
|
||||
SDL_FreeFormat(fmt);
|
||||
|
||||
Uint32 *pixels = calloc(w * h, sizeof(Uint32));
|
||||
if (!pixels)
|
||||
NOMEMERR();
|
||||
for (int y = 0; y < h; y += 4) {
|
||||
Uint32 *row = pixels + y * w;
|
||||
for (int x = 0; x < w; x += 4)
|
||||
row[x] = col;
|
||||
}
|
||||
|
||||
SDL_Texture *tx = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, w, h);
|
||||
SDL_UpdateTexture(tx, NULL, pixels, w * 4);
|
||||
free(pixels);
|
||||
SDL_SetTextureBlendMode(tx, SDL_BLENDMODE_BLEND);
|
||||
return tx;
|
||||
}
|
||||
|
||||
static struct sdl_effect *dithering_fade_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
|
||||
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
|
||||
if (!eff)
|
||||
NOMEMERR();
|
||||
switch (type) {
|
||||
case EFFECT_DITHERING_FADEOUT:
|
||||
SDL_FreeSurface(new);
|
||||
effect_init(eff, rect, old, NULL, type);
|
||||
eff->tx_new = create_dither_pattern_texture(rect->w, rect->h, 0);
|
||||
break;
|
||||
case EFFECT_DITHERING_FADEIN:
|
||||
SDL_FreeSurface(old);
|
||||
effect_init(eff, rect, new, NULL, type);
|
||||
eff->tx_new = create_dither_pattern_texture(rect->w, rect->h, 0);
|
||||
break;
|
||||
case EFFECT_DITHERING_WHITEOUT:
|
||||
SDL_FreeSurface(new);
|
||||
effect_init(eff, rect, old, NULL, type);
|
||||
eff->tx_new = create_dither_pattern_texture(rect->w, rect->h, 255);
|
||||
break;
|
||||
case EFFECT_DITHERING_WHITEIN:
|
||||
SDL_FreeSurface(old);
|
||||
effect_init(eff, rect, new, NULL, type);
|
||||
eff->tx_new = create_dither_pattern_texture(rect->w, rect->h, 255);
|
||||
break;
|
||||
default:
|
||||
assert(!"Cannot happen");
|
||||
}
|
||||
eff->step = dithering_fade_step;
|
||||
eff->finish = dithering_fade_free;
|
||||
return eff;
|
||||
}
|
||||
|
||||
static void dithering_fade_step(struct sdl_effect *eff, double progress) {
|
||||
static const int dither_x[16] = {0,2,2,0,1,3,3,1,1,3,3,1,0,2,2,0};
|
||||
static const int dither_y[16] = {0,2,0,2,1,3,1,3,0,2,0,2,1,3,1,3};
|
||||
|
||||
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
|
||||
|
||||
if (eff->type == EFFECT_DITHERING_FADEIN || eff->type == EFFECT_DITHERING_WHITEIN)
|
||||
progress = 1 - progress;
|
||||
int level = round(progress * 16);
|
||||
|
||||
assert(eff->is_fullscreen);
|
||||
SDL_Rect dr = eff->dst_rect;
|
||||
for (int i = 0; i < level; i++) {
|
||||
dr.x = eff->dst_rect.x + dither_x[i];
|
||||
dr.y = eff->dst_rect.y + dither_y[i];
|
||||
SDL_RenderCopy(sdl_renderer, eff->tx_new, NULL, &dr);
|
||||
}
|
||||
|
||||
SDL_RenderPresent(sdl_renderer);
|
||||
}
|
||||
|
||||
static void dithering_fade_free(struct sdl_effect *eff) {
|
||||
if (eff->type == EFFECT_DITHERING_FADEOUT)
|
||||
SDL_FillRect(sdl_display, &eff->dst_rect, SDL_MapRGB(sdl_display->format, 0, 0, 0));
|
||||
else if (eff->type == EFFECT_DITHERING_WHITEOUT)
|
||||
SDL_FillRect(sdl_display, &eff->dst_rect, SDL_MapRGB(sdl_display->format, 255, 255, 255));
|
||||
effect_finish(eff, false);
|
||||
free(eff);
|
||||
}
|
||||
|
||||
// EFFECT_BLIND_*
|
||||
|
||||
static void blind_step(struct sdl_effect *eff, double progress);
|
||||
@@ -1348,6 +1437,11 @@ struct sdl_effect *sdl_effect_init(SDL_Rect *rect, agsurface_t *old, int ox, int
|
||||
case EFFECT_WHITEOUT_FROM_NEW:
|
||||
case EFFECT_WHITEIN:
|
||||
return brightness_new(rect, sf_old, sf_new, type);
|
||||
case EFFECT_DITHERING_FADEOUT:
|
||||
case EFFECT_DITHERING_FADEIN:
|
||||
case EFFECT_DITHERING_WHITEOUT:
|
||||
case EFFECT_DITHERING_WHITEIN:
|
||||
return dithering_fade_new(rect, sf_old, sf_new, type);
|
||||
case EFFECT_BLIND_DOWN:
|
||||
case EFFECT_BLIND_UP:
|
||||
case EFFECT_BLIND_LR:
|
||||
|
||||
Reference in New Issue
Block a user