diff --git a/src/lua_colorlib.c b/src/lua_colorlib.c index e1665a0296d5c1c7fb6e83ecf818ca2d1da67a79..2365ffb440bb27bf5ccbd7ee4c7bbc5e9edf8f6f 100644 --- a/src/lua_colorlib.c +++ b/src/lua_colorlib.c @@ -22,7 +22,14 @@ #include "lua_script.h" #include "lua_libs.h" -static colorlookup_t colormix_lut; +#define COLORLIB_USE_LOOKUP + +#ifdef COLORLIB_USE_LOOKUP + static colorlookup_t colormix_lut; + #define GetNearestColor(r, g, b) GetColorLUT(&colormix_lut, r, g, b) +#else + #define GetNearestColor(r, g, b) NearestPaletteColor(r, g, b, pMasterPalette) +#endif static int colormap_get(lua_State *L) { @@ -46,6 +53,13 @@ static int colormap_set(lua_State *L) return 0; } +static int colormap_len(lua_State *L) +{ + colormap_t *colormap = *((colormap_t **)luaL_checkudata(L, 1, META_COLORMAP)); + lua_pushinteger(L, colormap->rows); + return 1; +} + static int colormap_free(lua_State *L) { colormap_t *colormap = *((colormap_t **)luaL_checkudata(L, 1, META_COLORMAP)); @@ -53,12 +67,12 @@ static int colormap_free(lua_State *L) return 0; } -static void MakeRGBColormap(UINT8 *colormap, UINT8 cr, UINT8 cg, UINT8 cb, UINT8 ca) +static void MakeRGBColormap(UINT8 *colormap, UINT8 cr, UINT8 cg, UINT8 cb, UINT8 ca, UINT16 start, UINT16 end) { double r, g, b, cbrightness; double map[256][3]; - size_t i; + INT32 i; ///////////////////// // Calc the RGBA mask @@ -76,15 +90,19 @@ static void MakeRGBColormap(UINT8 *colormap, UINT8 cr, UINT8 cg, UINT8 cb, UINT8 cmaskg *= maskamt; cmaskb *= maskamt; +#ifdef COLORLIB_USE_LOOKUP InitColorLUT(&colormix_lut, pMasterPalette, false); +#endif + + colormap += start; // map[i] stores an RGB color (as double) for index i, // which is then converted to SRB2's palette - for (i = 0; i < 256; i++) + for (i = start; i <= end; i++) { - r = pMasterPalette[i].s.red; - g = pMasterPalette[i].s.green; - b = pMasterPalette[i].s.blue; + r = pMasterPalette[*colormap].s.red; + g = pMasterPalette[*colormap].s.green; + b = pMasterPalette[*colormap].s.blue; cbrightness = sqrt((r*r) + (g*g) + (b*b)); map[i][0] = (cbrightness * cmaskr) + (r * othermask); @@ -99,7 +117,7 @@ static void MakeRGBColormap(UINT8 *colormap, UINT8 cr, UINT8 cg, UINT8 cb, UINT8 if (map[i][2] > 255.0l) map[i][2] = 255.0l; - *colormap = GetColorLUT(&colormix_lut, + *colormap = GetNearestColor( (UINT8)M_RoundUp(map[i][0]), (UINT8)M_RoundUp(map[i][1]), (UINT8)M_RoundUp(map[i][2])); @@ -189,7 +207,7 @@ static void GenerateColormap(lua_State *L, UINT8 *colormap) UINT8 g = luaL_checkinteger(L, 3); UINT8 b = luaL_checkinteger(L, 4); UINT8 a = luaL_optinteger(L, 5, 255); - MakeRGBColormap(colormap, r, g, b, a); + MakeRGBColormap(colormap, r, g, b, a, 0, NUM_PALETTE_ENTRIES - 1); break; } } @@ -240,7 +258,7 @@ static int lib_colormapMix(lua_State *L) INT32 amt = luaL_checkinteger(L, 3); INT32 mode = luaL_optinteger(L, 4, AST_TRANSLUCENT); INT32 start = luaL_optinteger(L, 5, 0); - INT32 end = luaL_optinteger(L, 6, NUM_PALETTE_ENTRIES-1), i; + INT32 end = luaL_optinteger(L, 6, NUM_PALETTE_ENTRIES) - 1, i; if (colormapA->flags & GTC_CACHE) return luaL_error(L, "colormap is read-only"); @@ -252,15 +270,17 @@ static int lib_colormapMix(lua_State *L) luaL_error(L, "blend mode %d out of range (%d - %d)", AST_COPY, AST_OVERLAY); if (start < 0 || start >= NUM_PALETTE_ENTRIES) - luaL_error(L, "translation start %d out of range (0 - %d)", start, NUM_PALETTE_ENTRIES-1); + luaL_error(L, "start index %d out of range (0 - %d)", start, NUM_PALETTE_ENTRIES-1); if (end <= 0) luaL_error(L, "invalid length %d (must be at least 1)", end); end += start; - if (end > NUM_PALETTE_ENTRIES) + if (end >= NUM_PALETTE_ENTRIES) end = NUM_PALETTE_ENTRIES - 1; +#ifdef COLORLIB_USE_LOOKUP InitColorLUT(&colormix_lut, pMasterPalette, false); +#endif for (i = start; i <= end; i++) { @@ -268,13 +288,55 @@ static int lib_colormapMix(lua_State *L) RGBA_t bg = V_GetMasterColor(colormapA->map[i]); RGBA_t fg = V_GetMasterColor(colormapB->map[i]); texel.rgba = ASTBlendPixel(bg, fg, mode, amt); - colormapA->map[i] = GetColorLUT(&colormix_lut, texel.s.red, texel.s.green, texel.s.blue); + colormapA->map[i] = GetNearestColor(texel.s.red, texel.s.green, texel.s.blue); } return 0; } -static int lib_colormapMixRGB(lua_State *L) +static int lib_colormapBlend(lua_State *L) +{ + colormap_t *colormap = *((colormap_t **)luaL_checkudata(L, 1, META_COLORMAP)); + RGBA_t fg = V_GetMasterColor((UINT8)luaL_checkinteger(L, 2)); + INT32 amt = luaL_checkinteger(L, 3); + INT32 mode = luaL_optinteger(L, 4, AST_TRANSLUCENT); + INT32 start = luaL_optinteger(L, 5, 0); + INT32 end = luaL_optinteger(L, 6, NUM_PALETTE_ENTRIES) - 1, i; + + if (colormap->flags & GTC_CACHE) + return luaL_error(L, "colormap is read-only"); + + if (amt < 0 || amt > 255) + luaL_error(L, "blend amount %d out of range (0 - %d)", amt, 255); + + if (mode < AST_COPY || mode > AST_OVERLAY) + luaL_error(L, "blend mode %d out of range (%d - %d)", AST_COPY, AST_OVERLAY); + + if (start < 0 || start >= NUM_PALETTE_ENTRIES) + luaL_error(L, "start index %d out of range (0 - %d)", start, NUM_PALETTE_ENTRIES-1); + if (end <= 0) + luaL_error(L, "invalid length %d (must be at least 1)", end); + + end += start; + if (end >= NUM_PALETTE_ENTRIES) + end = NUM_PALETTE_ENTRIES - 1; + +#ifdef COLORLIB_USE_LOOKUP + InitColorLUT(&colormix_lut, pMasterPalette, false); +#endif + + for (i = start; i <= end; i++) + { + RGBA_t texel; + RGBA_t bg = V_GetMasterColor(colormap->map[i]); + texel.rgba = ASTBlendPixel(bg, fg, mode, amt); + colormap->map[i] = GetNearestColor(texel.s.red, texel.s.green, texel.s.blue); + } + + return 0; +} + +static int lib_colormapBlendRGB(lua_State *L) { colormap_t *colormap = *((colormap_t **)luaL_checkudata(L, 1, META_COLORMAP)); UINT8 r = luaL_checkinteger(L, 2); @@ -283,7 +345,7 @@ static int lib_colormapMixRGB(lua_State *L) INT32 amt = luaL_checkinteger(L, 5); INT32 mode = luaL_optinteger(L, 6, AST_TRANSLUCENT); INT32 start = luaL_optinteger(L, 7, 0); - INT32 end = luaL_optinteger(L, 8, NUM_PALETTE_ENTRIES-1), i; + INT32 end = luaL_optinteger(L, 8, NUM_PALETTE_ENTRIES) - 1, i; RGBA_t fg; @@ -297,15 +359,17 @@ static int lib_colormapMixRGB(lua_State *L) luaL_error(L, "blend mode %d out of range (%d - %d)", AST_COPY, AST_OVERLAY); if (start < 0 || start >= NUM_PALETTE_ENTRIES) - luaL_error(L, "translation start %d out of range (0 - %d)", start, NUM_PALETTE_ENTRIES-1); + luaL_error(L, "start index %d out of range (0 - %d)", start, NUM_PALETTE_ENTRIES-1); if (end <= 0) luaL_error(L, "invalid length %d (must be at least 1)", end); end += start; - if (end > NUM_PALETTE_ENTRIES) + if (end >= NUM_PALETTE_ENTRIES) end = NUM_PALETTE_ENTRIES - 1; +#ifdef COLORLIB_USE_LOOKUP InitColorLUT(&colormix_lut, pMasterPalette, false); +#endif fg.s.red = r; fg.s.green = g; @@ -317,29 +381,87 @@ static int lib_colormapMixRGB(lua_State *L) RGBA_t texel; RGBA_t bg = V_GetMasterColor(colormap->map[i]); texel.rgba = ASTBlendPixel(bg, fg, mode, amt); - colormap->map[i] = GetColorLUT(&colormix_lut, texel.s.red, texel.s.green, texel.s.blue); + colormap->map[i] = GetNearestColor(texel.s.red, texel.s.green, texel.s.blue); } return 0; } +static int lib_colormapTint(lua_State *L) +{ + colormap_t *colormap = *((colormap_t **)luaL_checkudata(L, 1, META_COLORMAP)); + RGBA_t fg = V_GetMasterColor((UINT8)luaL_checkinteger(L, 2)); + INT32 amt = luaL_checkinteger(L, 3); + INT32 start = luaL_optinteger(L, 4, 0); + INT32 end = luaL_optinteger(L, 5, NUM_PALETTE_ENTRIES) - 1; + + if (colormap->flags & GTC_CACHE) + return luaL_error(L, "colormap is read-only"); + + if (amt < 0 || amt > 255) + luaL_error(L, "tint amount %d out of range (0 - %d)", amt, 255); + + if (start < 0 || start >= NUM_PALETTE_ENTRIES) + luaL_error(L, "start index %d out of range (0 - %d)", start, NUM_PALETTE_ENTRIES-1); + if (end <= 0) + luaL_error(L, "invalid length %d (must be at least 1)", end); + + end += start; + if (end >= NUM_PALETTE_ENTRIES) + end = NUM_PALETTE_ENTRIES - 1; + + MakeRGBColormap(colormap->map, fg.s.red, fg.s.green, fg.s.blue, amt, start, end); + + return 0; +} + +static int lib_colormapTintRGB(lua_State *L) +{ + colormap_t *colormap = *((colormap_t **)luaL_checkudata(L, 1, META_COLORMAP)); + UINT8 r = luaL_checkinteger(L, 2); + UINT8 g = luaL_checkinteger(L, 3); + UINT8 b = luaL_checkinteger(L, 4); + INT32 amt = luaL_checkinteger(L, 5); + INT32 start = luaL_optinteger(L, 6, 0); + INT32 end = luaL_optinteger(L, 7, NUM_PALETTE_ENTRIES) - 1; + + if (colormap->flags & GTC_CACHE) + return luaL_error(L, "colormap is read-only"); + + if (amt < 0 || amt > 255) + luaL_error(L, "tint amount %d out of range (0 - %d)", amt, 255); + + if (start < 0 || start >= NUM_PALETTE_ENTRIES) + luaL_error(L, "start index %d out of range (0 - %d)", start, NUM_PALETTE_ENTRIES-1); + if (end <= 0) + luaL_error(L, "invalid length %d (must be at least 1)", end); + + end += start; + if (end >= NUM_PALETTE_ENTRIES) + end = NUM_PALETTE_ENTRIES - 1; + + MakeRGBColormap(colormap->map, r, g, b, amt, start, end); + + return 0; +} + static int lib_colormapCopy(lua_State *L) { colormap_t *colormapA = *((colormap_t **)luaL_checkudata(L, 1, META_COLORMAP)); colormap_t *colormapB = *((colormap_t **)luaL_checkudata(L, 2, META_COLORMAP)); INT32 start = luaL_optinteger(L, 3, 0); - INT32 end = luaL_optinteger(L, 4, NUM_PALETTE_ENTRIES-1), i; + INT32 end = luaL_optinteger(L, 4, NUM_PALETTE_ENTRIES) - 1, i; if (colormapA->flags & GTC_CACHE) return luaL_error(L, "colormap is read-only"); if (start < 0 || start >= NUM_PALETTE_ENTRIES) - luaL_error(L, "index %d out of range (0 - %d)", start, NUM_PALETTE_ENTRIES-1); + luaL_error(L, "start index %d out of range (0 - %d)", start, NUM_PALETTE_ENTRIES-1); if (end <= 0) luaL_error(L, "invalid length %d (must be at least 1)", end); end += start; - if (end > NUM_PALETTE_ENTRIES) + if (end >= NUM_PALETTE_ENTRIES) end = NUM_PALETTE_ENTRIES - 1; for (i = start; i <= end; i++) @@ -362,10 +484,10 @@ static int lib_colormapCopySkinColor(lua_State *L) luaL_error(L, "skin color %d out of range (0 - %d)", skincolor, numskincolors-1); if (start < 0 || start >= NUM_PALETTE_ENTRIES) - luaL_error(L, "translation start %d out of range (0 - %d)", start, NUM_PALETTE_ENTRIES-1); + luaL_error(L, "start index %d out of range (0 - %d)", start, NUM_PALETTE_ENTRIES-1); - end = start + 16; - if (end > NUM_PALETTE_ENTRIES) + end = start + 15; + if (end >= NUM_PALETTE_ENTRIES) end = NUM_PALETTE_ENTRIES - 1; for (i = start; i <= end; i++, j++) @@ -378,7 +500,10 @@ static luaL_Reg lib[] = { {"create", lib_colormapCreate}, {"generate", lib_colormapGenerate}, {"mix", lib_colormapMix}, - {"mixRGB", lib_colormapMixRGB}, + {"blend", lib_colormapBlend}, + {"blendRGB", lib_colormapBlendRGB}, + {"tint", lib_colormapTint}, + {"tintRGB", lib_colormapTintRGB}, {"copy", lib_colormapCopy}, {"copySkinColor", lib_colormapCopySkinColor}, {NULL, NULL} @@ -393,9 +518,12 @@ int LUA_ColorLib(lua_State *L) lua_pushcfunction(L, colormap_set); lua_setfield(L, -2, "__newindex"); + lua_pushcfunction(L, colormap_len); + lua_setfield(L, -2, "__len"); + lua_pushcfunction(L, colormap_free); lua_setfield(L, -2, "__gc"); - lua_pop(L,1); + lua_pop(L, 1); luaL_register(L, "colormap", lib); return 0;