Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Brad Svercl 2021-02-11 13:13:14 -06:00
commit cb53f07263
16 changed files with 139 additions and 90 deletions

View File

@ -5,14 +5,20 @@ namespace Blah
{
struct Time
{
// uptime, in milliseconds
static uint64_t milliseconds;
// ticks per second (microseconds, in this case)
static constexpr uint64_t ticks_per_second = 1000000;
// uptime, in ticks
static uint64_t ticks;
// uptime, in seconds
static float elapsed;
static double seconds;
// previous frame uptime, in ticks
static uint64_t previous_ticks;
// previous frame uptime, in seconds
static float previous_elapsed;
static double previous_seconds;
// delta time from last frame
static float delta;
@ -21,10 +27,10 @@ namespace Blah
static float pause_timer;
// pauses the entire application for the given time
static void pause_for(float time);
static void pause_for(float duration);
// returns true on the given time interval
static bool on_interval(float time, float delta, float interval, float offset);
static bool on_interval(double time, float delta, float interval, float offset);
// returns true on the given time interval
static bool on_interval(float delta, float interval, float offset);
@ -33,10 +39,10 @@ namespace Blah
static bool on_interval(float interval, float offset = 0);
// returns true when the given timestamp is passed
static bool on_time(float time, float timestamp);
static bool on_time(double time, double timestamp);
// returns true between time intervals
static bool between_interval(float time, float interval, float offset);
static bool between_interval(double time, float interval, float offset);
// returns true between time intervals
static bool between_interval(float interval, float offset = 0);

View File

@ -61,9 +61,9 @@ namespace Blah
int m_last_value_i = 0;
bool m_pressed = false;
bool m_released = false;
float m_last_press_time = -1;
float m_last_release_time = -1;
float m_repeat_press_time = -1;
double m_last_press_time = -1;
double m_last_release_time = -1;
double m_repeat_press_time = -1;
public:
VirtualAxis& add_keys(Key negative, Key positive);

View File

@ -61,9 +61,9 @@ namespace Blah
bool m_down = false;
bool m_pressed = false;
bool m_released = false;
float m_last_press_time = -1;
float m_last_release_time = -1;
float m_repeat_press_time = -1;
double m_last_press_time = -1;
double m_last_release_time = -1;
double m_repeat_press_time = -1;
public:
VirtualButton& add_key(Key key);

View File

@ -70,9 +70,9 @@ namespace Blah
bool m_released = false;
float m_i_deadzone;
float m_last_press_time = -1;
float m_last_release_time = -1;
float m_repeat_press_time = -1;
double m_last_press_time = -1;
double m_last_release_time = -1;
double m_repeat_press_time = -1;
public:
VirtualStick();

View File

@ -1,5 +1,6 @@
#pragma once
#include <inttypes.h>
#include <blah/containers/str.h>
namespace Blah
{
@ -17,6 +18,7 @@ namespace Blah
Color(int rgb, float alpha);
Color(uint8_t r, uint8_t g, uint8_t b);
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
Color(const Vec4& vec4);
// Parses a Hex string in the format of "#00000000" or "0x00000000" or "00000000"
Color(const char* hexCstr);
@ -28,12 +30,20 @@ namespace Blah
// The buffer must be at least 8 bytes long
void to_hex_rgba(char* buffer) const;
// Returns an RGBA hex string of the color
String to_hex_rgba() const;
// Sets a Hex string to the given buffer, in the format of RRGGBB
// The buffer must be at least 6 bytes long
void to_hex_rgb(char* buffer) const;
// Returns an RGB hex string of the color
String to_hex_rgb() const;
// Convers the Color to a uint32_t
uint32_t to_rgba() const;
// Converts the Color to a Vec4
Vec4 to_vec4() const;
// Returns a RGBA Color representation of the integer value
@ -42,6 +52,7 @@ namespace Blah
// Returns a RGB Color representation of the integer value, with Alpha = 255
static Color from_rgb(uint32_t value);
// Lerps between two colors
static Color lerp(Color a, Color b, float amount);
// Mutliplties the Color
@ -49,7 +60,11 @@ namespace Blah
// assignment from int
Color& operator= (const int rgb);
// comparisons
bool operator ==(const Color& rhs) const;
bool operator !=(const Color& rhs) const;
static const Color transparent;
static const Color white;
static const Color black;

View File

@ -6,13 +6,6 @@
using namespace Blah;
const uint16_t UTF8_LEAD_SURROGATE_MIN = 0xd800u;
const uint16_t UTF8_LEAD_SURROGATE_MAX = 0xdbffu;
const uint16_t UTF8_TRAIL_SURROGATE_MIN = 0xdc00u;
const uint16_t UTF8_TRAIL_SURROGATE_MAX = 0xdfffu;
const uint16_t UTF8_LEAD_OFFSET = UTF8_LEAD_SURROGATE_MIN - (0x10000 >> 10);
const uint32_t UTF8_SURROGATE_OFFSET = 0x10000u - (UTF8_LEAD_SURROGATE_MIN << 10) - UTF8_TRAIL_SURROGATE_MIN;
char Str::empty_buffer[1] = { '\0' };
bool Str::operator==(const Str& rhs) const
@ -217,24 +210,30 @@ Str& Str::append_fmt(const char* fmt, ...)
return *this;
}
Str& Str::append_utf16(const uint16_t* start, const uint16_t* end, bool swapEndian)
Str& Str::append_utf16(const uint16_t* start, const uint16_t* end, bool swap_endian)
{
// converts utf16 into utf8
// more info: https://en.wikipedia.org/wiki/UTF-16#Description
const uint16_t surrogate_min = 0xd800u;
const uint16_t surrogate_max = 0xdbffu;
while (start != end)
{
uint16_t next = (*start++);
if (swapEndian)
if (swap_endian)
next = ((next & 0xff) << 8 | ((next & 0xff00) >> 8));
uint32_t cp = 0xffff & next;
if ((cp >= UTF8_LEAD_SURROGATE_MIN && cp <= UTF8_LEAD_SURROGATE_MAX))
if ((cp >= surrogate_min && cp <= surrogate_max))
{
next = (*start++);
if (swapEndian)
if (swap_endian)
next = ((next & 0xff) << 8 | ((next & 0xff00) >> 8));
uint32_t trail = 0xffff & next;
cp = (cp << 10) + trail + UTF8_SURROGATE_OFFSET;
cp = (cp << 10) + trail + 0x10000u - (surrogate_min << 10) - 0xdc00u;
}
append(cp);

View File

@ -48,8 +48,8 @@ namespace
// update at a fixed timerate
// TODO: allow a non-fixed step update?
{
uint64_t time_target = (uint64_t)((1.0f / app_config.target_framerate) * 1000);
uint64_t time_curr = PlatformBackend::time();
uint64_t time_target = (uint64_t)((1.0 / app_config.target_framerate) * Time::ticks_per_second);
uint64_t time_curr = PlatformBackend::ticks();
uint64_t time_diff = time_curr - time_last;
time_last = time_curr;
time_accumulator += time_diff;
@ -57,9 +57,10 @@ namespace
// do not let us run too fast
while (time_accumulator < time_target)
{
PlatformBackend::sleep((int)(time_target - time_accumulator));
int milliseconds = (int)(time_target - time_accumulator) / (Time::ticks_per_second / 1000);
PlatformBackend::sleep(milliseconds);
time_curr = PlatformBackend::time();
time_curr = PlatformBackend::ticks();
time_diff = time_curr - time_last;
time_last = time_curr;
time_accumulator += time_diff;
@ -81,15 +82,16 @@ namespace
if (Time::pause_timer > 0)
{
Time::pause_timer -= Time::delta;
if (Time::pause_timer <= -0.0001f)
if (Time::pause_timer <= -0.0001)
Time::delta = -Time::pause_timer;
else
continue;
}
Time::milliseconds += time_target;
Time::previous_elapsed = Time::elapsed;
Time::elapsed += Time::delta;
Time::previous_ticks = Time::ticks;
Time::ticks += time_target;
Time::previous_seconds = Time::seconds;
Time::seconds += Time::delta;
InputBackend::frame();
GraphicsBackend::frame();
@ -147,7 +149,7 @@ bool App::run(const Config* c)
if (app_config.on_startup != nullptr)
app_config.on_startup();
time_last = PlatformBackend::time();
time_last = PlatformBackend::ticks();
time_accumulator = 0;
// display window
@ -173,8 +175,11 @@ bool App::run(const Config* c)
// clear static state
app_is_running = false;
app_is_exiting = false;
Time::milliseconds = 0;
Time::elapsed = 0;
Time::ticks = 0;
Time::seconds = 0;
Time::previous_ticks = 0;
Time::previous_seconds = 0;
Time::delta = 0;
return true;

View File

@ -5,50 +5,51 @@ using namespace Blah;
namespace
{
float modf(float x, float m)
double modf(double x, double m)
{
return x - (int)(x / m) * m;
}
}
uint64_t Time::milliseconds = 0;
float Time::elapsed = 0;
uint64_t Time::ticks = 0;
uint64_t Time::previous_ticks = 0;
double Time::seconds = 0;
double Time::previous_seconds = 0;
float Time::delta = 0;
float Time::previous_elapsed = 0;
float Time::pause_timer = 0;
void Time::pause_for(float time)
void Time::pause_for(float duration)
{
if (time >= pause_timer)
pause_timer = time;
if (duration >= pause_timer)
pause_timer = duration;
}
bool Time::on_interval(float time, float delta, float interval, float offset)
bool Time::on_interval(double time, float delta, float interval, float offset)
{
return floor((time - offset - delta) / interval) < floor((time - offset) / interval);
}
bool Time::on_interval(float delta, float interval, float offset)
{
return Time::on_interval(Time::elapsed, delta, interval, offset);
return Time::on_interval(Time::seconds, delta, interval, offset);
}
bool Time::on_interval(float interval, float offset)
{
return Time::on_interval(Time::elapsed, Time::delta, interval, offset);
return Time::on_interval(Time::seconds, Time::delta, interval, offset);
}
bool Time::on_time(float time, float timestamp)
bool Time::on_time(double time, double timestamp)
{
return time >= timestamp && time - Time::delta < timestamp;
}
bool Time::between_interval(float time, float interval, float offset)
bool Time::between_interval(double time, float interval, float offset)
{
return modf(time - offset, interval * 2) >= interval;
}
bool Time::between_interval(float interval, float offset)
{
return between_interval(Time::elapsed, interval, offset);
return between_interval(Time::seconds, interval, offset);
}

View File

@ -63,7 +63,7 @@ void Packer::add_entry(uint64_t id, int w, int h, const Color* pixels)
Entry entry(id, RectI(0, 0, w, h));
// trim
int top = 0, left = 0, right = w, bottom = h;
int top = 0, left = 0, right = 0, bottom = 0;
// TOP:
for (int y = 0; y < h; y++)

View File

@ -93,7 +93,7 @@ void InputBackend::on_mouse_down(MouseButton button)
{
g_next_state.mouse.down[i] = true;
g_next_state.mouse.pressed[i] = true;
g_next_state.mouse.timestamp[i] = Time::milliseconds;
g_next_state.mouse.timestamp[i] = Time::ticks;
}
}
@ -114,7 +114,7 @@ void InputBackend::on_key_down(Key key)
{
g_next_state.keyboard.down[i] = true;
g_next_state.keyboard.pressed[i] = true;
g_next_state.keyboard.timestamp[i] = Time::milliseconds;
g_next_state.keyboard.timestamp[i] = Time::ticks;
}
}
@ -170,7 +170,7 @@ void InputBackend::on_button_down(int index, int button)
{
g_next_state.controllers[index].down[button] = 1;
g_next_state.controllers[index].pressed[button] = 1;
g_next_state.controllers[index].button_timestamp[button] = Time::milliseconds;
g_next_state.controllers[index].button_timestamp[button] = Time::ticks;
}
}
@ -194,7 +194,7 @@ void InputBackend::on_axis_move(int index, int axis, float value)
axis < g_next_state.controllers[index].axis_count)
{
g_next_state.controllers[index].axis[axis] = value;
g_next_state.controllers[index].axis_timestamp[axis] = Time::milliseconds;
g_next_state.controllers[index].axis_timestamp[axis] = Time::ticks;
}
}

View File

@ -102,16 +102,16 @@ void VirtualAxis::update()
if (m_value_i != 0 && m_last_value_i != m_value_i)
{
m_pressed = true;
m_last_press_time = m_repeat_press_time = Time::elapsed;
m_last_press_time = m_repeat_press_time = Time::seconds;
}
else if (m_value_i == m_last_value_i && m_value_i != 0)
{
if (Time::elapsed - m_last_press_time <= m_press_buffer)
if (Time::seconds - m_last_press_time <= m_press_buffer)
m_pressed = true;
else if (m_repeat_interval > 0 && Time::elapsed >= m_repeat_press_time + m_repeat_delay)
else if (m_repeat_interval > 0 && Time::seconds >= m_repeat_press_time + m_repeat_delay)
{
int prev = (int)((Time::previous_elapsed - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
int cur = (int)((Time::elapsed - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
int prev = (int)((Time::previous_seconds - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
int cur = (int)((Time::seconds - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
m_pressed = prev < cur;
}
}
@ -120,9 +120,9 @@ void VirtualAxis::update()
if (m_last_value_i != 0 && m_value_i != m_last_value_i)
{
m_released = true;
m_last_release_time = Time::elapsed;
m_last_release_time = Time::seconds;
}
else if (Time::elapsed - m_last_release_time <= m_release_buffer)
else if (Time::seconds - m_last_release_time <= m_release_buffer)
m_released = true;
else
m_released = false;

View File

@ -68,7 +68,7 @@ void VirtualButton::update()
m_pressed = false;
m_released = false;
//Keys
// Keys
for (int i = 0; i < m_keys_len; i++)
{
m_keys[i].update();
@ -78,7 +78,7 @@ void VirtualButton::update()
m_released = m_released || m_keys[i].released;
}
//Buttons
// Buttons
for (int i = 0; i < m_buttons_len; i++)
{
m_buttons[i].update();
@ -88,7 +88,7 @@ void VirtualButton::update()
m_released = m_released || m_buttons[i].released;
}
//Axes
// Axes
for (int i = 0; i < m_axes_len; i++)
{
m_axes[i].update();
@ -98,27 +98,27 @@ void VirtualButton::update()
m_released = m_released || m_axes[i].released;
}
//pressed?
// pressed?
if (m_pressed)
{
m_repeat_press_time = m_last_press_time = Time::elapsed;
m_repeat_press_time = m_last_press_time = Time::seconds;
}
else if (Time::elapsed - m_last_press_time <= m_press_buffer)
else if (Time::seconds - m_last_press_time <= m_press_buffer)
{
m_pressed = true;
}
else if (m_down && m_repeat_interval > 0 && Time::elapsed >= m_repeat_press_time + m_repeat_delay)
else if (m_down && m_repeat_interval > 0 && Time::seconds >= m_repeat_press_time + m_repeat_delay)
{
int prev = (int)((Time::previous_elapsed - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
int cur = (int)((Time::elapsed - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
int prev = (int)((Time::previous_seconds - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
int cur = (int)((Time::seconds - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
m_pressed = prev < cur;
}
//released?
// released?
if (m_released)
m_last_release_time = Time::elapsed;
m_last_release_time = Time::seconds;
else
m_released = Time::elapsed - m_last_release_time <= m_release_buffer;
m_released = Time::seconds - m_last_release_time <= m_release_buffer;
}
void VirtualButton::KeyNode::init(Key key)

View File

@ -118,16 +118,16 @@ void VirtualStick::update()
if (m_value_i != Point::zero && m_last_value_i != m_value_i)
{
m_pressed = true;
m_last_press_time = m_repeat_press_time = Time::elapsed;
m_last_press_time = m_repeat_press_time = Time::seconds;
}
else if (m_value_i == m_last_value_i && m_value_i != Point::zero)
{
if (Time::elapsed - m_last_press_time <= m_press_buffer)
if (Time::seconds - m_last_press_time <= m_press_buffer)
m_pressed = true;
else if (m_repeat_interval > 0 && Time::elapsed >= m_repeat_press_time + m_repeat_delay)
else if (m_repeat_interval > 0 && Time::seconds >= m_repeat_press_time + m_repeat_delay)
{
int prev = (int)((Time::previous_elapsed - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
int cur = (int)((Time::elapsed - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
int prev = (int)((Time::previous_seconds - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
int cur = (int)((Time::seconds - m_repeat_press_time - m_repeat_delay) / m_repeat_interval);
m_pressed = prev < cur;
}
}
@ -136,9 +136,9 @@ void VirtualStick::update()
if (m_last_value_i != Point::zero && m_value_i != m_last_value_i)
{
m_released = true;
m_last_release_time = Time::elapsed;
m_last_release_time = Time::seconds;
}
else if (Time::elapsed - m_last_release_time <= m_release_buffer)
else if (Time::seconds - m_last_release_time <= m_release_buffer)
m_released = true;
else
m_released = false;

View File

@ -21,8 +21,8 @@ namespace Blah
// Called during shutdown
void shutdown();
// The time, in milliseconds, since the Application was started
uint64_t time();
// The time, in ticks (microseconds) since the Application was started
uint64_t ticks();
// Called every frame
void frame();

View File

@ -7,6 +7,7 @@
#include <blah/core/app.h>
#include <blah/core/filesystem.h>
#include <blah/core/log.h>
#include <blah/core/time.h>
#include <SDL.h>
#include <SDL_vulkan.h>
@ -170,9 +171,11 @@ void PlatformBackend::shutdown()
SDL_Quit();
}
uint64_t PlatformBackend::time()
uint64_t PlatformBackend::ticks()
{
return (uint64_t)SDL_GetTicks();
auto counter = SDL_GetPerformanceCounter();
auto per_second = (double)SDL_GetPerformanceFrequency();
return (uint64_t)(counter * (Time::ticks_per_second / per_second));
}
// Macro defined by X11 conflicts with MouseButton enum

View File

@ -27,6 +27,9 @@ Color::Color(uint8_t r, uint8_t g, uint8_t b)
Color::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
: r(r), g(g), b(b), a(a) {}
Color::Color(const Vec4& vec4)
: r((int)(vec4.x * 255)), g((int)(vec4.y * 255)), b((int)(vec4.z * 255)), a((int)(vec4.w * 255)) {}
Color::Color(const char* value) : r(0), g(0), b(0), a(255)
{
int length = 0;
@ -83,6 +86,13 @@ void Color::to_hex_rgba(char* buffer) const
buffer[7] = hex[(a & 0x0F) >> 0];
}
String Color::to_hex_rgba() const
{
String str = "00000000";
to_hex_rgba(str.cstr());
return str;
}
void Color::to_hex_rgb(char* buffer) const
{
buffer[0] = hex[(r & 0xF0) >> 4];
@ -93,6 +103,13 @@ void Color::to_hex_rgb(char* buffer) const
buffer[5] = hex[(b & 0x0F) >> 0];
}
String Color::to_hex_rgb() const
{
String str = "000000";
to_hex_rgb(str.cstr());
return str;
}
Color Color::from_rgba(uint32_t value)
{
return
@ -136,7 +153,7 @@ Color Color::operator*(float multiply) const
(int)(a * multiply));
}
Color& Color::operator= (const int rgb)
Color& Color::operator=(const int rgb)
{
r = (uint8_t)((rgb & 0xFF0000) >> 16);
g = (uint8_t)((rgb & 0x00FF00) >> 8);
@ -145,6 +162,9 @@ Color& Color::operator= (const int rgb)
return *this;
}
bool Color::operator ==(const Color& rhs) const { return r == rhs.r && g == rhs.g && b == rhs.b && a == rhs.a; }
bool Color::operator !=(const Color& rhs) const { return r != rhs.r || g != rhs.g || b != rhs.b || a != rhs.a; }
const Color Color::transparent = Color(0, 0, 0, 0);
const Color Color::white = Color(255, 255, 255, 255);
const Color Color::black = Color(0, 0, 0, 255);