- store video stashes in linked lists
- cube face textures demo - only dispatch events to active nodes - only update animation if containing object is active
This commit is contained in:
parent
d7f1877cbe
commit
b2f5f56063
|
@ -1,9 +1,10 @@
|
|||
/***
|
||||
|
||||
reset, pause, auto reset, analog d-pad, gamepad config, any key, confirm exit
|
||||
game, screen wipes, screen offset, screen scale, networking
|
||||
game, screen wipes, screen offset, screen scale, networking, post processing
|
||||
:) SWEATY HANDS :) OILY SNACKS :) AND BAD HYGIENE :)
|
||||
*surf wizard*
|
||||
*Exxiit* eXIt
|
||||
|
||||
***/
|
||||
|
||||
|
@ -73,9 +74,9 @@ GLuint get_gl_texture_from_surface(SDL_Surface *surface, GLint mipmap_filter)
|
|||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
GLenum format;
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
format = GL_RGBA;
|
||||
#else
|
||||
format = GL_BGRA;
|
||||
#else
|
||||
format = GL_RGBA;
|
||||
#endif
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, format,
|
||||
GL_UNSIGNED_BYTE, surface->pixels);
|
||||
|
@ -142,7 +143,8 @@ void Mushroom::update()
|
|||
|
||||
Demo::Demo()
|
||||
{
|
||||
Mix_Music *music = Mix_LoadMUS("resource/Field.mp3");
|
||||
// Mix_Music *music = Mix_LoadMUS("resource/Field.mp3");
|
||||
Mix_Music *music = Mix_LoadMUS("/home/frank/WATERMELON-clean.mp3");
|
||||
Mix_PlayMusic(music, -1);
|
||||
load_gl_context();
|
||||
delegate.subscribe(&Demo::respond, this);
|
||||
|
@ -219,10 +221,19 @@ void Demo::load_gl_context()
|
|||
100.0f);
|
||||
view = glm::lookAt(
|
||||
glm::vec3(4, 3, 3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
|
||||
SDL_Surface *surface = rotateSurface90Degrees(IMG_Load("resource/tile.png"), 2);
|
||||
SDL_Surface* surface = zoomSurface(
|
||||
rotateSurface90Degrees(IMG_Load("resource/tile.png"), 2), 1, -1, SMOOTHING_OFF);
|
||||
SDL_Log("tile.png bytes per pixel %i", surface->format->BytesPerPixel);
|
||||
space_texture_id = get_gl_texture_from_surface(surface, GL_LINEAR);
|
||||
SDL_FreeSurface(surface);
|
||||
std::vector<fs::path> paths = sfw::glob("/home/frank/projects/public/games/rov/face03/[0-9]+\\-.+\\.png");
|
||||
for (fs::path path : paths)
|
||||
{
|
||||
surface = zoomSurface(rotateSurface90Degrees(IMG_Load(path.c_str()), 2), -1, 1, SMOOTHING_OFF);
|
||||
SDL_Log("loading %s", path.c_str());
|
||||
face_ids.push_back(get_gl_texture_from_surface(surface, GL_LINEAR));
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
std::array<glm::vec2, 6> framerate_indicator_uv = {
|
||||
{
|
||||
{0, 1}, {1, 1}, {0, 0},
|
||||
|
@ -296,8 +307,8 @@ void Demo::load_gl_context()
|
|||
link_shader(flat_program);
|
||||
mvp_id = glGetUniformLocation(world_program, "MVP");
|
||||
// GLuint sampler_uniform_id = glGetUniformLocation(world_program, "myTextureSampler");
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, space_texture_id);
|
||||
// glActiveTexture(GL_TEXTURE0);
|
||||
// glBindTexture(GL_TEXTURE_2D, space_texture_id);
|
||||
// glUniform1i(sampler_uniform_id, 0);
|
||||
glDepthFunc(GL_LESS);
|
||||
frame_count_timestamp = SDL_GetTicks();
|
||||
|
@ -399,7 +410,9 @@ void Demo::update()
|
|||
{
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
|
||||
// glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), diamond, GL_STATIC_DRAW);
|
||||
glClearColor(.7, .7, .5, 1);
|
||||
// glColorMask(false, false, false, true);
|
||||
// glClearColor(.7, .7, .5, 1);
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glUseProgram(flat_program);
|
||||
|
@ -417,18 +430,27 @@ void Demo::update()
|
|||
glDrawArrays(GL_TRIANGLES, 42, 6);
|
||||
}
|
||||
// printf("%s\n", glm::to_string(model).c_str());
|
||||
model = glm::rotate(model, .0005f * frame_length, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
float rotation = .0005f * frame_length;
|
||||
model = glm::rotate(model, rotation, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
mvp = projection * view * model;
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glUseProgram(world_program);
|
||||
glUniformMatrix4fv(mvp_id, 1, GL_FALSE, &mvp[0][0]);
|
||||
glBindTexture(GL_TEXTURE_2D, space_texture_id);
|
||||
glEnableVertexAttribArray(1);
|
||||
glDisableVertexAttribArray(2);
|
||||
glVertexAttrib3f(2, 1, 1, 1);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
for (int ii = 0; ii < 6; ii++)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, face_ids[ii]);
|
||||
glDrawArrays(GL_TRIANGLES, ii * 6, 6);
|
||||
}
|
||||
//glFlush();
|
||||
SDL_GL_SwapWindow(window);
|
||||
// if (amount_rotated < 3.14f * 2)
|
||||
// {
|
||||
// recorder.capture_screen();
|
||||
// }
|
||||
amount_rotated += rotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -63,6 +63,8 @@ struct Demo : Game
|
|||
glm::mat4 projection, view, model = glm::mat4(1.0f), mvp;
|
||||
Mushroom mushroom = Mushroom(this);
|
||||
Sprite grass = Sprite(this, "resource/Field.png");
|
||||
std::vector<GLuint> face_ids;
|
||||
float amount_rotated;
|
||||
|
||||
Demo();
|
||||
void load_sdl_context();
|
||||
|
|
|
@ -40,8 +40,8 @@ $(SFW_SRC_DIR)Sprite.o: $(addprefix $(SFW_SRC_DIR),Game.*pp Location.*pp Node.*p
|
|||
$(SFW_SRC_DIR)Game.o: $(addprefix $(SFW_SRC_DIR),Sprite.*pp Configuration.*pp Delegate.*pp Display.*pp \
|
||||
Recorder.*pp Node.*pp Input.*pp)
|
||||
$(SFW_SRC_DIR)Node.o: $(addprefix $(SFW_SRC_DIR),Game.*pp Configuration.*pp Delegate.*pp)
|
||||
$(SFW_SRC_DIR)Animation.o: $(addprefix $(SFW_SRC_DIR),Timer.*pp)
|
||||
$(SFW_SRC_DIR)Recorder.o: $(addprefix $(SFW_SRC_DIR),extension.*pp Node.*pp Delegate.*pp Animation.*pp)
|
||||
$(SFW_SRC_DIR)Animation.o: $(addprefix $(SFW_SRC_DIR),Node.*pp Timer.*pp)
|
||||
$(SFW_SRC_DIR)Recorder.o: $(addprefix $(SFW_SRC_DIR),extension.*pp Node.*pp Delegate.*pp Animation.*pp Display.*pp)
|
||||
$(SFW_SRC_DIR)Input.o: $(addprefix $(SFW_SRC_DIR),Delegate.*pp Node.*pp)
|
||||
$(SFW_SRC_DIR)Configuration.o: $(addprefix $(SFW_SRC_DIR),Node.*pp)
|
||||
$(SFW_SRC_DIR)Delegate.o: $(addprefix $(SFW_SRC_DIR),Node.*pp)
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
},
|
||||
"recording":
|
||||
{
|
||||
"enabled": true,
|
||||
"write-mp4": true,
|
||||
"video-frame-length": 33.334
|
||||
"video-frame-length": 16.667,
|
||||
"max-video-memory": 2000
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ void Animation::reset()
|
|||
void Animation::update()
|
||||
{
|
||||
timer.update();
|
||||
if (playing and not paused)
|
||||
if (playing and not paused and containing_object->is_active())
|
||||
{
|
||||
if (delay > 0)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <functional>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Node.hpp"
|
||||
#include "Timer.hpp"
|
||||
|
||||
typedef std::function<void()> callback;
|
||||
|
@ -16,6 +17,7 @@ struct Animation
|
|||
int previous_step_time = 0, overflow = 0, count = 0;
|
||||
float delay = 0, frame_length;
|
||||
callback step;
|
||||
Node* containing_object;
|
||||
Timer timer = Timer();
|
||||
|
||||
template<typename T>
|
||||
|
@ -23,6 +25,7 @@ struct Animation
|
|||
{
|
||||
step = std::bind(f, o);
|
||||
timer.toggle(false);
|
||||
containing_object = static_cast<Node*>(o);
|
||||
}
|
||||
|
||||
void set_frame_length(float);
|
||||
|
|
|
@ -34,6 +34,7 @@ void Configuration::set_defaults()
|
|||
{"fps", 60}
|
||||
};
|
||||
sys_config["recording"] = {
|
||||
{"enabled", false},
|
||||
{"screenshot-prefix", "screenshot-"},
|
||||
{"screenshot-extension", ".png"},
|
||||
{"screenshot-zfill", 5},
|
||||
|
|
|
@ -24,7 +24,10 @@ void Delegate::dispatch()
|
|||
{
|
||||
for (Subscriber s : iter->second)
|
||||
{
|
||||
s.f(event);
|
||||
if (s.o->is_active())
|
||||
{
|
||||
s.f(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
struct Subscriber
|
||||
{
|
||||
std::function<void(SDL_Event&)> f;
|
||||
void* o;
|
||||
Node* o;
|
||||
};
|
||||
|
||||
struct Delegate : Node
|
||||
|
@ -34,7 +34,7 @@ struct Delegate : Node
|
|||
template<typename T>
|
||||
void subscribe(void(T::*f)(SDL_Event&), T* o, int type = command_event_type)
|
||||
{
|
||||
add_subscriber({std::bind(f, o, std::placeholders::_1), o}, type);
|
||||
add_subscriber({std::bind(f, o, std::placeholders::_1), static_cast<Node*>(o)}, type);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -16,19 +16,25 @@ void Display::get_screen_pixels(unsigned char* pixels, int w, int h, int x, int
|
|||
{
|
||||
GLenum format;
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
format = GL_RGBA;
|
||||
#else
|
||||
format = GL_BGRA;
|
||||
#else
|
||||
format = GL_RGBA;
|
||||
#endif
|
||||
glReadBuffer(GL_FRONT);
|
||||
glReadPixels(x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
|
||||
// SDL_Log("(%i, %i, %i) (%i, %i, %i, %i)",
|
||||
// glCheckFramebufferStatus(GL_FRAMEBUFFER),
|
||||
// glCheckFramebufferStatus(GL_READ_FRAMEBUFFER),
|
||||
// glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER),
|
||||
// pixels[0], pixels[1], pixels[2], pixels[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Uint32 format;
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
format = SDL_PIXELFORMAT_ABGR8888;
|
||||
#else
|
||||
format = SDL_PIXELFORMAT_ARGB8888;
|
||||
#else
|
||||
format = SDL_PIXELFORMAT_ABGR8888;
|
||||
#endif
|
||||
SDL_RenderReadPixels(
|
||||
get_root()->renderer, NULL, format, pixels, bpp / 8 * w);
|
||||
|
@ -51,16 +57,28 @@ SDL_Surface* Display::get_screen_surface_from_pixels(
|
|||
{
|
||||
glm::ivec2 size = get_window_size();
|
||||
SDL_Surface* surface;
|
||||
Uint32 rmask, gmask, bmask, amask;
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
rmask = 0xff000000;
|
||||
gmask = 0x00ff0000;
|
||||
bmask = 0x0000ff00;
|
||||
amask = 0x000000ff;
|
||||
#else
|
||||
rmask = 0x000000ff;
|
||||
gmask = 0x0000ff00;
|
||||
bmask = 0x00ff0000;
|
||||
amask = 0xff000000;
|
||||
#endif
|
||||
if (flip)
|
||||
{
|
||||
SDL_Surface* pixel_surface = SDL_CreateRGBSurfaceFrom(
|
||||
pixels, size.x, size.y, bpp, bpp / 8 * size.x, 0, 0, 0, 0);
|
||||
pixels, size.x, size.y, bpp, bpp / 8 * size.x, rmask, gmask, bmask, amask);
|
||||
surface = zoomSurface(pixel_surface, 1, -1, SMOOTHING_OFF);
|
||||
SDL_FreeSurface(pixel_surface);
|
||||
}
|
||||
else
|
||||
{
|
||||
surface = SDL_CreateRGBSurface(0, size.x, size.y, bpp, 0, 0, 0, 0);
|
||||
surface = SDL_CreateRGBSurface(0, size.x, size.y, bpp, rmask, gmask, bmask, amask);
|
||||
std::memcpy(surface->pixels, pixels, bpp / 8 * size.x * size.y);
|
||||
}
|
||||
return surface;
|
||||
|
|
308
src/Game.cpp
308
src/Game.cpp
|
@ -13,7 +13,7 @@ Game::Game()
|
|||
delegate.subscribe(&Game::handle_quit_event, this, SDL_QUIT);
|
||||
SDL_Log("GLEW %s", glewGetString(GLEW_VERSION));
|
||||
putenv("SDL_VIDEO_X11_LEGACY_FULLSCREEN=0");
|
||||
putenv("SDL_VIDEO_CENTERED=0");
|
||||
// putenv("SDL_VIDEO_CENTERED=0");
|
||||
SDL_version version;
|
||||
SDL_GetVersion(&version);
|
||||
SDL_Log("SDL %d.%d.%d", version.major, version.minor, version.patch);
|
||||
|
@ -31,9 +31,14 @@ Game::Game()
|
|||
// SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
|
||||
print_gl_attributes();
|
||||
std::vector<int> window_size = get_configuration()["display"]["dimensions"];
|
||||
window = SDL_CreateWindow("TARE control", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
window = SDL_CreateWindow("TARE control", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
window_size[0], window_size[1], SDL_WINDOW_OPENGL);
|
||||
if (window == NULL)
|
||||
{
|
||||
|
@ -74,9 +79,9 @@ Game::Game()
|
|||
SDL_GetAudioDeviceName(ii, SDL_TRUE));
|
||||
}
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
SDL_Log("big endian, using GL_RGBA and SDL_PIXELFORMAT_ABGR8888");
|
||||
SDL_Log("big endian");
|
||||
#else
|
||||
SDL_Log("little endian, using GL_BGRA and SDL_PIXELFORMAT_ARGB8888");
|
||||
SDL_Log("little endian");
|
||||
#endif
|
||||
last_frame_timestamp = SDL_GetTicks();
|
||||
}
|
||||
|
@ -133,6 +138,7 @@ void Game::load_sdl_context()
|
|||
info.max_texture_height);
|
||||
}
|
||||
is_gl_context = false;
|
||||
log_display_mode();
|
||||
}
|
||||
|
||||
void Game::load_gl_context()
|
||||
|
@ -162,6 +168,7 @@ void Game::load_gl_context()
|
|||
glGetString(GL_VERSION), glGetString(GL_RENDERER),
|
||||
glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
is_gl_context = true;
|
||||
log_display_mode();
|
||||
}
|
||||
|
||||
GLuint Game::create_gl_texture()
|
||||
|
@ -172,7 +179,7 @@ GLuint Game::create_gl_texture()
|
|||
return id;
|
||||
}
|
||||
|
||||
bool Game::log_gl_errors()
|
||||
bool Game::log_gl_errors(std::string suffix)
|
||||
{
|
||||
GLenum error;
|
||||
bool error_logged = false;
|
||||
|
@ -184,186 +191,213 @@ bool Game::log_gl_errors()
|
|||
SDL_LogError(
|
||||
SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GL_INVALID_ENUM, an unacceptable value is specified for an "
|
||||
"enumerated argument");
|
||||
"enumerated argument %s", suffix.c_str());
|
||||
}
|
||||
else if (error == GL_INVALID_VALUE)
|
||||
{
|
||||
SDL_LogError(
|
||||
SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GL_INVALID_VALUE, a numeric argument is out of range");
|
||||
"GL_INVALID_VALUE, a numeric argument is out of range %s", suffix.c_str());
|
||||
}
|
||||
else if (error == GL_INVALID_OPERATION)
|
||||
{
|
||||
SDL_LogError(
|
||||
SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GL_INVALID_OPERATION, the specified operation is not allowed "
|
||||
"in the current state");
|
||||
"in the current state %s", suffix.c_str());
|
||||
}
|
||||
else if (error == GL_INVALID_FRAMEBUFFER_OPERATION)
|
||||
{
|
||||
SDL_LogError(
|
||||
SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GL_INVALID_FRAMEBUFFER_OPERATION, the framebuffer object is "
|
||||
"not complete");
|
||||
"not complete %s", suffix.c_str());
|
||||
}
|
||||
else if (error == GL_OUT_OF_MEMORY)
|
||||
{
|
||||
SDL_LogError(
|
||||
SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GL_OUT_OF_MEMORY, there is not enough memory left to execute "
|
||||
"the command");
|
||||
"the command %s", suffix.c_str());
|
||||
}
|
||||
else if (error == GL_STACK_UNDERFLOW)
|
||||
{
|
||||
SDL_LogError(
|
||||
SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GL_STACK_UNDERFLOW, an attempt has been made to perform an "
|
||||
"operation that would cause an internal stack to underflow.");
|
||||
"operation that would cause an internal stack to underflow. %s", suffix.c_str());
|
||||
}
|
||||
else if (error == GL_STACK_OVERFLOW)
|
||||
{
|
||||
SDL_LogError(
|
||||
SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GL_STACK_OVERFLOW, an attempt has been made to perform an "
|
||||
"operation that would cause an internal stack to overflow.");
|
||||
"operation that would cause an internal stack to overflow. %s", suffix.c_str());
|
||||
}
|
||||
}
|
||||
return error_logged;
|
||||
}
|
||||
|
||||
// from SDL_GetCurrentDisplayMode.html
|
||||
void Game::log_display_mode()
|
||||
{
|
||||
SDL_DisplayMode current;
|
||||
for (int ii = 0; ii < SDL_GetNumVideoDisplays(); ii++)
|
||||
{
|
||||
int mode = SDL_GetCurrentDisplayMode(ii, ¤t);
|
||||
if (mode != 0)
|
||||
{
|
||||
SDL_Log("Could not get display mode for video display #%d: %s", ii,
|
||||
SDL_GetError());
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_Log("Display #%d: display mode is %dx%dpx @ %dhz %s", ii,
|
||||
current.w, current.h, current.refresh_rate,
|
||||
get_pixel_format_string(current.format).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::log_surface_format(SDL_Surface* surface, std::string preface)
|
||||
{
|
||||
SDL_PixelFormat* format = surface->format;
|
||||
std::string pixel_format;
|
||||
if (format->format == SDL_PIXELFORMAT_UNKNOWN)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_UNKNOWN";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_INDEX1LSB)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_INDEX1LSB";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_INDEX1MSB)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_INDEX1MSB";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_INDEX4LSB)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_INDEX4LSB";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_INDEX4MSB)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_INDEX4MSB";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_INDEX8)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_INDEX8";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_RGB332)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGB332";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_RGB444)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGB444";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_RGB555)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGB555";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_BGR555)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGR555";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_ARGB4444)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ARGB4444";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_RGBA4444)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGBA4444";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_ABGR4444)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ABGR4444";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_BGRA4444)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGRA4444";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_ARGB1555)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ARGB1555";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_RGBA5551)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGBA5551";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_ABGR1555)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ABGR1555";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_BGRA5551)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGRA5551";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_RGB565)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGB565";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_BGR565)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGR565";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_RGB24)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGB24";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_BGR24)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGR24";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_RGB888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGB888";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_RGBX8888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGBX8888";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_BGR888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGR888";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_BGRX8888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGRX8888";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_ARGB8888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ARGB8888";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_RGBA8888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGBA8888";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_ABGR8888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ABGR8888";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_BGRA8888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGRA8888";
|
||||
}
|
||||
else if (format->format == SDL_PIXELFORMAT_ARGB2101010)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ARGB2101010";
|
||||
}
|
||||
std::string pixel_format = get_pixel_format_string(format->format);
|
||||
SDL_Log("%s bpp: %i mask: %i %i %i %i format: %s", preface.c_str(),
|
||||
format->BytesPerPixel, format->Rmask, format->Gmask, format->Bmask,
|
||||
format->Amask, pixel_format.c_str());
|
||||
}
|
||||
|
||||
std::string Game::get_pixel_format_string(Uint32 format)
|
||||
{
|
||||
std::string pixel_format;
|
||||
if (format == SDL_PIXELFORMAT_UNKNOWN)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_UNKNOWN";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_INDEX1LSB)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_INDEX1LSB";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_INDEX1MSB)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_INDEX1MSB";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_INDEX4LSB)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_INDEX4LSB";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_INDEX4MSB)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_INDEX4MSB";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_INDEX8)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_INDEX8";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_RGB332)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGB332";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_RGB444)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGB444";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_RGB555)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGB555";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_BGR555)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGR555";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_ARGB4444)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ARGB4444";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_RGBA4444)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGBA4444";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_ABGR4444)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ABGR4444";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_BGRA4444)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGRA4444";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_ARGB1555)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ARGB1555";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_RGBA5551)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGBA5551";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_ABGR1555)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ABGR1555";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_BGRA5551)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGRA5551";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_RGB565)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGB565";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_BGR565)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGR565";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_RGB24)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGB24";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_BGR24)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGR24";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_RGB888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGB888";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_RGBX8888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGBX8888";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_BGR888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGR888";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_BGRX8888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGRX8888";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_ARGB8888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ARGB8888";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_RGBA8888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_RGBA8888";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_ABGR8888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ABGR8888";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_BGRA8888)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_BGRA8888";
|
||||
}
|
||||
else if (format == SDL_PIXELFORMAT_ARGB2101010)
|
||||
{
|
||||
pixel_format = "SDL_PIXELFORMAT_ARGB2101010";
|
||||
}
|
||||
return pixel_format;
|
||||
}
|
||||
|
||||
void Game::run()
|
||||
{
|
||||
while (not done)
|
||||
|
|
|
@ -46,7 +46,7 @@ struct Game : Node
|
|||
int frame_time_overflow = 0, framerate, ticks, last_frame_timestamp,
|
||||
frame_count_timestamp, last_frame_length;
|
||||
float frame_length;
|
||||
bool done = false, show_framerate = false, is_gl_context = true;
|
||||
bool done = false, show_framerate = true, is_gl_context = true;
|
||||
Configuration configuration = Configuration(this);
|
||||
Delegate delegate = Delegate(this);
|
||||
Display display = Display(this);
|
||||
|
@ -61,8 +61,10 @@ struct Game : Node
|
|||
void load_sdl_context();
|
||||
void load_gl_context();
|
||||
GLuint create_gl_texture();
|
||||
bool log_gl_errors();
|
||||
bool log_gl_errors(std::string);
|
||||
void log_display_mode();
|
||||
void log_surface_format(SDL_Surface*, std::string = "surface");
|
||||
std::string get_pixel_format_string(Uint32);
|
||||
void run();
|
||||
void flag_to_end();
|
||||
virtual void update() {};
|
||||
|
|
|
@ -32,6 +32,11 @@ void Node::deactivate()
|
|||
active = false;
|
||||
}
|
||||
|
||||
bool Node::is_active()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
nlohmann::json& Node::get_configuration()
|
||||
{
|
||||
return get_root()->configuration.config;
|
||||
|
|
|
@ -20,10 +20,11 @@ struct Node
|
|||
bool active = false;
|
||||
|
||||
Node();
|
||||
Node(Node*, bool = false);
|
||||
Node(Node*, bool = true);
|
||||
virtual ~Node();
|
||||
void activate();
|
||||
void deactivate();
|
||||
bool is_active();
|
||||
Game* get_root();
|
||||
nlohmann::json& get_configuration();
|
||||
Delegate& get_delegate();
|
||||
|
|
|
@ -7,7 +7,10 @@ Recorder::Recorder(Node* parent) : Node(parent)
|
|||
get_delegate().subscribe(&Recorder::respond, this);
|
||||
animation.play();
|
||||
Mix_SetPostMix(&process_audio, this);
|
||||
video_stashes.reserve(100);
|
||||
if (not get_configuration()["recording"]["enabled"])
|
||||
{
|
||||
deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
float Recorder::get_frame_length()
|
||||
|
@ -87,9 +90,7 @@ void Recorder::grab_stash()
|
|||
void Recorder::write_most_recent_frames()
|
||||
{
|
||||
make_directory();
|
||||
write_stash_frames(&most_recent_stash.pixel_buffers,
|
||||
&most_recent_stash.flipped,
|
||||
most_recent_stash.frame_offset);
|
||||
write_stash_frames(&most_recent_stash);
|
||||
open_audio_file();
|
||||
while (not most_recent_stash.audio_buffers.empty())
|
||||
{
|
||||
|
@ -136,7 +137,7 @@ void Recorder::open_audio_file()
|
|||
void Recorder::add_frame()
|
||||
{
|
||||
glm::ivec2 size = get_display().get_window_size();
|
||||
int bytes = 32 / 8 * size.x * size.y;
|
||||
int bytes = Display::bpp / 8 * size.x * size.y;
|
||||
unsigned char* pixels = new unsigned char[bytes];
|
||||
get_display().get_screen_pixels(pixels, size.x, size.y);
|
||||
int max_length = get_configuration()["recording"]["max-stash-length"];
|
||||
|
@ -157,14 +158,29 @@ void Recorder::add_frame()
|
|||
video_stashes.back().flipped.push_back(get_root()->is_gl_context);
|
||||
if (video_stashes.back().pixel_buffers.size() * get_frame_length() > max_length)
|
||||
{
|
||||
std::function<void(std::vector<unsigned char*>*, std::vector<bool>*, int)> f =
|
||||
std::bind(&Recorder::write_stash_frames, this,
|
||||
std::placeholders::_1, std::placeholders::_2,
|
||||
std::placeholders::_3);
|
||||
std::thread writing(f, &video_stashes.back().pixel_buffers,
|
||||
&video_stashes.back().flipped,
|
||||
video_stashes.back().frame_offset);
|
||||
std::function<void(Stash*)> f =
|
||||
std::bind(&Recorder::write_stash_frames, this, std::placeholders::_1);
|
||||
std::thread writing(f, &video_stashes.back());
|
||||
writing.detach();
|
||||
// int frame_offset = video_stashes.back().frame_offset;
|
||||
// std::vector<unsigned char*> pixel_buffers = video_stashes.back().pixel_buffers;
|
||||
// std::vector<bool> flipped = video_stashes.back().flipped;
|
||||
// for (int ii = frame_offset; ii < pixel_buffers.size() + frame_offset; ii++)
|
||||
// {
|
||||
// SDL_Surface* frame = get_display().get_screen_surface_from_pixels(
|
||||
// pixel_buffers[ii - frame_offset], flipped[ii - frame_offset]);
|
||||
// std::stringstream name;
|
||||
// name << sfw::pad(ii, 5) << ".png";
|
||||
// fs::path path = current_video_directory / name.str();
|
||||
// SDL_Log("%s (%i, %i) (%i, %i, %i, %i)", path.c_str(), frame->w, frame->h,
|
||||
// ((unsigned char*) frame->pixels)[0], ((unsigned char*) frame->pixels)[1],
|
||||
// ((unsigned char*) frame->pixels)[2], ((unsigned char*) frame->pixels)[3]);
|
||||
// IMG_SavePNG(frame, path.string().c_str());
|
||||
// }
|
||||
// end_recording();
|
||||
// write_stash_frames(video_stashes.back().pixel_buffers,
|
||||
// video_stashes.back().flipped,
|
||||
// video_stashes.back().frame_offset);
|
||||
video_stashes.push_back(
|
||||
Stash(video_stashes.back().frame_offset +
|
||||
video_stashes.back().pixel_buffers.size()));
|
||||
|
@ -212,31 +228,27 @@ void Recorder::make_directory()
|
|||
current_video_directory = directory;
|
||||
}
|
||||
|
||||
void Recorder::write_stash_frames(
|
||||
std::vector<unsigned char*>* pixel_buffers, std::vector<bool>* flipped,
|
||||
int frame_offset)
|
||||
void Recorder::write_stash_frames(Stash* stash)
|
||||
{
|
||||
SDL_Log("Writing stash offset %i to %s...", frame_offset, current_video_directory.c_str());
|
||||
SDL_Log("Writing stash offset %i to %s...", stash->frame_offset, current_video_directory.c_str());
|
||||
SDL_Surface* frame;
|
||||
GifWriter gif_writer;
|
||||
int gif_frame_length = get_configuration()["recording"]["gif-frame-length"];
|
||||
fs::path gif_path = sfw::get_next_file_name(
|
||||
current_video_directory, 3, "gif-", ".gif");
|
||||
float elapsed = 0, last_gif_write = 0, gif_write_overflow = 0;
|
||||
SDL_Log("Pixel buffers size %zu", pixel_buffers->size());
|
||||
for (int ii = frame_offset; not pixel_buffers->empty(); ii++)
|
||||
for (int ii = stash->frame_offset; not stash->pixel_buffers.empty(); ii++)
|
||||
{
|
||||
frame = get_display().get_screen_surface_from_pixels(
|
||||
pixel_buffers->front(), flipped->front());
|
||||
get_root()->log_surface_format(frame, "got");
|
||||
stash->pixel_buffers.front(), stash->flipped.front());
|
||||
std::stringstream name;
|
||||
name << sfw::pad(ii, 5) << ".png";
|
||||
fs::path path = current_video_directory / name.str();
|
||||
IMG_SavePNG(frame, path.string().c_str());
|
||||
if (ii == frame_offset or
|
||||
if (ii == stash->frame_offset or
|
||||
elapsed - last_gif_write + gif_write_overflow >= gif_frame_length)
|
||||
{
|
||||
if (ii == frame_offset)
|
||||
if (ii == stash->frame_offset)
|
||||
{
|
||||
GifBegin(&gif_writer, gif_path.string().c_str(), frame->w,
|
||||
frame->h, gif_frame_length / 10);
|
||||
|
@ -252,9 +264,9 @@ void Recorder::write_stash_frames(
|
|||
frame->w, frame->h, gif_frame_length / 10);
|
||||
}
|
||||
elapsed += get_frame_length();
|
||||
delete[] pixel_buffers->front();
|
||||
pixel_buffers->erase(pixel_buffers->begin());
|
||||
flipped->erase(flipped->begin());
|
||||
delete[] stash->pixel_buffers.front();
|
||||
stash->pixel_buffers.erase(stash->pixel_buffers.begin());
|
||||
stash->flipped.erase(stash->flipped.begin());
|
||||
SDL_FreeSurface(frame);
|
||||
}
|
||||
GifEnd(&gif_writer);
|
||||
|
@ -291,9 +303,7 @@ void Recorder::end_recording()
|
|||
|
||||
void Recorder::finish_writing_video()
|
||||
{
|
||||
write_stash_frames(
|
||||
&video_stashes.back().pixel_buffers, &video_stashes.back().flipped,
|
||||
video_stashes.back().frame_offset);
|
||||
write_stash_frames(&video_stashes.back());
|
||||
int count;
|
||||
while (true)
|
||||
{
|
||||
|
@ -352,21 +362,24 @@ void Recorder::update()
|
|||
void process_audio(void* user_data, Uint8* stream, int len)
|
||||
{
|
||||
Recorder* recorder = static_cast<Recorder*>(user_data);
|
||||
int max_length = recorder->get_configuration()["recording"]["max-stash-length"];
|
||||
float length = recorder->get_frame_length() * recorder->current_stash.pixel_buffers.size();
|
||||
if (length > max_length)
|
||||
if (recorder->is_active())
|
||||
{
|
||||
delete[] recorder->current_stash.audio_buffers.front();
|
||||
recorder->current_stash.audio_buffers.erase(recorder->current_stash.audio_buffers.begin());
|
||||
recorder->current_stash.audio_buffer_lengths.erase(
|
||||
recorder->current_stash.audio_buffer_lengths.begin());
|
||||
}
|
||||
Uint8* stream_copy = new Uint8[len];
|
||||
std::memcpy(stream_copy, stream, len);
|
||||
recorder->current_stash.audio_buffers.push_back(stream_copy);
|
||||
recorder->current_stash.audio_buffer_lengths.push_back(len);
|
||||
if (recorder->is_recording)
|
||||
{
|
||||
recorder->write_audio(stream_copy, len);
|
||||
int max_length = recorder->get_configuration()["recording"]["max-stash-length"];
|
||||
float length = recorder->get_frame_length() * recorder->current_stash.pixel_buffers.size();
|
||||
if (length > max_length)
|
||||
{
|
||||
delete[] recorder->current_stash.audio_buffers.front();
|
||||
recorder->current_stash.audio_buffers.erase(recorder->current_stash.audio_buffers.begin());
|
||||
recorder->current_stash.audio_buffer_lengths.erase(
|
||||
recorder->current_stash.audio_buffer_lengths.begin());
|
||||
}
|
||||
Uint8* stream_copy = new Uint8[len];
|
||||
std::memcpy(stream_copy, stream, len);
|
||||
recorder->current_stash.audio_buffers.push_back(stream_copy);
|
||||
recorder->current_stash.audio_buffer_lengths.push_back(len);
|
||||
if (recorder->is_recording)
|
||||
{
|
||||
recorder->write_audio(stream_copy, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,8 +36,8 @@ struct Recorder : Node
|
|||
|
||||
Stash current_stash = Stash();
|
||||
Stash most_recent_stash;
|
||||
std::vector<Stash> in_game_stashes;
|
||||
std::vector<Stash> video_stashes;
|
||||
std::list<Stash> in_game_stashes;
|
||||
std::list<Stash> video_stashes;
|
||||
fs::path current_video_directory, current_audio_path;
|
||||
Animation animation = Animation(&Recorder::add_frame, this);
|
||||
bool is_recording = false, writing_recording = false, writing_most_recent = false;
|
||||
|
@ -54,8 +54,7 @@ struct Recorder : Node
|
|||
void add_frame();
|
||||
int get_memory_size();
|
||||
void make_directory();
|
||||
void write_stash_frames(
|
||||
std::vector<unsigned char*>*, std::vector<bool>*, int);
|
||||
void write_stash_frames(Stash*);
|
||||
void keep_stash();
|
||||
void end_recording();
|
||||
void finish_writing_video();
|
||||
|
|
Loading…
Reference in New Issue