mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-28 15:11:55 +00:00
Support patch as input in image:copy
Add image:clear
This commit is contained in:
parent
f464297169
commit
46aebb7638
5 changed files with 308 additions and 34 deletions
|
@ -90,7 +90,8 @@ enum patch {
|
|||
// Methods
|
||||
patch_getPixel,
|
||||
patch_setPixel,
|
||||
patch_copy
|
||||
patch_copy,
|
||||
patch_clear
|
||||
};
|
||||
static const char *const patch_opt[] = {
|
||||
"valid",
|
||||
|
@ -103,6 +104,7 @@ static const char *const patch_opt[] = {
|
|||
"getPixel",
|
||||
"setPixel",
|
||||
"copy",
|
||||
"clear",
|
||||
NULL};
|
||||
|
||||
static int patch_fields_ref = LUA_NOREF;
|
||||
|
@ -378,8 +380,17 @@ static int lib_patch_copy(lua_State *L)
|
|||
int src_img_width = -1;
|
||||
int src_img_height = -1;
|
||||
|
||||
patch_t *src_patch = NULL;
|
||||
|
||||
if (!lua_istable(L, 2))
|
||||
return luaL_typerror(L, 2, "table");
|
||||
{
|
||||
src_patch = *((patch_t **)luaL_checkudata(L, 2, META_PATCH));
|
||||
if (!src_patch)
|
||||
return LUA_ErrInvalid(L, "patch_t");
|
||||
|
||||
src_img_width = src_patch->width;
|
||||
src_img_height = src_patch->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
src_img_width = luaL_optinteger(L, 3, patch->width);
|
||||
|
@ -387,17 +398,17 @@ static int lib_patch_copy(lua_State *L)
|
|||
|
||||
lua_remove(L, 3);
|
||||
lua_remove(L, 3);
|
||||
}
|
||||
|
||||
if (src_img_width <= 0)
|
||||
return luaL_error(L, "invalid source image width");
|
||||
if (src_img_height <= 0)
|
||||
return luaL_error(L, "invalid source image height");
|
||||
if (src_img_width <= 0)
|
||||
return luaL_error(L, "invalid source image width");
|
||||
if (src_img_height <= 0)
|
||||
return luaL_error(L, "invalid source image height");
|
||||
}
|
||||
|
||||
int sx = luaL_optinteger(L, 3, 0);
|
||||
int sy = luaL_optinteger(L, 4, 0);
|
||||
int sw = luaL_optinteger(L, 5, patch->width);
|
||||
int sh = luaL_optinteger(L, 6, patch->height);
|
||||
int sw = luaL_optinteger(L, 5, src_img_width);
|
||||
int sh = luaL_optinteger(L, 6, src_img_height);
|
||||
int dx = luaL_optinteger(L, 7, 0);
|
||||
int dy = luaL_optinteger(L, 8, 0);
|
||||
boolean copy_transparent = lua_optboolean(L, 9);
|
||||
|
@ -407,12 +418,12 @@ static int lib_patch_copy(lua_State *L)
|
|||
if (sh <= 0)
|
||||
return luaL_error(L, "invalid copy rect height");
|
||||
|
||||
size_t size = (unsigned)(src_img_width * src_img_height);
|
||||
|
||||
img_prepare_buffer(size);
|
||||
|
||||
if (lua_istable(L, 2))
|
||||
{
|
||||
size_t size = (unsigned)(src_img_width * src_img_height);
|
||||
|
||||
img_prepare_buffer(size);
|
||||
|
||||
if (lua_objlen(L, 2) + 1 != size)
|
||||
return luaL_error(L, "invalid table length");
|
||||
|
||||
|
@ -422,9 +433,27 @@ static int lib_patch_copy(lua_State *L)
|
|||
img_get_pixels_from_table(L, size);
|
||||
|
||||
lua_pop(L, 2);
|
||||
|
||||
Patch_UpdatePixels(patch, patch_update_buffer, src_img_width, src_img_height, PICFMT_FLAT16, sx, sy, sw, sh, dx, dy, copy_transparent);
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawIntoPatch(patch, src_patch, dx << FRACBITS, dy << FRACBITS, FRACUNIT, FRACUNIT, 0, NULL, sx << FRACBITS, sy << FRACBITS, sw << FRACBITS, sh << FRACBITS, copy_transparent);
|
||||
}
|
||||
|
||||
Patch_UpdatePixels(patch, patch_update_buffer, src_img_width, src_img_height, PICFMT_FLAT16, sx, sy, sw, sh, dx, dy, copy_transparent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_patch_clear(lua_State *L)
|
||||
{
|
||||
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
|
||||
if (!patch)
|
||||
return LUA_ErrInvalid(L, "patch_t");
|
||||
|
||||
if (patch->type != PATCH_TYPE_DYNAMIC)
|
||||
return luaL_error(L, "cannot modify a static patch");
|
||||
|
||||
Patch_Clear(patch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -471,6 +500,9 @@ static int patch_get(lua_State *L)
|
|||
case patch_copy:
|
||||
lua_pushcfunction(L, lib_patch_copy);
|
||||
break;
|
||||
case patch_clear:
|
||||
lua_pushcfunction(L, lib_patch_clear);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
131
src/r_patch.c
131
src/r_patch.c
|
@ -19,7 +19,7 @@
|
|||
#include "hardware/hw_glob.h"
|
||||
#endif
|
||||
|
||||
static void Patch_MarkDirtyRect(dynamicpatch_t *dpatch, INT16 left, INT16 top, INT16 right, INT16 bottom);
|
||||
static boolean Patch_CheckDirtyRect(dynamicpatch_t *dpatch);
|
||||
static void Patch_ClearDirtyRect(dynamicpatch_t *dpatch);
|
||||
|
||||
patch_t *Patch_Create(INT16 width, INT16 height)
|
||||
|
@ -51,8 +51,15 @@ patch_t *Patch_CreateDynamic(INT16 width, INT16 height)
|
|||
return patch;
|
||||
}
|
||||
|
||||
static void Patch_MarkDirtyRect(dynamicpatch_t *dpatch, INT16 left, INT16 top, INT16 right, INT16 bottom)
|
||||
void Patch_MarkDirtyRect(patch_t *patch, INT16 left, INT16 top, INT16 right, INT16 bottom)
|
||||
{
|
||||
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
|
||||
|
||||
left = max(0, left);
|
||||
right = min(right, patch->width);
|
||||
top = max(0, top);
|
||||
bottom = min(bottom, patch->height);
|
||||
|
||||
if (left < dpatch->rect_dirty[0])
|
||||
dpatch->rect_dirty[0] = left;
|
||||
if (top < dpatch->rect_dirty[1])
|
||||
|
@ -63,6 +70,37 @@ static void Patch_MarkDirtyRect(dynamicpatch_t *dpatch, INT16 left, INT16 top, I
|
|||
dpatch->rect_dirty[3] = bottom;
|
||||
}
|
||||
|
||||
static boolean Patch_CheckDirtyRect(dynamicpatch_t *dpatch)
|
||||
{
|
||||
patch_t *patch = (patch_t*)dpatch;
|
||||
|
||||
// left
|
||||
if (dpatch->rect_dirty[0] < 0
|
||||
|| dpatch->rect_dirty[0] > patch->width
|
||||
|| dpatch->rect_dirty[0] >= dpatch->rect_dirty[2]) // right
|
||||
return false;
|
||||
|
||||
// top
|
||||
if (dpatch->rect_dirty[1] < 0
|
||||
|| dpatch->rect_dirty[1] > patch->height
|
||||
|| dpatch->rect_dirty[1] >= dpatch->rect_dirty[3]) // bottom
|
||||
return false;
|
||||
|
||||
// right
|
||||
if (dpatch->rect_dirty[2] > patch->width
|
||||
|| dpatch->rect_dirty[2] < 0
|
||||
|| dpatch->rect_dirty[2] <= dpatch->rect_dirty[0]) // left
|
||||
return false;
|
||||
|
||||
// bottom
|
||||
if (dpatch->rect_dirty[3] > patch->height
|
||||
|| dpatch->rect_dirty[3] < 0
|
||||
|| dpatch->rect_dirty[3] <= dpatch->rect_dirty[1]) // top
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Patch_ClearDirtyRect(dynamicpatch_t *dpatch)
|
||||
{
|
||||
dpatch->rect_dirty[0] = INT16_MAX;
|
||||
|
@ -83,6 +121,53 @@ static void Patch_InitDynamicColumns(patch_t *patch)
|
|||
}
|
||||
}
|
||||
|
||||
void Patch_Clear(patch_t *patch)
|
||||
{
|
||||
if (patch->type != PATCH_TYPE_DYNAMIC)
|
||||
return;
|
||||
|
||||
size_t total_pixels = patch->width * patch->height;
|
||||
|
||||
memset(patch->pixels, 0, total_pixels * sizeof(UINT8));
|
||||
|
||||
for (INT32 x = 0; x < patch->width; x++)
|
||||
patch->columns[x].num_posts = 0;
|
||||
|
||||
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
|
||||
|
||||
memset(dpatch->pixels_opaque, 0, BIT_ARRAY_SIZE(total_pixels));
|
||||
|
||||
dpatch->is_dirty = dpatch->update_columns = true;
|
||||
}
|
||||
|
||||
void Patch_ClearRect(patch_t *patch, INT16 x, INT16 y, INT16 width, INT16 height)
|
||||
{
|
||||
if (patch->type != PATCH_TYPE_DYNAMIC)
|
||||
return;
|
||||
|
||||
dynamicpatch_t *dpatch = (dynamicpatch_t*)patch;
|
||||
|
||||
for (INT16 dy = y; dy < y + height; dy++)
|
||||
{
|
||||
if (dy < 0)
|
||||
continue;
|
||||
else if (dy >= patch->height)
|
||||
break;
|
||||
|
||||
for (INT16 dx = x; dx < x + width; dx++)
|
||||
{
|
||||
if (dx < 0)
|
||||
continue;
|
||||
else if (dx >= patch->width)
|
||||
break;
|
||||
|
||||
size_t position = (dx * patch->height) + dy;
|
||||
unset_bit_array(dpatch->pixels_opaque, position);
|
||||
dpatch->is_dirty = dpatch->update_columns = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source)
|
||||
{
|
||||
patch_t *patch = (patch_t*)Patch_Create(0, 0);
|
||||
|
@ -337,16 +422,18 @@ void Patch_SetPixel(patch_t *patch, void *pixel, pictureformat_t informat, INT32
|
|||
{
|
||||
// No pixel in this position, so columns need to be rebuilt
|
||||
if (!in_bit_array(dpatch->pixels_opaque, position))
|
||||
{
|
||||
set_bit_array(dpatch->pixels_opaque, position);
|
||||
dpatch->update_columns = true;
|
||||
}
|
||||
|
||||
set_bit_array(dpatch->pixels_opaque, position);
|
||||
writePixelFunc(&patch->pixels[position], pixel);
|
||||
|
||||
dpatch->is_dirty = true;
|
||||
}
|
||||
|
||||
if (dpatch->is_dirty)
|
||||
Patch_MarkDirtyRect(dpatch, x, y, x + 1, y + 1);
|
||||
Patch_MarkDirtyRect(patch, x, y, x + 1, y + 1);
|
||||
}
|
||||
|
||||
void Patch_UpdatePixels(patch_t *patch,
|
||||
|
@ -409,12 +496,7 @@ void Patch_UpdatePixels(patch_t *patch,
|
|||
|
||||
dynamicpatch_t *dpatch = (dynamicpatch_t *)patch;
|
||||
|
||||
INT32 dest_x1 = max(0, dx);
|
||||
INT32 dest_x2 = min(dx + sw, patch->width);
|
||||
INT32 dest_y1 = max(0, dy);
|
||||
INT32 dest_y2 = min(dy + sh, patch->height);
|
||||
|
||||
Patch_MarkDirtyRect(dpatch, dest_x1, dest_y1, dest_x2, dest_y2);
|
||||
Patch_MarkDirtyRect(patch, dx, dy, dx + sw, dy + sh);
|
||||
|
||||
for (INT32 x = dx; x < dx + sw; x++, sx++)
|
||||
{
|
||||
|
@ -453,9 +535,15 @@ void Patch_UpdatePixels(patch_t *patch,
|
|||
}
|
||||
else
|
||||
{
|
||||
set_bit_array(dpatch->pixels_opaque, position);
|
||||
if (!in_bit_array(dpatch->pixels_opaque, position))
|
||||
{
|
||||
set_bit_array(dpatch->pixels_opaque, position);
|
||||
dpatch->update_columns = true;
|
||||
}
|
||||
|
||||
writePixelFunc(&patch->pixels[position], input);
|
||||
dpatch->update_columns = dpatch->is_dirty = true;
|
||||
|
||||
dpatch->is_dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -482,19 +570,22 @@ void Patch_DoDynamicUpdate(patch_t *patch)
|
|||
if (patch->columns == NULL)
|
||||
Patch_InitDynamicColumns(patch);
|
||||
|
||||
if (dpatch->update_columns)
|
||||
if (Patch_CheckDirtyRect(dpatch))
|
||||
{
|
||||
for (INT32 x = dpatch->rect_dirty[0]; x < dpatch->rect_dirty[2]; x++)
|
||||
Patch_RebuildColumn(&patch->columns[x], x, patch->height, dpatch->pixels_opaque);
|
||||
if (dpatch->update_columns)
|
||||
{
|
||||
for (INT32 x = dpatch->rect_dirty[0]; x < dpatch->rect_dirty[2]; x++)
|
||||
Patch_RebuildColumn(&patch->columns[x], x, patch->height, dpatch->pixels_opaque);
|
||||
}
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (patch->hardware)
|
||||
HWR_UpdatePatchRegion(patch, dpatch->rect_dirty[0], dpatch->rect_dirty[1], dpatch->rect_dirty[2], dpatch->rect_dirty[3]);
|
||||
#endif
|
||||
}
|
||||
|
||||
Patch_FreeMiscData(patch);
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (patch->hardware)
|
||||
HWR_UpdatePatchRegion(patch, dpatch->rect_dirty[0], dpatch->rect_dirty[1], dpatch->rect_dirty[2], dpatch->rect_dirty[3]);
|
||||
#endif
|
||||
|
||||
dpatch->is_dirty = false;
|
||||
dpatch->update_columns = false;
|
||||
|
||||
|
|
|
@ -37,6 +37,10 @@ void Patch_UpdatePixels(patch_t *patch,
|
|||
|
||||
boolean Patch_NeedsUpdate(patch_t *patch);
|
||||
void Patch_DoDynamicUpdate(patch_t *patch);
|
||||
void Patch_MarkDirtyRect(patch_t *dpatch, INT16 left, INT16 top, INT16 right, INT16 bottom);
|
||||
|
||||
void Patch_Clear(patch_t *patch);
|
||||
void Patch_ClearRect(patch_t *patch, INT16 x, INT16 y, INT16 width, INT16 height);
|
||||
|
||||
bitarray_t *Patch_GetOpaqueRegions(patch_t *patch);
|
||||
|
||||
|
|
146
src/v_video.c
146
src/v_video.c
|
@ -1064,6 +1064,152 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
|
|||
}
|
||||
}
|
||||
|
||||
void V_DrawIntoPatch(patch_t *dest_patch, patch_t *src_patch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 flags, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h, boolean copy_transparent)
|
||||
{
|
||||
if (dest_patch->type != PATCH_TYPE_DYNAMIC)
|
||||
return;
|
||||
|
||||
dynamicpatch_t *dpatch = (dynamicpatch_t *)dest_patch;
|
||||
|
||||
if (Patch_NeedsUpdate(src_patch))
|
||||
Patch_DoDynamicUpdate(src_patch);
|
||||
|
||||
if (src_patch->columns == NULL)
|
||||
return;
|
||||
|
||||
if (sx < 0)
|
||||
{
|
||||
w += sx;
|
||||
sx = 0;
|
||||
}
|
||||
if (sy < 0)
|
||||
{
|
||||
h += sy;
|
||||
sy = 0;
|
||||
}
|
||||
|
||||
if (sx >= src_patch->width << FRACBITS || w <= 0)
|
||||
return;
|
||||
if (sy >= src_patch->height << FRACBITS || h <= 0)
|
||||
return;
|
||||
|
||||
UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t) = standardpdraw;
|
||||
|
||||
v_translevel = NULL;
|
||||
v_colormap = NULL;
|
||||
|
||||
UINT32 alphalevel = ((flags & V_ALPHAMASK) >> V_ALPHASHIFT);
|
||||
UINT32 blendmode = ((flags & V_BLENDMASK) >> V_BLENDSHIFT);
|
||||
|
||||
if (alphalevel || blendmode)
|
||||
{
|
||||
if (alphalevel >= 10)
|
||||
return; // invis
|
||||
|
||||
if (alphalevel || blendmode)
|
||||
{
|
||||
v_translevel = R_GetBlendTable(blendmode+1, alphalevel);
|
||||
patchdrawfunc = translucentpdraw;
|
||||
}
|
||||
}
|
||||
|
||||
if (colormap)
|
||||
{
|
||||
v_colormap = colormap;
|
||||
patchdrawfunc = v_translevel ? transmappedpdraw : mappedpdraw;
|
||||
}
|
||||
|
||||
fixed_t fdup = pscale;
|
||||
fixed_t vdup = vscale;
|
||||
fixed_t colfrac = FixedDiv(FRACUNIT, fdup);
|
||||
fixed_t rowfrac = FixedDiv(FRACUNIT, vdup);
|
||||
|
||||
fixed_t offsetx = 0, offsety = 0;
|
||||
|
||||
// left offset
|
||||
if (flags & V_FLIP)
|
||||
offsetx = FixedMul((src_patch->width - src_patch->leftoffset)<<FRACBITS, pscale) + 1;
|
||||
else
|
||||
offsetx = FixedMul(src_patch->leftoffset<<FRACBITS, pscale);
|
||||
|
||||
// top offset
|
||||
offsety = FixedMul(src_patch->topoffset<<FRACBITS, vscale);
|
||||
|
||||
// Subtract the offsets from x/y positions
|
||||
x -= offsetx;
|
||||
y -= offsety;
|
||||
|
||||
x >>= FRACBITS;
|
||||
y >>= FRACBITS;
|
||||
|
||||
fixed_t pwidth = src_patch->width;
|
||||
if (pscale != FRACUNIT)
|
||||
pwidth = (pwidth * pscale) >> FRACBITS;
|
||||
|
||||
int dest_x = x;
|
||||
|
||||
Patch_MarkDirtyRect(dest_patch, x, y, x + (w >> FRACBITS), y + (h >> FRACBITS));
|
||||
|
||||
if (copy_transparent)
|
||||
Patch_ClearRect(dest_patch, x, y, w >> FRACBITS, h >> FRACBITS);
|
||||
|
||||
if (dest_patch->pixels == NULL)
|
||||
dest_patch->pixels = Z_Calloc(dest_patch->width * dest_patch->height, PU_PATCH_DATA, NULL);
|
||||
|
||||
for (fixed_t col = sx; (col>>FRACBITS) < src_patch->width && (col - sx) < w; col += colfrac, dest_x++)
|
||||
{
|
||||
if (dest_x < 0)
|
||||
continue;
|
||||
else if (dest_x >= dest_patch->width)
|
||||
break;
|
||||
|
||||
unsigned texturecolumn = col >> FRACBITS;
|
||||
if (flags & V_FLIP)
|
||||
texturecolumn = src_patch->width - 1 - texturecolumn;
|
||||
|
||||
column_t *column = &src_patch->columns[texturecolumn];
|
||||
|
||||
for (unsigned i = 0; i < column->num_posts; i++)
|
||||
{
|
||||
post_t *post = &column->posts[i];
|
||||
INT32 topdelta = post->topdelta << FRACBITS;
|
||||
UINT8 *source = column->pixels + post->data_offset;
|
||||
|
||||
int dest_y = y;
|
||||
|
||||
fixed_t ofs;
|
||||
if (topdelta - sy > 0)
|
||||
{
|
||||
dest_y = y + FixedInt(FixedMul(topdelta - sy, vdup));
|
||||
ofs = 0;
|
||||
}
|
||||
else
|
||||
ofs = sy - topdelta;
|
||||
|
||||
for (; dest_y < dest_patch->height && (size_t)(ofs>>FRACBITS) < post->length && ((ofs - sy) + topdelta) < h; ofs += rowfrac, dest_y++)
|
||||
{
|
||||
if (dest_y < 0)
|
||||
continue;
|
||||
|
||||
size_t position = (dest_x * dest_patch->height) + dest_y;
|
||||
if (!in_bit_array(dpatch->pixels_opaque, position))
|
||||
{
|
||||
set_bit_array(dpatch->pixels_opaque, position);
|
||||
dpatch->update_columns = true;
|
||||
}
|
||||
|
||||
UINT8 *dest = &dest_patch->pixels[position];
|
||||
*dest = patchdrawfunc(dest, source, ofs);
|
||||
|
||||
dpatch->is_dirty = true;
|
||||
}
|
||||
|
||||
if (dest_y >= dest_patch->height)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// V_DrawContinueIcon
|
||||
// Draw a mini player! If we can, that is. Otherwise we draw a star.
|
||||
|
|
|
@ -172,6 +172,7 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue);
|
|||
#define V_DrawFixedPatch(x,y,sc,s,p,c) V_DrawStretchyFixedPatch(x,y,sc,sc,s,p,c)
|
||||
void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap);
|
||||
void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h);
|
||||
void V_DrawIntoPatch(patch_t *dest_patch, patch_t *src_patch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 flags, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h, boolean copy_transparent);
|
||||
|
||||
void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 skincolor);
|
||||
|
||||
|
|
Loading…
Reference in a new issue