simplegui/Simulator/src/simulator_window.cpp
2023-03-24 17:39:15 +08:00

259 lines
7.1 KiB
C++

#include "simulator.h"
#include "console_log.h"
#define ZOOM_SCALE (2)
simulator_touch_state::simulator_touch_state(void)
: m_pos_x(0)
, m_pos_y(0)
, m_pressed(false)
{
}
simulator_touch_state::~simulator_touch_state(void)
{
}
simulator_key_state::simulator_key_state(void)
: m_keycode(SDL_SCANCODE_UNKNOWN)
, m_pressed(false)
{
}
simulator_key_state::~simulator_key_state(void)
{
}
simulator_window::simulator_window(int width, int height, simulator_key_event_queue& key_event_queue)
: m_width(width)
, m_height(height)
, m_window_handle(nullptr)
, m_texture(nullptr)
, m_renderer(nullptr)
, m_exit(false)
, m_initialized(false)
, m_key_event_queue(key_event_queue)
{
DBG_LOG("Window created.");
memset(&m_event, 0x00, sizeof(SDL_Event));
}
simulator_window::~simulator_window(void)
{
deinit();
}
bool simulator_window::init(void)
{
// Use SDL2 screen with 24-bit RGB-888 format color.
// Confirm paint buffer create done and continue.
// Create and initialize SDL instance.
do
{
// Allocate simulator texture paint buffer.
size_t paint_buffer_size = m_width * m_height * SIMULATOR_COLOR_BYTES;
m_paint_buffer = new uint8_t[paint_buffer_size];
if(nullptr == m_paint_buffer)
{
ERR_LOG("Allocate paint buffer failed.");
break;
}
m_window_handle = SDL_CreateWindow("Simulator", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_width * ZOOM_SCALE, m_height * ZOOM_SCALE, SDL_WINDOW_OPENGL);
if(nullptr == m_window_handle)
{
ERR_LOG("SDL create window failed: %s\n", SDL_GetError());
break;
}
m_renderer = SDL_CreateRenderer(m_window_handle, 0, SDL_RENDERER_SOFTWARE);
if(nullptr == m_renderer)
{
ERR_LOG("SDL create renderer failed: %s\n", SDL_GetError());
break;
}
m_texture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGB24, // NOTE: Use 24-bit RGB-888 format color.
SDL_TEXTUREACCESS_TARGET, m_width, m_height);
if(nullptr == m_texture)
{
ERR_LOG("create texture failed: %s\n", SDL_GetError());
break;
}
// Initialize texture for background.
SDL_SetTextureBlendMode(m_texture, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(m_renderer, 0x00, 0x00, 0x00, 0x00);
SDL_RenderClear(m_renderer);
SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
SDL_RenderPresent(m_renderer);
// SDL instance initialize done.
m_initialized = true;
}
while(false);
return m_initialized;
}
void simulator_window::deinit(void)
{
if(m_initialized)
{
if(nullptr != m_window_handle)
{
SDL_DestroyWindow(m_window_handle);
m_window_handle = nullptr;
}
if(nullptr != m_renderer)
{
SDL_DestroyRenderer(m_renderer);
m_renderer = nullptr;
}
if(nullptr != m_texture)
{
SDL_DestroyTexture(m_texture);
m_texture = nullptr;
}
m_initialized = false;
}
}
bool simulator_window::prolog(void)
{
bool has_event = true;
if(m_initialized)
{
if(SDL_PollEvent(&m_event))
{
switch(m_event.type)
{
case SDL_QUIT:
{
m_exit = true;
break;
}
case SDL_MOUSEBUTTONDOWN:
{
m_touch_state.m_pos_x = m_event.motion.x;
m_touch_state.m_pos_y = m_event.motion.y;
m_touch_state.m_pressed = true;
break;
}
case SDL_MOUSEMOTION:
{
m_touch_state.m_pos_x = m_event.motion.x;
m_touch_state.m_pos_y = m_event.motion.y;
break;
}
case SDL_MOUSEBUTTONUP:
{
m_touch_state.m_pos_x = m_event.motion.x;
m_touch_state.m_pos_y = m_event.motion.y;
m_touch_state.m_pressed = false;
break;
}
case SDL_KEYDOWN:
{
m_key_event_queue.emplace(m_event.key.keysym.scancode, sim_key_press);
if(SDL_SCANCODE_P == m_event.key.keysym.scancode)
{
snapshot();
}
break;
}
case SDL_KEYUP:
{
m_key_event_queue.emplace(m_event.key.keysym.scancode, sim_key_release);
break;
}
default:
{
// INF_LOG("No event process for 0x%04X.", event.type);
/* do nothing. */
has_event = false;
}
}
}
}
return has_event;
}
void simulator_window::paint_pixel(int pos_x, int pos_y, uint8_t red, uint8_t green, uint8_t blue)
{
if(m_paint_buffer)
{
m_paint_buffer[(pos_y * m_width + pos_x) * SIMULATOR_COLOR_BYTES + 0] = red;
m_paint_buffer[(pos_y * m_width + pos_x) * SIMULATOR_COLOR_BYTES + 1] = green;
m_paint_buffer[(pos_y * m_width + pos_x) * SIMULATOR_COLOR_BYTES + 2] = blue;
}
}
void simulator_window::paint_pixel(int pos_x, int pos_y, uint32_t color_hex)
{
if(m_paint_buffer)
{
m_paint_buffer[(pos_y * m_width + pos_x) * SIMULATOR_COLOR_BYTES + 0] = (color_hex >> 16) & 0xFF;
m_paint_buffer[(pos_y * m_width + pos_x) * SIMULATOR_COLOR_BYTES + 1] = (color_hex >> 8) & 0xFF;
m_paint_buffer[(pos_y * m_width + pos_x) * SIMULATOR_COLOR_BYTES + 2] = color_hex & 0xFF;
}
}
void simulator_window::clear_paint(void)
{
::memset(m_paint_buffer, 0x00, sizeof(uint8_t)*(m_width * m_height * SIMULATOR_COLOR_BYTES));
}
void simulator_window::sync_paint_buffer(void)
{
/* Sync paint buffer content to screens. */
SDL_UpdateTexture(m_texture, NULL, m_paint_buffer, m_width * SIMULATOR_COLOR_BYTES);
SDL_RenderClear(m_renderer);
SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
SDL_RenderPresent(m_renderer);
}
bool simulator_window::exit(void)
{
return m_exit;
}
int simulator_window::width(void) const
{
return m_width;
}
int simulator_window::height(void) const
{
return m_height;
}
int simulator_window::get_touch_pos_x(void) const
{
return m_touch_state.m_pos_x;
}
int simulator_window::get_touch_pos_y(void) const
{
return m_touch_state.m_pos_y;
}
bool simulator_window::get_touch_pressed(void) const
{
return m_touch_state.m_pressed;
}
simulator_key_event_queue& simulator_window::key_event(void)
{
return m_key_event_queue;
}
void simulator_window::snapshot(void)
{
SDL_Surface *sshot = SDL_CreateRGBSurface(0, m_width*ZOOM_SCALE, m_height*ZOOM_SCALE, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
SDL_RenderReadPixels(m_renderer, NULL, SDL_PIXELFORMAT_ARGB8888, sshot->pixels, sshot->pitch);
SDL_SaveBMP(sshot, "screenshot.bmp");
SDL_FreeSurface(sshot);
}