sdl_effect: Implement EFFECT_PAN_IN_* and EFFECT_SKIP_LINE_*

This also fixes incorrect behavior of `CD 1` and `CD 2`.
This commit is contained in:
kichikuou
2024-09-01 14:57:59 +09:00
parent 86068b0ab9
commit d3db3fa83e
7 changed files with 173 additions and 119 deletions
+17 -114
View File
@@ -54,84 +54,6 @@ static void eCopyUpdateArea(int sx, int sy, int w, int h, int dx, int dy) {
sdl_updateArea(&src, &dst);
}
static int eCopyArea1(int dx, int dy, int w, int h, int opt) {
int y, key = 0, cnt;
int waitcnt = opt == 0 ? 20 : opt;
cnt = sdl_getTicks();
for (y = 0; y < h - 24; y += 24) {
cnt += waitcnt;
eCopyUpdateArea(dx, dy + h - y, w, y, dx, dy);
EC_WAIT;
}
eCopyUpdateArea(dx, dy, w, h, dx, dy);
return key;
}
static int eCopyArea2(int dx, int dy, int w, int h, int opt) {
int y, key = 0, cnt;
int waitcnt = opt == 0 ? 20 : opt;
cnt = sdl_getTicks();
for (y = 0; y < h - 24; y += 24) {
cnt += waitcnt;
eCopyUpdateArea(dx, dy , w, y, dx, dy + h - y);
EC_WAIT;
}
eCopyUpdateArea(dx, dy, w, h, dx, dy);
return key;
}
static int eCopyArea3(int dx, int dy, int w, int h, int opt) {
int y1, y2, key = 0, cnt;
int waitcnt = opt == 0 ? 3 : opt;
if (h % 2) {
h--;
eCopyUpdateArea(dx , dy + h, w, 1, dx, dy + h);
}
y1 = dy;
y2 = dy + h - 1;
cnt = sdl_getTicks();
while (h > 0) {
cnt += waitcnt;
eCopyUpdateArea(dx, y1, w, 1, dx, y1);
eCopyUpdateArea(dx, y2, w, 1, dx, y2);
y1 += 2;
y2 -= 2;
h -= 2;
EC_WAIT;
}
eCopyUpdateArea(dx, dy, w, h, dx, dy);
return key;
}
static int eCopyArea4(int dx, int dy, int w, int h, int opt) {
int x1,x2, key = 0, cnt;
int waitcnt = opt == 0 ? 3 : opt;
if (w % 2) {
w--;
eCopyUpdateArea(dx + w , dy, 1, h, dx + w, dy);
}
x1 = dx;
x2 = dx + w - 1;
cnt = sdl_getTicks();
while (w > 0) {
cnt += waitcnt;
eCopyUpdateArea(x1, dy, 1, h, x1, dy);
eCopyUpdateArea(x2, dy, 1, h, x2, dy);
x1 += 2;
x2 -= 2;
w -= 2;
EC_WAIT;
}
eCopyUpdateArea(dx, dy, w, h, dx, dy);
return key;
}
static int eCopyArea5(int sx, int sy, int w, int h, int dx, int dy, int opt) {
int i, x, y, key = 0, cnt;
int waitcnt = opt == 0 ? 20 : opt;
@@ -299,6 +221,13 @@ static int eCopyArea2001(int sx, int sy, int w, int h, int dx, int dy, int opt)
static int duration(enum nact_effect effect, int opt, SDL_Rect *rect) {
switch (effect) {
case NACT_EFFECT_PAN_IN_DOWN:
case NACT_EFFECT_PAN_IN_UP:
return (opt ? opt : 20) * (rect->h / 24);
case NACT_EFFECT_SKIP_LINE_UP_DOWN:
return (opt ? opt : 3) * (rect->h / 2);
case NACT_EFFECT_SKIP_LINE_LR_RL:
return (opt ? opt : 3) * (rect->w / 2);
case NACT_EFFECT_ZOOM_IN:
return opt ? opt * 64 : 500;
case NACT_EFFECT_BLIND_DOWN:
@@ -423,10 +352,6 @@ void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt
ecp_cancel = cancel;
switch(sw) {
case 1:
case 2:
case 3:
case 4:
case 6:
case 16:
case 17:
@@ -441,18 +366,6 @@ void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt
}
switch(sw) {
case 1:
ret = eCopyArea1(dx, dy, w, h, opt);
break;
case 2:
ret = eCopyArea2(dx, dy, w, h, opt);
break;
case 3:
ret = eCopyArea3(dx, dy, w, h, opt);
break;
case 4:
ret = eCopyArea4(dx, dy, w, h, opt);
break;
case 5:
ret = eCopyArea5(sx, sy, w, h, dx, dy, opt);
break;
@@ -505,6 +418,16 @@ void ags_eSpriteCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, i
nact->waitcancel_key = 0;
if (1 <= sw && sw <= 4) {
SDL_Rect rect = { dx - nact->ags.view_area.x, dy - nact->ags.view_area.y, w, h };
struct sdl_effect *eff = sdl_sprite_effect_init(&rect, dx, dy, sx, sy, spCol, from_nact_effect(sw));
ags_runEffect(duration(sw, opt, &rect), cancel, (ags_EffectStepFunc)sdl_effect_step, eff);
sdl_effect_finish(eff);
// Actual copy.
ags_copyAreaSP(sx, sy, w, h, dx, dy, spCol);
ags_updateArea(dx, dy, w, h);
return;
}
if (sw == 5) {
SDL_Rect rect = { dx - nact->ags.view_area.x, dy - nact->ags.view_area.y, w, h };
struct sdl_effect *eff = sdl_effect_raster_blend_init(&rect, sx, sy);
@@ -518,28 +441,8 @@ void ags_eSpriteCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, i
ecp_cancel = cancel;
if (1 <= sw && sw <= 4) {
ags_copyAreaSP(sx, sy, w, h, dx, dy, spCol);
MyRectangle r = {dx, dy, w, h}, update;
SDL_IntersectRect(&nact->ags.view_area, &r, &update);
w = update.w;
h = update.h;
}
int ret = 0;
switch(sw) {
case 1:
ret = eCopyArea1(dx, dy, w, h, opt);
break;
case 2:
ret = eCopyArea2(dx, dy, w, h, opt);
break;
case 3:
ret = eCopyArea3(dx, dy, w, h, opt);
break;
case 4:
ret = eCopyArea4(dx, dy, w, h, opt);
break;
case NACT_EFFECT_PALETTE_SHIFT:
if (nact->ags.world_depth != 8) return;
ags_copyPaletteShift(sx, sy, w, h, dx, dy, spCol);
+8
View File
@@ -22,6 +22,10 @@
// Effect types of the CE/CD command.
enum nact_effect {
NACT_EFFECT_PAN_IN_DOWN = 1,
NACT_EFFECT_PAN_IN_UP = 2,
NACT_EFFECT_SKIP_LINE_UP_DOWN = 3,
NACT_EFFECT_SKIP_LINE_LR_RL = 4,
NACT_EFFECT_WIPE_IN = 7,
NACT_EFFECT_WIPE_OUT = 8,
NACT_EFFECT_ZOOM_IN = 10,
@@ -124,6 +128,10 @@ enum sdl_effect_type {
EFFECT_DITHERING_FADEIN,
EFFECT_DITHERING_WHITEOUT,
EFFECT_DITHERING_WHITEIN,
EFFECT_PAN_IN_DOWN,
EFFECT_PAN_IN_UP,
EFFECT_SKIP_LINE_UP_DOWN,
EFFECT_SKIP_LINE_LR_RL,
EFFECT_WIPE_IN,
EFFECT_WIPE_OUT,
EFFECT_WIPE_LR,
+1
View File
@@ -87,6 +87,7 @@ 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);
struct sdl_effect *sdl_sprite_effect_init(SDL_Rect *rect, int dx, int dy, int sx, int sy, int col, enum sdl_effect_type type);
struct sdl_effect *sdl_effect_magnify_init(agsurface_t *surface, SDL_Rect *view_rect, SDL_Rect *target_rect);
struct sdl_effect *sdl_effect_raster_blend_init(SDL_Rect *rect, int sx, int sy);
void sdl_effect_step(struct sdl_effect *eff, float progress);
+16 -5
View File
@@ -202,10 +202,7 @@ void sdl_copyArea(int sx, int sy, int w, int h, int dx, int dy) {
}
}
/*
* dib に指定のパレット sp を抜いてコピー
*/
void sdl_copyAreaSP(int sx, int sy, int w, int h, int dx, int dy, uint8_t sp) {
static void sdl_dib_sprite_copy(SDL_Surface *dst, int sx, int sy, int w, int h, int dx, int dy, uint8_t sp) {
sdl_pal_check();
Uint32 col = palette_color(sp);
@@ -214,10 +211,24 @@ void sdl_copyAreaSP(int sx, int sy, int w, int h, int dx, int dy, uint8_t sp) {
SDL_Rect r_src = {sx, sy, w, h};
SDL_Rect r_dst = {dx, dy, w, h};
SDL_BlitSurface(sdl_dib, &r_src, sdl_dib, &r_dst);
SDL_BlitSurface(sdl_dib, &r_src, dst, &r_dst);
SDL_SetColorKey(sdl_dib, SDL_FALSE, 0);
}
/*
* dib に指定のパレット sp を抜いてコピー
*/
void sdl_copyAreaSP(int sx, int sy, int w, int h, int dx, int dy, uint8_t sp) {
sdl_dib_sprite_copy(sdl_dib, sx, sy, w, h, dx, dy, sp);
}
SDL_Surface *sdl_dib_to_surface_colorkey(int x, int y, int w, int h, int sp) {
SDL_Surface *s = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_ARGB8888);
SDL_FillRect(s, NULL, 0);
sdl_dib_sprite_copy(s, x, y, w, h, 0, 0, sp);
return s;
}
void sdl_drawImage8_fromData(cgdata *cg, int dx, int dy, int sprite_color) {
int w = cg->width;
int h = cg->height;
+128
View File
@@ -32,6 +32,10 @@
enum sdl_effect_type from_nact_effect(enum nact_effect effect) {
switch (effect) {
case NACT_EFFECT_PAN_IN_DOWN: return EFFECT_PAN_IN_DOWN;
case NACT_EFFECT_PAN_IN_UP: return EFFECT_PAN_IN_UP;
case NACT_EFFECT_SKIP_LINE_UP_DOWN: return EFFECT_SKIP_LINE_UP_DOWN;
case NACT_EFFECT_SKIP_LINE_LR_RL: return EFFECT_SKIP_LINE_LR_RL;
case NACT_EFFECT_WIPE_IN: return EFFECT_WIPE_IN;
case NACT_EFFECT_WIPE_OUT: return EFFECT_WIPE_OUT;
case NACT_EFFECT_ZOOM_IN: return EFFECT_ZOOM_IN;
@@ -563,6 +567,107 @@ static void dithering_fade_free(struct sdl_effect *eff) {
free(eff);
}
// EFFECT_PAN_IN_*
static void pan_in_step(struct sdl_effect *eff, float progress);
static void pan_in_free(struct sdl_effect *eff);
static struct sdl_effect *pan_in_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();
effect_init(eff, rect, old, new, type);
eff->step = pan_in_step;
eff->finish = pan_in_free;
return eff;
}
static void pan_in_step(struct sdl_effect *eff, float progress) {
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
int h = eff->dst_rect.h * progress;
SDL_Rect sr = { 0, 0, eff->dst_rect.w, h };
SDL_Rect dr = eff->dst_rect;
dr.h = h;
if (eff->type == EFFECT_PAN_IN_DOWN) {
sr.y = eff->dst_rect.h - h;
} else {
dr.y += eff->dst_rect.h - h;
}
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
SDL_RenderPresent(sdl_renderer);
}
static void pan_in_free(struct sdl_effect *eff) {
effect_finish(eff, true);
free(eff);
}
// EFFECT_SKIP_LINE_*
static void skip_line_step(struct sdl_effect *eff, float progress);
static void skip_line_free(struct sdl_effect *eff);
static struct sdl_effect *skip_line_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();
effect_init(eff, rect, old, new, type);
eff->step = skip_line_step;
eff->finish = skip_line_free;
return eff;
}
static void skip_line_step(struct sdl_effect *eff, float progress) {
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
if (eff->type == EFFECT_SKIP_LINE_UP_DOWN) {
int h = eff->dst_rect.h * progress;
SDL_Rect sr = { 0, 0, eff->dst_rect.w, 1 };
SDL_Rect dr = eff->dst_rect;
dr.h = 1;
int bottom = (eff->dst_rect.h - 1) | 1;
for (int y = 0; y < h; y += 2) {
sr.y = y;
dr.y = eff->dst_rect.y + y;
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
if (y == 0 && eff->dst_rect.h & 1)
continue;
sr.y = bottom - y;
dr.y = eff->dst_rect.y + bottom - y;
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
}
} else {
int w = eff->dst_rect.w * progress;
SDL_Rect sr = { 0, 0, 1, eff->dst_rect.h };
SDL_Rect dr = eff->dst_rect;
dr.w = 1;
int right = (eff->dst_rect.w - 1) | 1;
for (int x = 0; x < w; x += 2) {
sr.x = x;
dr.x = eff->dst_rect.x + x;
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
if (x == 0 && eff->dst_rect.w & 1)
continue;
sr.x = right - x;
dr.x = eff->dst_rect.x + right - x;
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
}
}
SDL_RenderPresent(sdl_renderer);
}
static void skip_line_free(struct sdl_effect *eff) {
effect_finish(eff, true);
free(eff);
}
// EFFECT_WIPE_*
static void wipe_step(struct sdl_effect *eff, float progress);
@@ -1607,6 +1712,12 @@ struct sdl_effect *sdl_effect_init(SDL_Rect *rect, agsurface_t *old, int ox, int
case EFFECT_DITHERING_WHITEOUT:
case EFFECT_DITHERING_WHITEIN:
return dithering_fade_new(rect, sf_old, sf_new, type);
case EFFECT_PAN_IN_DOWN:
case EFFECT_PAN_IN_UP:
return pan_in_new(rect, sf_old, sf_new, type);
case EFFECT_SKIP_LINE_UP_DOWN:
case EFFECT_SKIP_LINE_LR_RL:
return skip_line_new(rect, sf_old, sf_new, type);
case EFFECT_WIPE_IN:
case EFFECT_WIPE_OUT:
case EFFECT_WIPE_LR:
@@ -1663,6 +1774,23 @@ struct sdl_effect *sdl_effect_init(SDL_Rect *rect, agsurface_t *old, int ox, int
}
}
struct sdl_effect *sdl_sprite_effect_init(SDL_Rect *rect, int dx, int dy, int sx, int sy, int col, enum sdl_effect_type type) {
SDL_Surface *sf_old = create_surface(sdl_dibinfo, dx, dy, rect->w, rect->h);
SDL_Surface *sprite = sdl_dib_to_surface_colorkey(sx, sy, rect->w, rect->h, col);
switch (type) {
case EFFECT_PAN_IN_DOWN:
case EFFECT_PAN_IN_UP:
return pan_in_new(rect, sf_old, sprite, type);
case EFFECT_SKIP_LINE_UP_DOWN:
case EFFECT_SKIP_LINE_LR_RL:
return skip_line_new(rect, sf_old, sprite, type);
default:
SYSERROR("Unknown sprite effect %d", type);
return NULL;
}
}
struct sdl_effect *sdl_effect_magnify_init(agsurface_t *surface, SDL_Rect *view_rect, SDL_Rect *target_rect) {
SDL_Surface *sf = create_surface(surface, view_rect->x, view_rect->y, view_rect->w, view_rect->h);
return magnify_new(sf, view_rect, target_rect);
+2
View File
@@ -245,6 +245,7 @@ void sdl_copyAreaSP16_alphaBlend(int sx, int sy, int w, int h, int dx, int dy, i
SDL_SetSurfaceBlendMode(sdl_dib, SDL_BLENDMODE_BLEND);
SDL_SetSurfaceAlphaMod(sdl_dib, lv);
SDL_BlitSurface(sdl_dib, &r_src, sdl_dib, &r_dst);
SDL_SetSurfaceAlphaMod(sdl_dib, 255);
SDL_SetSurfaceBlendMode(sdl_dib, SDL_BLENDMODE_NONE);
}
@@ -255,6 +256,7 @@ void sdl_copyAreaSP16_alphaLevel(int sx, int sy, int w, int h, int dx, int dy, i
SDL_SetSurfaceAlphaMod(sdl_dib, lv);
SDL_FillRect(sdl_dib, &r_dst, 0);
SDL_BlitSurface(sdl_dib, &r_src, sdl_dib, &r_dst);
SDL_SetSurfaceAlphaMod(sdl_dib, 255);
SDL_SetSurfaceBlendMode(sdl_dib, SDL_BLENDMODE_NONE);
}
+1
View File
@@ -57,6 +57,7 @@ void sdl_cursor_init(void);
int sdl_nearest_color(int r, int g, int b);
boolean sdl_joy_open(int index);
SDL_Surface *sdl_dib_to_surface_with_alpha(int x, int y, int w, int h);
SDL_Surface *sdl_dib_to_surface_colorkey(int x, int y, int w, int h, int col);
extern struct sdl_private_data *sdl_videodev;