Basic painting and invalidation systems work.

This commit is contained in:
That_One_Nerd 2024-05-24 07:49:27 -04:00
parent 597b7c26e4
commit ced7886a10
8 changed files with 149 additions and 20 deletions

View File

@ -6,6 +6,7 @@ namespace sharp
{
enum window_flags : uint32_t
{
WINDOW_ACTIVE = 1,
CONTINUOUS_PAINT = 0x01,
CONTINUOUS_TICK = 0x02,
};
}

View File

@ -16,6 +16,7 @@ namespace sharp
static const global_properties defaults;
color background_color;
float refresh_rate;
};
void initialize();

View File

@ -1,8 +1,11 @@
#pragma once
#ifdef SHARPSOFT_INTERNAL
#include "basic_types.hpp"
#include "window_types.hpp"
#define HAS_WINDOW_FLAG(pwin, flag) ((pwin->flags & flag) > 0)
namespace sharp
{
namespace internal
@ -11,6 +14,9 @@ namespace sharp
void render_iter();
void render_loop();
void draw_global_rectangle(const color& color, const int_rect& rect);
void fill_global_rectangle(const color& color, const int_rect& rect);
}
}
#endif

View File

@ -1,5 +1,6 @@
#pragma once
#include <atomic>
#include <inttypes.h>
#include <string>
#include "sharpsoft/basic_types.hpp"
@ -9,32 +10,47 @@ namespace sharp
{
class window_base
{
#ifdef SHARPSOFT_INTERNAL
public:
#else
private:
#endif
uint16_t posX, posY;
uint16_t width, height;
std::string title;
window_flags flags;
bool active, visible;
bool header_validated;
bool content_validated;
void paint_header();
#ifndef SHARPSOFT_INTERNAL
protected:
#endif
window_base(const std::string& title, const int2& pos, const int2& size);
#ifdef SHARPSOFT_INTERNAL
public:
#endif
virtual void paint() = 0;
virtual void tick() = 0;
public:
bool get_flag(window_flags flag) const;
const int2 get_pos() const;
const int2 get_size() const;
const int_rect get_window_rect() const;
const std::string get_title() const;
const bool is_active() const;
bool is_active() const;
bool is_visible() const;
void set_flag(window_flags flag, bool value);
void set_pos(const int2& new_pos);
void set_size(const int2& new_size);
void set_window_rect(const int_rect& new_rect);
void set_title(const std::string& new_title);
void invalidate();
void show();
void hide();
};

View File

@ -9,13 +9,17 @@ class test_window : public sharp::window_base
protected:
void paint() override
{
printf("Printed: %d\n", test_variable);
printf("Paint called.\n");
}
void tick() override
{
printf("Tick called.\n");
}
public:
test_window() : window_base("Testing", sharp::int2(10, 10), sharp::int2(150, 100))
{
set_flag(sharp::CONTINUOUS_TICK, true);
}
int test_variable;

View File

@ -1,8 +1,8 @@
#include "pros/rtos.hpp"
#define SHARPSOFT_INTERNAL
#include <string.h>
#include <vector>
#include "sharpsoft/enums.hpp"
#include "sharpsoft/global_misc.hpp"
#include "sharpsoft/internal.hpp"
#include "sharpsoft/interop.hpp"
@ -12,12 +12,14 @@ using std::vector;
const global_properties global_properties::defaults =
{
0x95d9ed
0x95d9ed,
20,
};
bool init = false;
bool started = false;
color back_col;
int render_wait_ms;
thread* render_thread = nullptr;
vector<window_base*> windows;
@ -31,6 +33,7 @@ void sharp::initialize(const global_properties& props)
if (init) return;
back_col = props.background_color;
render_wait_ms = 1000 / props.refresh_rate;
init = true;
}
@ -70,18 +73,41 @@ bool sharp::is_initialized()
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.
// Now tick the window if applicable.
if (HAS_WINDOW_FLAG(win, CONTINUOUS_TICK)) win->tick();
// Apply any possible invalidations.
if (HAS_WINDOW_FLAG(win, CONTINUOUS_PAINT)) win->content_validated = false;
// Now render anything that is invalidated.
if (!win->content_validated)
{
win->paint();
win->content_validated = true;
}
if (!win->header_validated)
{
win->paint_header();
win->header_validated = true;
}
}
}
void sharp::internal::render_loop()
{
thread::delay(50); // Wait a sec for the screen to be ready.
while (true)
{
render_iter();
thread::delay(100); // TODO: should be something else.
thread::delay(render_wait_ms);
}
}
@ -92,6 +118,7 @@ void sharp::internal::add_window(window_base* win_ptr, size_t size)
window_base* copy = (window_base*)copy_raw;
windows.push_back(copy);
copy->active = true;
}
void sharp::start()

View File

@ -0,0 +1,31 @@
#define SHARPSOFT_INTERNAL
#include "sharpsoft/internal.hpp"
#include "sharpsoft/macros.hpp"
#include "sharpsoft/window_types.hpp"
#ifdef SH_PROS_ACTIVE
#include "pros/screen.hpp"
#endif
using namespace sharp;
#ifdef SH_PROS_ACTIVE
void internal::draw_global_rectangle(const color& color, const int_rect& rect)
{
pros::screen::set_pen(color.get_value());
pros::screen::draw_rect(rect.left, rect.top, rect.left + rect.width - 1, rect.top + rect.height - 1);
}
void internal::fill_global_rectangle(const color& color, const int_rect& rect)
{
pros::screen::set_pen(color.get_value());
pros::screen::fill_rect(rect.left, rect.top, rect.left + rect.width - 1, rect.top + rect.height - 1);
}
#endif
void window_base::paint_header()
{
// Draw outline.
const color outline_color = color(255, 255, 255);
internal::draw_global_rectangle(outline_color, int_rect(posX - 1, posY - 1, width + 1, height + 1));
}

View File

@ -10,10 +10,19 @@ sharp::window_base::window_base(const string& title, const int2& pos, const int2
posX = pos.x;
posY = pos.y;
width = size.x;
width = size.y;
height = size.y;
flags = (window_flags)0;
active = false;
visible = true;
header_validated = false;
content_validated = false;
}
bool sharp::window_base::get_flag(window_flags flag) const
{
return (flags & flag) > 0;
}
const int2 sharp::window_base::get_pos() const
{
return int2(posX, posY);
@ -30,45 +39,79 @@ const string sharp::window_base::get_title() const
{
return title;
}
const bool sharp::window_base::is_active() const
bool sharp::window_base::is_active() const
{
return (flags & WINDOW_ACTIVE) > 0;
return active;
}
bool sharp::window_base::is_visible() const
{
return visible;
}
void sharp::window_base::set_flag(window_flags flag, bool value)
{
switch (flag)
{
case CONTINUOUS_PAINT:
case CONTINUOUS_TICK:
break; // No invalidation.
}
if (value) flags = (window_flags)(flags | flag);
else flags = (window_flags)(flags & ~flag);
}
void sharp::window_base::set_pos(const int2& new_pos)
{
// TODO: I'll have to re-render some parts.
// TODO: This will affect windows below it.
posX = new_pos.x;
posY = new_pos.y;
header_validated = false;
content_validated = false;
}
void sharp::window_base::set_size(const int2& new_pos)
{
// TODO: I'll have to re-render some parts.
// TODO: This will affect windows below it.
width = new_pos.x;
height = new_pos.y;
header_validated = false;
content_validated = false;
}
void sharp::window_base::set_window_rect(const int_rect& new_rect)
{
// TODO: I'll have to re-render some parts.
// TODO: This will affect windows below it.
posX = new_rect.left;
posY = new_rect.top;
width = new_rect.width;
height = new_rect.height;
header_validated = false;
content_validated = false;
}
void sharp::window_base::set_title(const std::string& new_title)
{
title = new_title;
header_validated = false;
}
void sharp::window_base::invalidate()
{
header_validated = false;
content_validated = false;
}
void sharp::window_base::hide()
{
// TODO: This will affect the renderer
flags = (window_flags)(flags & ~WINDOW_ACTIVE);
visible = false;
}
void sharp::window_base::show()
{
// TODO: This will affect the renderer
flags = (window_flags)(flags | WINDOW_ACTIVE);
visible = true;
header_validated = false;
content_validated = false;
}