Video can now be scaled, rotated, and anti-aliased.

This commit is contained in:
Scott Duensing 2023-12-01 20:08:31 -06:00
parent edbad04ca6
commit 5173a88dc8

View file

@ -142,6 +142,10 @@ typedef struct VideoS {
bool wasPlayingBeforePause; bool wasPlayingBeforePause;
SDL_Texture *texture; SDL_Texture *texture;
SDL_Surface *surface; SDL_Surface *surface;
double angle;
double scaleX;
double scaleY;
int smooth;
UT_hash_handle hh; UT_hash_handle hh;
} VideoT; } VideoT;
@ -406,6 +410,10 @@ int32_t apiVideoIsPlaying(lua_State *L);
int32_t apiVideoLoad(lua_State *L); int32_t apiVideoLoad(lua_State *L);
int32_t apiVideoPause(lua_State *L); int32_t apiVideoPause(lua_State *L);
int32_t apiVideoPlay(lua_State *L); int32_t apiVideoPlay(lua_State *L);
int32_t apiVideoQuality(lua_State *L);
int32_t apiVideoRotate(lua_State *L);
int32_t apiVideoRotateAndScale(lua_State *L);
int32_t apiVideoScale(lua_State *L);
int32_t apiVideoSeek(lua_State *L); int32_t apiVideoSeek(lua_State *L);
int32_t apiVideoSetAudioTrack(lua_State *L); int32_t apiVideoSetAudioTrack(lua_State *L);
int32_t apiVideoSetVolume(lua_State *L); int32_t apiVideoSetVolume(lua_State *L);
@ -1935,8 +1943,8 @@ int32_t apiSpriteDraw(lua_State *L) {
// spriteDraw(x, y, id) - Simple draw // spriteDraw(x, y, id) - Simple draw
// spriteDraw(x, y, c, id) - Centered draw // spriteDraw(x, y, c, id) - Centered draw
// spriteDraw(x, y, x2, y2, id) - Scaled draw // spriteDraw(x, y, x2, y2, id) - Stretched draw
// spriteDraw(x, y, x2, y2, c, id) - Centered scaled draw // spriteDraw(x, y, x2, y2, c, id) - Centered Stretched draw
if ((n >= 3) && (n <= 6)) { if ((n >= 3) && (n <= 6)) {
if (lua_isnumber(L, 1)) { if (lua_isnumber(L, 1)) {
@ -1984,7 +1992,7 @@ int32_t apiSpriteDraw(lua_State *L) {
if (center) { if (center) {
// Move sprite so the drawing coordinate is the center of the sprite // Move sprite so the drawing coordinate is the center of the sprite
dest.x -= dest.w * 0.5; dest.x -= dest.w * 0.5;
dest.y -= dest.w * 0.5; dest.y -= dest.h * 0.5;
} }
if ((n == 3) || (n == 4)) { if ((n == 3) || (n == 4)) {
// No scaling // No scaling
@ -2286,23 +2294,37 @@ int32_t apiVideoDraw(lua_State *L) {
int64_t frame = 0; int64_t frame = 0;
double d = 0.0; double d = 0.0;
VideoT *video = NULL; VideoT *video = NULL;
bool center = false;
SDL_Rect dest; SDL_Rect dest;
SDL_Surface *surface = NULL;
if (n == 5) { // videoDraw(id, x1, y1, x2, y2) - Simple/Stretched draw
// videoDraw(id, x1, y1, c) - Scaled/Rotated draw
if ((n == 4) || (n == 5)) {
if (lua_isnumber(L, 1)) { if (lua_isnumber(L, 1)) {
if (lua_isnumber(L, 2)) { if (lua_isnumber(L, 2)) {
if (lua_isnumber(L, 3)) { if (lua_isnumber(L, 3)) {
if (lua_isnumber(L, 4)) { if (lua_isnumber(L, 4)) {
if (lua_isnumber(L, 5)) {
d = lua_tonumber(L, 1); id = (int32_t)d; d = lua_tonumber(L, 1); id = (int32_t)d;
d = lua_tonumber(L, 2); dest.x = (int32_t)d; d = lua_tonumber(L, 2); dest.x = (int32_t)d;
d = lua_tonumber(L, 3); dest.y = (int32_t)d; d = lua_tonumber(L, 3); dest.y = (int32_t)d;
if (n == 5) {
if (lua_isnumber(L, 5)) {
d = lua_tonumber(L, 4); dest.w = (int32_t)d - dest.x + 1; d = lua_tonumber(L, 4); dest.w = (int32_t)d - dest.x + 1;
d = lua_tonumber(L, 5); dest.h = (int32_t)d - dest.y + 1; d = lua_tonumber(L, 5); dest.h = (int32_t)d - dest.y + 1;
}
} else {
d = lua_tonumber(L, 4); center = (int32_t)d != 0;
dest.w = 0;
dest.h = 0;
}
// Get our video structure // Get our video structure
HASH_FIND_INT(_global.videoList, &id, video); HASH_FIND_INT(_global.videoList, &id, video);
if (!video) luaDie(L, "videoDraw", "No video at index %d in apiVideoDraw.", id); if (!video) luaDie(L, "videoDraw", "No video at index %d in apiVideoDraw.", id);
frame = videoUpdate(video->handle, &video->texture); frame = videoUpdate(video->handle, &video->texture);
// New Frame? // New Frame?
if (frame != video->lastFrame) { if (frame != video->lastFrame) {
// Get new frame into a surface - this is slow // Get new frame into a surface - this is slow
@ -2314,10 +2336,25 @@ int32_t apiVideoDraw(lua_State *L) {
if (SDL_RenderReadPixels(_global.renderer, NULL, video->surface->format->format, video->surface->pixels, video->surface->pitch) != 0) luaDie(L, "videoDraw", "%s", SDL_GetError()); if (SDL_RenderReadPixels(_global.renderer, NULL, video->surface->format->format, video->surface->pixels, video->surface->pitch) != 0) luaDie(L, "videoDraw", "%s", SDL_GetError());
if (SDL_SetRenderTarget(_global.renderer, NULL) < 0) luaDie(L, "videoDraw", "%s", SDL_GetError()); if (SDL_SetRenderTarget(_global.renderer, NULL) < 0) luaDie(L, "videoDraw", "%s", SDL_GetError());
} }
// Render frame into overlay // Render frame into overlay
if (SDL_BlitScaled(video->surface, NULL, _global.overlay, &dest) != 0) luaDie(L, "videoDraw", "%s", SDL_GetError()); if ((dest.w == 0) && (dest.h == 0)) {
result = true; surface = rotozoomSurfaceXY(video->surface, 360 - video->angle, video->scaleX, video->scaleY, video->smooth);
dest.w = surface->w;
dest.h = surface->h;
// Scaled/Rotated draw
if (center) {
// Move video so the drawing coordinate is the center of the video
dest.x -= dest.w * 0.5;
dest.y -= dest.h * 0.5;
} }
SDL_BlitSurface(surface, NULL, _global.overlay, &dest);
SDL_FreeSurface(surface);
} else {
// Simple/Stretched draw
if (SDL_BlitScaled(video->surface, NULL, _global.overlay, &dest) != 0) luaDie(L, "videoDraw", "%s", SDL_GetError());
}
result = true;
} }
} }
} }
@ -2683,6 +2720,145 @@ int32_t apiVideoPlay(lua_State *L) {
} }
int32_t apiVideoQuality(lua_State *L) {
int32_t n = lua_gettop(L);
int32_t id = -1;
int32_t s;
double d;
VideoT *video = NULL;
if (n == 2) {
if (lua_isnumber(L, 1)) {
if (lua_isnumber(L, 2)) {
d = lua_tonumber(L, 1); id = (int32_t)d;
d = lua_tonumber(L, 2); s = (int32_t)d;
HASH_FIND_INT(_global.videoList, &id, video);
if (!video) luaDie(L, "videoQuality", "No video at index %d in apiVideoQuality.", id);
video->smooth = s;
}
}
}
if (id >= 0) {
luaTrace(L, "videoQuality", "%d %d", id, video->smooth);
} else {
luaDie(L, "videoQuality", "Failed!");
}
return 0;
}
int32_t apiVideoRotate(lua_State *L) {
int32_t n = lua_gettop(L);
int32_t id = -1;
double d;
double a;
VideoT *video = NULL;
if (n == 2) {
if (lua_isnumber(L, 1)) {
if (lua_isnumber(L, 2)) {
d = lua_tonumber(L, 1); id = (int32_t)d;
d = lua_tonumber(L, 2); a = fmod(d, 360.0);
HASH_FIND_INT(_global.videoList, &id, video);
if (!video) luaDie(L, "videoRotate", "No video at index %d in apiVideoRotate.", id);
video->angle = a;
}
}
}
if (id >= 0) {
luaTrace(L, "videoRotate", "%d %f", id, video->angle);
} else {
luaDie(L, "videoRotate", "Failed!");
}
return 0;
}
int32_t apiVideoRotateAndScale(lua_State *L) {
int32_t n = lua_gettop(L);
int32_t id = -1;
double d;
double a;
double x;
double y;
VideoT *video = NULL;
if ((n == 3) || (n == 4)) {
if (lua_isnumber(L, 1)) {
d = lua_tonumber(L, 1); id = (int32_t)d;
if (lua_isnumber(L, 2)) {
if (lua_isnumber(L, 3)) {
d = lua_tonumber(L, 2); a = fmod(d, 360.0);
d = lua_tonumber(L, 3); x = d;
if (n == 3) {
y = x;
} else {
if (lua_isnumber(L, 4)) {
d = lua_tonumber(L, 4); y = (int32_t)d;
}
}
HASH_FIND_INT(_global.videoList, &id, video);
if (!video) luaDie(L, "videoRotateAndScale", "No video at index %d in apiVideoRotateAndScale.", id);
video->angle = a;
video->scaleX = x;
video->scaleY = y;
}
}
}
}
if (id >= 0) {
luaTrace(L, "videoRotateAndScale", "%d %f %f %f", id, video->angle, video->scaleX, video->scaleY);
} else {
luaDie(L, "videoRotateAndScale", "Failed!");
}
return 0;
}
int32_t apiVideoScale(lua_State *L) {
int32_t n = lua_gettop(L);
int32_t id = -1;
double d;
double x;
double y;
VideoT *video = NULL;
if ((n == 2) || (n == 3)) {
if (lua_isnumber(L, 1)) {
d = lua_tonumber(L, 1); id = (int32_t)d;
if (lua_isnumber(L, 2)) {
d = lua_tonumber(L, 2); x = d;
if (n == 2) {
y = x;
} else {
if (lua_isnumber(L, 3)) {
d = lua_tonumber(L, 3); y = d;
}
}
HASH_FIND_INT(_global.videoList, &id, video);
if (!video) luaDie(L, "videoScale", "No video at index %d in apiVideoScale.", id);
video->scaleX = x;
video->scaleY = y;
}
}
}
if (id >= 0) {
luaTrace(L, "videoScale", "%d %f %f", id, video->scaleX, video->scaleY);
} else {
luaDie(L, "videoScale", "Failed!");
}
return 0;
}
int32_t apiVideoSeek(lua_State *L) { int32_t apiVideoSeek(lua_State *L) {
int32_t n = lua_gettop(L); int32_t n = lua_gettop(L);
bool result = false; bool result = false;
@ -4233,6 +4409,10 @@ void singe(SDL_Window *window, SDL_Renderer *renderer, ConfigT *conf) {
lua_register(_global.luaContext, "videoLoad", apiVideoLoad); lua_register(_global.luaContext, "videoLoad", apiVideoLoad);
lua_register(_global.luaContext, "videoPause", apiVideoPause); lua_register(_global.luaContext, "videoPause", apiVideoPause);
lua_register(_global.luaContext, "videoPlay", apiVideoPlay); lua_register(_global.luaContext, "videoPlay", apiVideoPlay);
lua_register(_global.luaContext, "videoQuality", apiVideoQuality);
lua_register(_global.luaContext, "videoRotate", apiVideoRotate);
lua_register(_global.luaContext, "videoRotateAndScale", apiVideoRotateAndScale);
lua_register(_global.luaContext, "videoScale", apiVideoScale);
lua_register(_global.luaContext, "videoSeek", apiVideoSeek); lua_register(_global.luaContext, "videoSeek", apiVideoSeek);
lua_register(_global.luaContext, "videoSetAudioTrack", apiVideoSetAudioTrack); lua_register(_global.luaContext, "videoSetAudioTrack", apiVideoSetAudioTrack);
lua_register(_global.luaContext, "videoSetVolume", apiVideoSetVolume); lua_register(_global.luaContext, "videoSetVolume", apiVideoSetVolume);