Good progress. Header and content rects work.

This commit is contained in:
That-One-Nerd 2024-08-02 10:07:39 -04:00
parent 3aa8a4af8b
commit e0b31c0238
9 changed files with 181 additions and 67 deletions

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <inttypes.h> #include <cstdint>
namespace sharp namespace sharp
{ {
@ -50,5 +50,22 @@ namespace sharp
int_rect(); int_rect();
int_rect(int left, int top, int width, int height); int_rect(int left, int top, int width, int height);
int_rect(const int2 pos, const int2 size); int_rect(const int2 pos, const int2 size);
const int2 tl() const; // Top left
const int2 tr() const; // Top right
const int2 bl() const; // Bottom left
const int2 br() const; // Bottom right
bool contains(const int2& point) const;
bool contains(const int_rect& rect) const; // Fully contains other rect.
bool intersects(const int_rect& rect) const; // Partially contains other rect.
};
enum size
{
SMALL = -1,
NORMAL = 0,
LARGE = 1
}; };
} }

View File

@ -4,7 +4,6 @@
#include "basic_types.hpp" #include "basic_types.hpp"
#include "windowing.hpp" #include "windowing.hpp"
#define HAS_WINDOW_FLAG(pwin, flag) ((pwin->flags & flag) > 0)
#define HAS_INTERNAL_FLAG(pwin, flag) ((pwin->int_flags & flag) > 0) #define HAS_INTERNAL_FLAG(pwin, flag) ((pwin->int_flags & flag) > 0)
#define ON_INTERNAL_FLAG(pwin, flag) pwin->int_flags = (window_internal_flags)(pwin->int_flags | flag) #define ON_INTERNAL_FLAG(pwin, flag) pwin->int_flags = (window_internal_flags)(pwin->int_flags | flag)
#define OFF_INTERNAL_FLAG(pwin, flag) pwin->int_flags = (window_internal_flags)(pwin->int_flags & ~flag) #define OFF_INTERNAL_FLAG(pwin, flag) pwin->int_flags = (window_internal_flags)(pwin->int_flags & ~flag)
@ -18,6 +17,7 @@ namespace sharp
void render_iter(); void render_iter();
void render_loop(); void render_loop();
void draw_global_line(const color& color, const int2& start, const int2& end);
void draw_global_rectangle(const color& color, const int_rect& rect); void draw_global_rectangle(const color& color, const int_rect& rect);
void fill_global_rectangle(const color& color, const int_rect& rect); void fill_global_rectangle(const color& color, const int_rect& rect);
} }

View File

@ -1,18 +1,10 @@
#pragma once #pragma once
#include <atomic>
#include <inttypes.h>
#include <string> #include <string>
#include "sharpsoft/basic_types.hpp" #include "sharpsoft/basic_types.hpp"
namespace sharp namespace sharp
{ {
enum window_flags : uint32_t
{
CONTINUOUS_PAINT = 0x01,
CONTINUOUS_TICK = 0x02,
HEADER_UPDATE = 0x04,
};
enum window_internal_flags : uint32_t enum window_internal_flags : uint32_t
{ {
WINDOW_ACTIVE = 0x01, WINDOW_ACTIVE = 0x01,
@ -21,12 +13,25 @@ namespace sharp
WINDOW_CONTENT_VALIDATED = 0x08 WINDOW_CONTENT_VALIDATED = 0x08
}; };
struct window_features
{
static const window_features defaults;
bool continuous_paint; // Re-validate the content every frame. Otherwise, only when content is invalidated.
bool continuous_tick; // Call tick every frame. Otherwise, never called.
bool update_header; // If set, update header along with content. Otherwise, only when header is invalidated.
bool show_header; // If not set, the header will not be rendered. The outline still will.
};
struct window_styles struct window_styles
{ {
static const window_styles defaults; static const window_styles defaults;
color background_color; color background_color;
color outline_color; color outline_color;
color header_color;
size header_size;
}; };
class window_base class window_base
@ -39,8 +44,9 @@ namespace sharp
uint16_t posX, posY; uint16_t posX, posY;
uint16_t width, height; uint16_t width, height;
std::string title; std::string title;
window_flags flags;
window_internal_flags int_flags; window_internal_flags int_flags;
window_features win_features;
window_styles styles; window_styles styles;
void paint_header() const; void paint_header() const;
@ -50,6 +56,7 @@ namespace sharp
protected: protected:
#endif #endif
window_base(const std::string& title, const int2& pos, const int2& size); window_base(const std::string& title, const int2& pos, const int2& size);
virtual ~window_base();
virtual void paint() = 0; virtual void paint() = 0;
virtual void tick() = 0; virtual void tick() = 0;
@ -58,15 +65,19 @@ namespace sharp
const window_styles& style() const; const window_styles& style() const;
window_styles& style(); window_styles& style();
bool get_flag(window_flags flag) const; const window_features& features() const;
window_features& features();
const int2 get_pos() const; const int2 get_pos() const;
const int2 get_size() const; const int2 get_size() const;
const int_rect get_content_rect() const;
const int_rect get_header_rect() const;
int get_header_height() const;
const int_rect get_window_rect() const; const int_rect get_window_rect() const;
const std::string get_title() const; const std::string get_title() const;
bool is_active() const; bool is_active() const;
bool is_visible() const; bool is_visible() const;
void set_flag(window_flags flag, bool value);
void set_pos(const int2& new_pos); void set_pos(const int2& new_pos);
void set_size(const int2& new_size); void set_size(const int2& new_size);
void set_window_rect(const int_rect& new_rect); void set_window_rect(const int_rect& new_rect);
@ -78,5 +89,5 @@ namespace sharp
void hide(); void hide();
}; };
bool windows_intersect(const window_base& winA, const window_base& winB); int get_header_height(size size);
} }

View File

@ -1,5 +1,7 @@
#include "main.h" #include "main.h"
#include "sharpsoft/all.hpp" #include "sharpsoft/all.hpp"
#include "sharpsoft/basic_types.hpp"
#include "sharpsoft/windowing.hpp"
// This library is intended to be referenced by the prefix `sharp::` // This library is intended to be referenced by the prefix `sharp::`
// Including `using namespace sharp;` is not recommended. // Including `using namespace sharp;` is not recommended.
@ -9,14 +11,7 @@ class test_window : public sharp::window_base
protected: protected:
void paint() override void paint() override
{ {
static int frame = 0;
frame++;
style() =
{
sharp::color(frame % 256, 0, 0),
sharp::color(0, 0, frame % 256)
};
} }
void tick() override void tick() override
{ {
@ -26,9 +21,9 @@ protected:
public: public:
test_window() : window_base("Testing", sharp::int2(10, 10), sharp::int2(150, 100)) test_window() : window_base("Testing", sharp::int2(10, 10), sharp::int2(150, 100))
{ {
set_flag(sharp::CONTINUOUS_PAINT, true); features().continuous_paint = true;
set_flag(sharp::CONTINUOUS_TICK, false); features().continuous_tick = false;
set_flag(sharp::HEADER_UPDATE, true); features().update_header = true;
} }
}; };

View File

@ -108,3 +108,38 @@ sharp::int_rect::int_rect(const int2 pos, const int2 size)
width = size.x; width = size.x;
height = size.y; height = size.y;
} }
const int2 sharp::int_rect::tl() const
{
return int2(top, left);
}
const int2 sharp::int_rect::tr() const
{
return int2(top, left + width);
}
const int2 sharp::int_rect::bl() const
{
return int2(top + height, left);
}
const int2 sharp::int_rect::br() const
{
return int2(top + height, left + width);
}
bool sharp::int_rect::contains(const int2& point) const
{
return point.x >= left && point.x <= left + width &&
point.y >= top && point.y <= top + height;
}
bool sharp::int_rect::contains(const int_rect& rect) const
{
return contains(rect.tl()) && contains(rect.tr());
}
bool sharp::int_rect::intersects(const int_rect& rect) const
{
// Top row is if this rect contains point of other rect.
// Bottom row is if other rect contains point of this rect.
return contains(rect.tl()) || contains(rect.tr()) || contains(rect.bl()) || contains(rect.br()) ||
rect.contains(tl()) || rect.contains(tr()) || rect.contains(bl()) || rect.contains(br());
}

View File

@ -43,7 +43,12 @@ void sharp::uninitialize()
if (!init) return; if (!init) return;
if (started) sharp::end(); if (started) sharp::end();
// TODO // Dispose of all windows.
for (int i = 0; i < windows.size(); i++)
{
delete windows.at(i);
}
windows.clear();
init = false; init = false;
} }
@ -81,12 +86,13 @@ void sharp::internal::render_iter()
{ {
window_base* win = windows.at(i); window_base* win = windows.at(i);
// First handle special stuff. // First handle special stuff.
// TODO: if the window is null, display an error?
// Now tick the window if applicable. // Now tick the window if applicable.
if (HAS_WINDOW_FLAG(win, CONTINUOUS_TICK)) win->tick(); if (win->win_features.continuous_tick) win->tick();
// Apply any possible invalidations. // Apply any possible invalidations.
if (HAS_WINDOW_FLAG(win, CONTINUOUS_PAINT)) if (win->win_features.continuous_paint)
{ {
OFF_INTERNAL_FLAG(win, WINDOW_CONTENT_VALIDATED); OFF_INTERNAL_FLAG(win, WINDOW_CONTENT_VALIDATED);
} }
@ -95,7 +101,7 @@ void sharp::internal::render_iter()
// If the header is set to sync with the content validation, render it // If the header is set to sync with the content validation, render it
// regardless of if it would otherwise. // regardless of if it would otherwise.
if (!HAS_INTERNAL_FLAG(win, WINDOW_HEADER_VALIDATED) || if (!HAS_INTERNAL_FLAG(win, WINDOW_HEADER_VALIDATED) ||
(!HAS_INTERNAL_FLAG(win, WINDOW_CONTENT_VALIDATED) && HAS_WINDOW_FLAG(win, HEADER_UPDATE))) (!HAS_INTERNAL_FLAG(win, WINDOW_CONTENT_VALIDATED) && win->win_features.update_header))
{ {
win->paint_header(); win->paint_header();
ON_INTERNAL_FLAG(win, WINDOW_HEADER_VALIDATED); ON_INTERNAL_FLAG(win, WINDOW_HEADER_VALIDATED);
@ -120,6 +126,17 @@ void sharp::internal::render_loop()
void sharp::internal::add_window(window_base* win_ptr, size_t size) 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); void* copy_raw = malloc(size);
memcpy(copy_raw, (void*)(win_ptr), size); memcpy(copy_raw, (void*)(win_ptr), size);

View File

@ -1,31 +1,32 @@
#define SHARPSOFT_INTERNAL #define SHARPSOFT_INTERNAL
#include "sharpsoft/internal.hpp"
#include "sharpsoft/windowing.hpp" #include "sharpsoft/windowing.hpp"
using namespace sharp; using namespace sharp;
const sharp::window_features sharp::window_features::defaults =
{
false,
true,
false,
true
};
const sharp::window_styles sharp::window_styles::defaults = const sharp::window_styles sharp::window_styles::defaults =
{ {
color(0, 0, 0), 0x000000,
color(255, 255, 255) 0xffffff,
0x42b7ff,
NORMAL
}; };
bool sharp::windows_intersect(const window_base& winA, const window_base& winB) int sharp::get_header_height(size size)
{ {
// TODO: When I finish the header this'll change. switch (size)
int winAMinX = winA.posX - 1, winAMaxX = winA.posX + winA.width + 2, {
winAMinY = winA.posY - 1, winAMaxY = winA.posY + winA.height + 2, case SMALL: return 16;
winBMinX = winB.posX - 1, winBMaxX = winB.posX + winB.width + 2, case NORMAL: return 24;
winBMinY = winB.posY - 1, winBMaxY = winB.posY + winB.height + 2; case LARGE: return 32;
// Killer IF statement but it works. default: return -1; // Unknown.
return (winAMinX >= winBMinX && winAMinX <= winBMaxX) || // winAMinX within winB }
(winAMinY >= winBMinY && winAMinY <= winBMaxY) || // winAMinY within winB
(winAMaxX >= winBMinX && winAMaxX <= winBMaxX) || // winAMaxX within winB
(winAMaxY >= winBMinY && winAMaxY <= winBMaxY) || // winAMaxY within winB
(winBMinX >= winAMinX && winBMinX <= winAMaxX) || // winBMinX within winA
(winBMinY >= winAMinY && winBMinY <= winAMaxY) || // winBMinY within winA
(winBMaxX >= winAMinX && winBMaxX <= winAMaxX) || // winBMaxX within winA
(winBMaxY >= winAMinY && winBMaxY <= winAMaxY);
} }

View File

@ -11,6 +11,11 @@
using namespace sharp; using namespace sharp;
#ifdef SH_PROS_ACTIVE #ifdef SH_PROS_ACTIVE
void internal::draw_global_line(const color &color, const int2 &start, const int2 &end)
{
pros::screen::set_pen(color.get_value());
pros::screen::draw_line(start.x, start.y, end.x, end.y);
}
void internal::draw_global_rectangle(const color& color, const int_rect& rect) void internal::draw_global_rectangle(const color& color, const int_rect& rect)
{ {
pros::screen::set_pen(color.get_value()); pros::screen::set_pen(color.get_value());
@ -25,11 +30,29 @@ void internal::fill_global_rectangle(const color& color, const int_rect& rect)
void window_base::paint_header() const void window_base::paint_header() const
{ {
// Draw outline. internal::draw_global_rectangle(styles.outline_color, get_window_rect());
internal::draw_global_rectangle(styles.outline_color, int_rect(posX - 1, posY - 1, width + 2, height + 2));
int header_height = get_header_height();
if (header_height > 0)
{
// Draw line between header and content.
internal::draw_global_line(
styles.outline_color,
int2(
posX,
posY + header_height
),
int2(
posX + width,
posY + header_height
)
);
// Draw header.
internal::fill_global_rectangle(styles.header_color, get_header_rect());
}
} }
void window_base::paint_content_back() const void window_base::paint_content_back() const
{ {
// Draw background. internal::fill_global_rectangle(styles.background_color, get_content_rect());
internal::fill_global_rectangle(styles.background_color, int_rect(posX, posY, width, height));
} }

View File

@ -13,10 +13,16 @@ sharp::window_base::window_base(const string& title, const int2& pos, const int2
posY = pos.y; posY = pos.y;
width = size.x; width = size.x;
height = size.y; height = size.y;
flags = (window_flags)(CONTINUOUS_TICK);
int_flags = (window_internal_flags)WINDOW_VISIBLE; int_flags = (window_internal_flags)WINDOW_VISIBLE;
win_features = window_features::defaults;
styles = window_styles::defaults; styles = window_styles::defaults;
} }
sharp::window_base::~window_base()
{
// Dispose of window.
title.~basic_string();
}
const window_styles& sharp::window_base::style() const const window_styles& sharp::window_base::style() const
{ {
@ -26,9 +32,13 @@ window_styles& sharp::window_base::style()
{ {
return styles; return styles;
} }
bool sharp::window_base::get_flag(window_flags flag) const const window_features& sharp::window_base::features() const
{ {
return (flags & flag) > 0; return win_features;
}
window_features& sharp::window_base::features()
{
return win_features;
} }
const int2 sharp::window_base::get_pos() const const int2 sharp::window_base::get_pos() const
{ {
@ -38,9 +48,26 @@ const int2 sharp::window_base::get_size() const
{ {
return int2(width, height); return int2(width, height);
} }
const int_rect sharp::window_base::get_content_rect() const
{
int header_height = get_header_height();
if (header_height > 0) return int_rect(posX, posY + header_height + 1, width, height);
else return int_rect(posX, posY, width, height);
}
const int_rect sharp::window_base::get_header_rect() const
{
return int_rect(posX, posY, width, get_header_height());
}
int sharp::window_base::get_header_height() const
{
if (win_features.show_header) return sharp::get_header_height(styles.header_size);
else return 0;
}
const int_rect sharp::window_base::get_window_rect() const const int_rect sharp::window_base::get_window_rect() const
{ {
return int_rect(posX, posY, width, height); int header_height = get_header_height();
if (header_height > 0) return int_rect(posX - 1, posY - 1, width + 2, height + header_height + 3);
else return int_rect(posX - 1, posY - 1, width + 2, height + 2);
} }
const string sharp::window_base::get_title() const const string sharp::window_base::get_title() const
{ {
@ -55,18 +82,6 @@ bool sharp::window_base::is_visible() const
return HAS_INTERNAL_FLAG(this, WINDOW_VISIBLE); return HAS_INTERNAL_FLAG(this, WINDOW_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) void sharp::window_base::set_pos(const int2& new_pos)
{ {
// TODO: This will affect windows below it. // TODO: This will affect windows below it.