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:
kichikuou
2022-02-05 14:49:00 +09:00
parent 0b71a84bb0
commit 605de284e9
5 changed files with 154 additions and 164 deletions
+52 -14
View File
@@ -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) {
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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
*/
+94
View File
@@ -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: