171 lines
4.0 KiB
C++
171 lines
4.0 KiB
C++
#define SHARPSOFT_INTERNAL
|
|
|
|
#include <string.h>
|
|
#include <vector>
|
|
#include "sharpsoft/global_misc.hpp"
|
|
#include "sharpsoft/internal.hpp"
|
|
#include "sharpsoft/interop.hpp"
|
|
#include "sharpsoft/windowing.hpp"
|
|
|
|
using namespace sharp;
|
|
using std::vector;
|
|
|
|
const global_properties global_properties::defaults =
|
|
{
|
|
0x95d9ed,
|
|
20,
|
|
};
|
|
|
|
bool init = false;
|
|
bool started = false;
|
|
color back_col;
|
|
int render_wait_ms;
|
|
thread* render_thread = nullptr;
|
|
|
|
vector<window_base*> windows;
|
|
|
|
void sharp::initialize()
|
|
{
|
|
sharp::initialize(global_properties::defaults);
|
|
}
|
|
void sharp::initialize(const global_properties& props)
|
|
{
|
|
if (init) return;
|
|
|
|
back_col = props.background_color;
|
|
render_wait_ms = 1000 / props.refresh_rate;
|
|
|
|
init = true;
|
|
}
|
|
|
|
void sharp::uninitialize()
|
|
{
|
|
if (!init) return;
|
|
if (started) sharp::end();
|
|
|
|
// Dispose of all windows.
|
|
for (int i = 0; i < windows.size(); i++)
|
|
{
|
|
delete windows.at(i);
|
|
}
|
|
windows.clear();
|
|
|
|
init = false;
|
|
}
|
|
|
|
void sharp::re_initialize()
|
|
{
|
|
bool restart = started;
|
|
if (!init) return;
|
|
uninitialize();
|
|
initialize();
|
|
if (restart) start();
|
|
}
|
|
void sharp::re_initialize(const global_properties& props)
|
|
{
|
|
bool restart = started;
|
|
if (!init) return;
|
|
uninitialize();
|
|
initialize();
|
|
if (restart) start();
|
|
}
|
|
|
|
bool sharp::is_initialized()
|
|
{
|
|
return init;
|
|
}
|
|
|
|
void sharp::internal::render_iter()
|
|
{
|
|
int window_count = windows.size();
|
|
|
|
// The way windows are ordered in the vector represents
|
|
// the rendering order. More recent pushes (so further
|
|
// down the list) have a higher order.
|
|
for (int i = 0; i < window_count; i++)
|
|
{
|
|
window_base* win = windows.at(i);
|
|
// First handle special stuff.
|
|
// TODO: if the window is null, display an error?
|
|
|
|
// Now tick the window if applicable.
|
|
if (win->win_features.continuous_tick) win->tick();
|
|
|
|
// Apply any possible invalidations.
|
|
if (win->win_features.continuous_paint)
|
|
{
|
|
OFF_INTERNAL_FLAG(win, WINDOW_CONTENT_VALIDATED);
|
|
}
|
|
|
|
// Now render anything that is invalidated.
|
|
// If the header is set to sync with the content validation, render it
|
|
// regardless of if it would otherwise.
|
|
if (!HAS_INTERNAL_FLAG(win, WINDOW_HEADER_VALIDATED) ||
|
|
(!HAS_INTERNAL_FLAG(win, WINDOW_CONTENT_VALIDATED) && win->win_features.update_header))
|
|
{
|
|
win->paint_header();
|
|
ON_INTERNAL_FLAG(win, WINDOW_HEADER_VALIDATED);
|
|
}
|
|
if (!HAS_INTERNAL_FLAG(win, WINDOW_CONTENT_VALIDATED))
|
|
{
|
|
win->paint_content_back();
|
|
win->paint();
|
|
ON_INTERNAL_FLAG(win, WINDOW_CONTENT_VALIDATED);
|
|
}
|
|
}
|
|
}
|
|
void sharp::internal::render_loop()
|
|
{
|
|
thread::delay(50); // Wait a sec for the screen to be ready.
|
|
while (true)
|
|
{
|
|
render_iter();
|
|
thread::delay(render_wait_ms);
|
|
}
|
|
}
|
|
|
|
void sharp::internal::add_window(window_base* win_ptr, size_t size)
|
|
{
|
|
// Make copy of window so it remains in scope.
|
|
// There must be a better way to do this, but I don't know it.
|
|
// If you don't do this, then if windows are created in a method,
|
|
// then when that scope is terminated, a null pointer is created.
|
|
// However, when a copy is made, from that point onward the original
|
|
// in the method no longer affects the copy.
|
|
|
|
// Maybe instead a reference could be added to the original pointer
|
|
// to prevent it going out of scope with shared_ptr? Don't know,
|
|
// never used it.
|
|
|
|
void* copy_raw = malloc(size);
|
|
memcpy(copy_raw, (void*)(win_ptr), size);
|
|
|
|
window_base* copy = (window_base*)copy_raw;
|
|
windows.push_back(copy);
|
|
ON_INTERNAL_FLAG(copy, WINDOW_ACTIVE);
|
|
}
|
|
|
|
void sharp::start()
|
|
{
|
|
if (!init || started) return;
|
|
|
|
render_thread = new thread(internal::render_loop);
|
|
render_thread->start();
|
|
|
|
started = true;
|
|
}
|
|
void sharp::end()
|
|
{
|
|
if (!init || !started) return;
|
|
|
|
render_thread->stop();
|
|
delete render_thread;
|
|
|
|
started = false;
|
|
}
|
|
|
|
bool sharp::is_started()
|
|
{
|
|
return started;
|
|
}
|