mirror of
https://gitee.com/Polarix/simplegui.git
synced 2025-06-17 05:27:52 +00:00
259 lines
7.1 KiB
C++
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);
|
||
|
}
|