large organizational & cleanup refactor

This commit is contained in:
Noel Berry
2021-05-09 17:23:02 -07:00
parent e65752f30b
commit e615b9d7e4
91 changed files with 3188 additions and 3224 deletions

View File

@ -1,11 +1,11 @@
#include <blah/core/app.h>
#include <blah/core/common.h>
#include <blah/core/time.h>
#include <blah/math/point.h>
#include <blah/graphics/framebuffer.h>
#include "../internal/platform_backend.h"
#include "../internal/graphics_backend.h"
#include "../internal/input_backend.h"
#include <blah/app.h>
#include <blah/common.h>
#include <blah/time.h>
#include <blah/numerics/point.h>
#include <blah/graphics/target.h>
#include "internal/platform_backend.h"
#include "internal/graphics_backend.h"
#include "internal/input_backend.h"
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
@ -261,21 +261,20 @@ namespace
{
// A dummy Frame Buffer that represents the Back Buffer
// it doesn't actually contain any textures or details.
class BackBuffer final : public FrameBuffer
class BackBuffer final : public Target
{
Attachments empty_attachments;
TextureRef empty_texture;
Attachments empty_textures;
Attachments& attachments() override
Attachments& textures() override
{
BLAH_ASSERT(false, "Backbuffer doesn't have any attachments");
return empty_attachments;
BLAH_ASSERT(false, "Backbuffer doesn't have any textures");
return empty_textures;
}
const Attachments& attachments() const override
const Attachments& textures() const override
{
BLAH_ASSERT(false, "Backbuffer doesn't have any attachments");
return empty_attachments;
BLAH_ASSERT(false, "Backbuffer doesn't have any textures");
return empty_textures;
}
int width() const override
@ -296,4 +295,4 @@ namespace
}
extern const FrameBufferRef App::backbuffer = FrameBufferRef(new BackBuffer());
extern const TargetRef App::backbuffer = TargetRef(new BackBuffer());

View File

@ -1,5 +1,5 @@
#include <blah/core/common.h>
#include <blah/core/app.h>
#include <blah/common.h>
#include <blah/app.h>
#include <stdarg.h> // for logging methods
#include <stdio.h> // for sprintf

View File

@ -1,24 +1,24 @@
#include <blah/core/filesystem.h>
#include <blah/filesystem.h>
#include <blah/streams/filestream.h>
#include "../internal/platform_backend.h"
#include "internal/platform_backend.h"
using namespace Blah;
FileRef File::open(const FilePath& path, FileMode mode)
{
return PlatformBackend::file_open(path.cstr(), mode);
}
bool File::exists(const FilePath& path)
{
return PlatformBackend::file_exists(path.cstr());
}
bool File::remove(const FilePath& path)
bool File::destroy(const FilePath& path)
{
return PlatformBackend::file_delete(path.cstr());
}
FileStream File::open(const FilePath& path , FileMode mode)
{
return FileStream(path, mode);
}
bool Directory::create(const FilePath& path)
{
return PlatformBackend::dir_create(path.cstr());
@ -29,7 +29,7 @@ bool Directory::exists(const FilePath& path)
return PlatformBackend::dir_exists(path.cstr());
}
bool Directory::remove(const FilePath& path)
bool Directory::destroy(const FilePath& path)
{
return PlatformBackend::dir_delete(path.cstr());
}
@ -56,11 +56,11 @@ void Directory::explore(const FilePath& path)
FilePath Path::get_file_name(const FilePath& path)
{
const char* cstr = path.cstr();
for (int n = path.length() - 2; n >= 0; n --)
if (*(cstr + n) == '/')
{
return FilePath(cstr + n + 1);
}
auto length = path.length();
for (auto n = length; n > 0; n--)
if (*(cstr + n - 1) == '/')
return FilePath(cstr + n);
return path;
}
@ -85,7 +85,7 @@ FilePath Path::get_directory_name(const FilePath& path)
FilePath directory = path;
while (directory.ends_with("/"))
directory = directory.substr(0, -1);
int last = directory.last_index_of('/');
auto last = directory.last_index_of('/');
if (last >= 0)
directory = directory.substr(0, last + 1);
return directory;
@ -107,8 +107,8 @@ FilePath Path::normalize(const FilePath& path)
{
FilePath normalized;
int len = path.length();
for (int n = 0; n < len; n++)
auto len = path.length();
for (auto n = 0; n < len; n++)
{
// normalize slashes
if (path[n] == '\\' || path[n] == '/')
@ -120,16 +120,19 @@ FilePath Path::normalize(const FilePath& path)
else if (path[n] == '.' && n < len - 1 && path[n + 1] == '.')
{
// search backwards for last /
bool couldMoveUp = false;
for (int k = normalized.length() - 2; k >= 0; k--)
if (normalized[k] == '/')
{
normalized = normalized.substr(0, k);
couldMoveUp = true;
break;
}
bool could_move_up = false;
if (normalized.length() > 0)
{
for (auto k = normalized.length() - 1; k > 0; k--)
if (normalized[k - 1] == '/')
{
normalized = normalized.substr(0, k - 1);
could_move_up = true;
break;
}
}
if (!couldMoveUp)
if (!could_move_up)
normalized.append('.');
else
n++;

View File

@ -1,11 +1,11 @@
#include <blah/graphics/batch.h>
#include <blah/graphics/texture.h>
#include <blah/graphics/framebuffer.h>
#include <blah/graphics/target.h>
#include <blah/graphics/mesh.h>
#include <blah/graphics/shader.h>
#include <blah/graphics/material.h>
#include <blah/math/calc.h>
#include <blah/core/app.h>
#include <blah/numerics/calc.h>
#include <blah/app.h>
#include <cmath>
using namespace Blah;
@ -185,7 +185,7 @@ namespace
#define INSERT_BATCH() \
do { \
m_batches.expand(); \
for (int i = m_batches.size() - 1; i > m_batch_insert; i --) \
for (auto i = m_batches.size() - 1; i > m_batch_insert; i --) \
m_batches[i] = std::move(m_batches[i - 1]); \
m_batches[m_batch_insert++] = m_batch; \
m_batch.offset += m_batch.elements; \
@ -378,7 +378,7 @@ void Batch::set_sampler(const TextureSampler& sampler)
m_batch.sampler = sampler;
}
void Batch::render(const FrameBufferRef& target)
void Batch::render(const TargetRef& target)
{
Point size;
if (!target)
@ -389,7 +389,7 @@ void Batch::render(const FrameBufferRef& target)
render(target, Mat4x4::create_ortho_offcenter(0, (float)size.x, (float)size.y, 0, 0.01f, 1000.0f));
}
void Batch::render(const FrameBufferRef& target, const Mat4x4& matrix)
void Batch::render(const TargetRef& target, const Mat4x4& matrix)
{
// nothing to draw
if ((m_batches.size() <= 0 && m_batch.elements <= 0) || m_indices.size() <= 0)

View File

@ -1,53 +0,0 @@
#include <blah/graphics/framebuffer.h>
#include "../internal/graphics_backend.h"
using namespace Blah;
FrameBufferRef FrameBuffer::create(int width, int height)
{
return create(width, height, { TextureFormat::RGBA });
}
FrameBufferRef FrameBuffer::create(int width, int height, const AttachmentFormats& attachments)
{
BLAH_ASSERT(width > 0 && height > 0, "FrameBuffer width and height must be larger than 0");
BLAH_ASSERT(attachments.size() > 0, "At least one attachment must be provided");
int color_count = 0;
int depth_count = 0;
for (int i = 0; i < attachments.size(); i++)
{
BLAH_ASSERT((int)attachments[i] > (int)TextureFormat::None && (int)attachments[i] < (int)TextureFormat::Count, "Invalid texture format");
if (attachments[i] == TextureFormat::DepthStencil)
depth_count++;
else
color_count++;
}
BLAH_ASSERT(depth_count <= 1, "FrameBuffer can only have 1 Depth/Stencil Texture");
BLAH_ASSERT(color_count <= Attachments::MaxCapacity - 1, "Exceeded maximum Color attachment count");
return GraphicsBackend::create_framebuffer(width, height, attachments.data(), attachments.size());
}
TextureRef& FrameBuffer::attachment(int index)
{
return attachments()[index];
}
const TextureRef& FrameBuffer::attachment(int index) const
{
return attachments()[index];
}
int FrameBuffer::width() const
{
return attachments()[0]->width();
}
int FrameBuffer::height() const
{
return attachments()[0]->height();
}

View File

@ -1,5 +1,5 @@
#include <blah/graphics/material.h>
#include <blah/core/common.h>
#include <blah/common.h>
#include <cstring>
using namespace Blah;
@ -19,7 +19,7 @@ namespace
case UniformType::Mat3x2: components = 6; break;
case UniformType::Mat4x4: components = 16; break;
default:
BLAH_ERROR("Unespected Uniform Type");
BLAH_ASSERT(false, "Unespected Uniform Type");
break;
}

View File

@ -1,5 +1,5 @@
#include <blah/graphics/renderpass.h>
#include <blah/core/common.h>
#include <blah/common.h>
#include "../internal/graphics_backend.h"
using namespace Blah;
@ -66,11 +66,7 @@ void RenderPass::perform()
}
// get the total drawable size
Vec2 draw_size;
if (!pass.target)
draw_size = Vec2(App::draw_width(), App::draw_height());
else
draw_size = Vec2(pass.target->width(), pass.target->height());
auto draw_size = Vec2(pass.target->width(), pass.target->height());
// Validate Viewport
if (!pass.has_viewport)

View File

@ -1,5 +1,5 @@
#include <blah/graphics/shader.h>
#include <blah/core/app.h>
#include <blah/app.h>
#include "../internal/graphics_backend.h"
using namespace Blah;
@ -21,7 +21,8 @@ ShaderRef Shader::create(const ShaderData& data)
for (auto& it : uniforms)
if (it.type == UniformType::None)
{
BLAH_ERROR_FMT("Uniform '%s' has an invalid type!\n\tOnly Float/Float2/Float3/Float4/Mat3x2/Mat4x4/Texture are allowed!", it.name.cstr());
auto error = String::fmt("Uniform '%s' has an invalid type!\n\tOnly Float/Float2/Float3/Float4/Mat3x2/Mat4x4/Texture are allowed!", it.name.cstr());
BLAH_ASSERT(false, error.cstr());
return ShaderRef();
}
@ -30,7 +31,8 @@ ShaderRef Shader::create(const ShaderData& data)
for (int j = i + 1; j < uniforms.size(); j ++)
if (uniforms[i].name == uniforms[j].name)
{
BLAH_ERROR_FMT("Shader Uniform names '%s' overlap! All Names must be unique.", uniforms[0].name.cstr());
auto error = String::fmt("Shader Uniform names '%s' overlap! All Names must be unique.", uniforms[0].name.cstr());
BLAH_ASSERT(false, error.cstr());
return ShaderRef();
}
}

View File

@ -1,7 +1,7 @@
#include <blah/graphics/spritefont.h>
#include <blah/images/font.h>
#include <blah/images/packer.h>
#include <blah/core/common.h>
#include <blah/common.h>
using namespace Blah;
@ -123,7 +123,7 @@ float SpriteFont::width_of_line(const String& text, int start) const
float width = 0;
Codepoint last = 0;
for (int i = start; i < text.length(); i ++)
for (auto i = start; i < text.length(); i ++)
{
if (text[i] == '\n')
return width;
@ -139,7 +139,9 @@ float SpriteFont::width_of_line(const String& text, int start) const
width += get_kerning(last, next);
// move to thext utf8 character
i += text.utf8_length(i) - 1;
auto len = text.utf8_length(i);
if (len > 0)
i += len - 1;
last = next;
}
@ -153,7 +155,7 @@ float SpriteFont::height_of(const String& text) const
return 0;
float height = line_height();
for (int i = 0; i < text.length(); i ++)
for (auto i = 0; i < text.length(); i ++)
{
if (text[i] == '\n')
height += line_height();

View File

@ -1,5 +1,5 @@
#include <blah/graphics/subtexture.h>
#include <blah/math/calc.h>
#include <blah/numerics/calc.h>
using namespace Blah;

53
src/graphics/target.cpp Normal file
View File

@ -0,0 +1,53 @@
#include <blah/graphics/target.h>
#include "../internal/graphics_backend.h"
using namespace Blah;
TargetRef Target::create(int width, int height)
{
return create(width, height, { TextureFormat::RGBA });
}
TargetRef Target::create(int width, int height, const AttachmentFormats& textures)
{
BLAH_ASSERT(width > 0 && height > 0, "Target width and height must be larger than 0");
BLAH_ASSERT(textures.size() > 0, "At least one texture must be provided");
int color_count = 0;
int depth_count = 0;
for (int i = 0; i < textures.size(); i++)
{
BLAH_ASSERT((int)textures[i] > (int)TextureFormat::None && (int)textures[i] < (int)TextureFormat::Count, "Invalid texture format");
if (textures[i] == TextureFormat::DepthStencil)
depth_count++;
else
color_count++;
}
BLAH_ASSERT(depth_count <= 1, "Target can only have 1 Depth/Stencil Texture");
BLAH_ASSERT(color_count <= Attachments::capacity - 1, "Exceeded maximum Color texture count");
return GraphicsBackend::create_target(width, height, textures.data(), textures.size());
}
TextureRef& Target::texture(int index)
{
return textures()[index];
}
const TextureRef& Target::texture(int index) const
{
return textures()[index];
}
int Target::width() const
{
return textures()[0]->width();
}
int Target::height() const
{
return textures()[0]->height();
}

View File

@ -1,7 +1,7 @@
#include <blah/graphics/texture.h>
#include <blah/images/image.h>
#include <blah/streams/stream.h>
#include <blah/core/common.h>
#include <blah/common.h>
#include "../internal/graphics_backend.h"
using namespace Blah;

View File

@ -1,8 +1,8 @@
#include <blah/images/aseprite.h>
#include <blah/streams/filestream.h>
#include <blah/core/filesystem.h>
#include <blah/core/common.h>
#include <blah/math/calc.h>
#include <blah/filesystem.h>
#include <blah/common.h>
#include <blah/numerics/calc.h>
#define STBI_NO_STDIO
#define STBI_ONLY_ZLIB
@ -81,7 +81,7 @@ void Aseprite::parse(Stream& stream)
{
if (!stream.is_readable())
{
BLAH_ERROR("Stream is not readable");
BLAH_ASSERT(false, "Stream is not readable");
return;
}
@ -96,7 +96,7 @@ void Aseprite::parse(Stream& stream)
auto magic = stream.read<u16>(Endian::Little);
if (magic != 0xA5E0)
{
BLAH_ERROR("File is not a valid Aseprite file");
BLAH_ASSERT(false, "File is not a valid Aseprite file");
return;
}
@ -133,7 +133,7 @@ void Aseprite::parse(Stream& stream)
auto magic = stream.read<u16>(Endian::Little); // magic number
if (magic != 0xF1FA)
{
BLAH_ERROR("File is not a valid Aseprite file");
BLAH_ASSERT(false, "File is not a valid Aseprite file");
return;
}
@ -247,7 +247,7 @@ void Aseprite::parse_cel(Stream& stream, int frameIndex, size_t maxPosition)
if (res < 0)
{
BLAH_ERROR("Unable to parse Aseprite file");
BLAH_ASSERT(false, "Unable to parse Aseprite file");
return;
}
}
@ -460,6 +460,6 @@ void Aseprite::render_cel(Cel* cel, Frame* frame)
}
else
{
BLAH_ERROR("Aseprite blendmodes aren't implemented");
BLAH_ASSERT(false, "Aseprite blendmodes aren't implemented");
}
}

View File

@ -1,7 +1,7 @@
#include <blah/images/font.h>
#include <blah/streams/filestream.h>
#include <blah/math/calc.h>
#include <blah/core/common.h>
#include <blah/numerics/calc.h>
#include <blah/common.h>
using namespace Blah;
@ -111,7 +111,7 @@ void Font::load(Stream& stream)
if (!stream.is_readable())
{
BLAH_ERROR("Unable to load a font as the Stream was not readable");
BLAH_ASSERT(false, "Unable to load a font as the Stream was not readable");
return;
}

View File

@ -1,7 +1,7 @@
#include <blah/images/image.h>
#include <blah/streams/stream.h>
#include <blah/streams/filestream.h>
#include <blah/core/common.h>
#include <blah/common.h>
using namespace Blah;
@ -148,7 +148,7 @@ void Image::from_stream(Stream& stream)
if (!stream.is_readable())
{
BLAH_ERROR("Unable to load image as the Stream was not readable");
BLAH_ASSERT(false, "Unable to load image as the Stream was not readable");
return;
}
@ -162,7 +162,7 @@ void Image::from_stream(Stream& stream)
if (data == nullptr)
{
BLAH_ERROR("Unable to load image as the Stream's data was not a valid image");
BLAH_ASSERT(false, "Unable to load image as the Stream's data was not a valid image");
return;
}

View File

@ -1,5 +1,5 @@
#include <blah/images/packer.h>
#include <blah/core/common.h>
#include <blah/common.h>
#include <algorithm>
#include <cstring>
@ -169,7 +169,7 @@ void Packer::pack()
// make sure the largest isn't too large
if (sources[0]->packed.w + padding * 2 > max_size || sources[0]->packed.h + padding * 2 > max_size)
{
BLAH_ERROR("Source image is larger than max atlas size");
BLAH_ASSERT(false, "Source image is larger than max atlas size");
return;
}

937
src/input.cpp Normal file
View File

@ -0,0 +1,937 @@
#include <blah/input.h>
#include <blah/app.h>
#include <blah/time.h>
#include <blah/common.h>
#include <blah/numerics/point.h>
#include <blah/numerics/calc.h>
#include "internal/input_backend.h"
#include <cstring>
using namespace Blah;
namespace
{
InputState g_last_state;
InputState g_curr_state;
InputState g_next_state;
InputState g_empty_state;
ControllerState g_empty_controller;
Vector<WeakRef<InputBinding>> g_bindings;
Vector<WeakRef<AxisBinding>> g_axes;
Vector<WeakRef<StickBinding>> g_sticks;
}
void InputBackend::init()
{
g_empty_controller.name = "Disconnected";
for (int i = 0; i < Blah::Input::max_controllers; i++)
g_empty_state.controllers[i].name = g_empty_controller.name;
g_last_state = g_empty_state;
g_curr_state = g_empty_state;
g_next_state = g_empty_state;
g_bindings.dispose();
g_axes.dispose();
g_sticks.dispose();
}
void InputBackend::frame()
{
// cycle states
g_last_state = g_curr_state;
g_curr_state = g_next_state;
// copy state, clear pressed / released values
{
for (int i = 0; i < Blah::Input::max_keyboard_keys; i++)
{
g_next_state.keyboard.pressed[i] = false;
g_next_state.keyboard.released[i] = false;
}
for (int i = 0; i < Blah::Input::max_mouse_buttons; i++)
{
g_next_state.mouse.pressed[i] = false;
g_next_state.mouse.released[i] = false;
}
g_next_state.mouse.wheel = Point::zero;
g_next_state.keyboard.text.clear();
for (int i = 0; i < Blah::Input::max_controllers; i++)
{
ControllerState* controller = &(g_next_state.controllers[i]);
if (!controller->is_connected)
controller->name = nullptr;
for (int j = 0; j < Blah::Input::max_controller_buttons; j++)
{
controller->pressed[j] = false;
controller->released[j] = false;
}
}
}
// update bindings
for (int i = 0; i < g_bindings.size(); i++)
{
if (g_bindings[i].use_count() <= 0)
{
g_bindings.erase(i);
i--;
}
else if (auto binding = g_bindings[i].lock())
{
binding->update();
}
}
for (int i = 0; i < g_axes.size(); i++)
{
if (g_axes[i].use_count() <= 0)
{
g_axes.erase(i);
i--;
}
else if (auto binding = g_axes[i].lock())
{
binding->update();
}
}
for (int i = 0; i < g_sticks.size(); i++)
{
if (g_sticks[i].use_count() <= 0)
{
g_sticks.erase(i);
i--;
}
else if (auto binding = g_sticks[i].lock())
{
binding->update();
}
}
}
void InputBackend::on_mouse_move(float x, float y)
{
g_next_state.mouse.position.x = x;
g_next_state.mouse.position.y = y;
Point size = Point(App::width(), App::height());
Point draw = Point(App::draw_width(), App::draw_height());
g_next_state.mouse.draw_position.x = (x / (float)size.x) * draw.x;
g_next_state.mouse.draw_position.y = (y / (float)size.y) * draw.y;
}
void InputBackend::on_mouse_screen_move(float x, float y)
{
g_next_state.mouse.screen_position.x = x;
g_next_state.mouse.screen_position.y = y;
}
void InputBackend::on_mouse_down(MouseButton button)
{
int i = (int)button;
if (i >= 0 && i < Blah::Input::max_mouse_buttons)
{
g_next_state.mouse.down[i] = true;
g_next_state.mouse.pressed[i] = true;
g_next_state.mouse.timestamp[i] = Time::ticks;
}
}
void InputBackend::on_mouse_up(MouseButton button)
{
int i = (int)button;
if (i >= 0 && i < Blah::Input::max_mouse_buttons)
{
g_next_state.mouse.down[i] = false;
g_next_state.mouse.released[i] = true;
}
}
void InputBackend::on_key_down(Key key)
{
int i = (int)key;
if (i >= 0 && i < Blah::Input::max_keyboard_keys)
{
g_next_state.keyboard.down[i] = true;
g_next_state.keyboard.pressed[i] = true;
g_next_state.keyboard.timestamp[i] = Time::ticks;
}
}
void InputBackend::on_mouse_wheel(Point wheel)
{
g_next_state.mouse.wheel = wheel;
}
void InputBackend::on_key_up(Key key)
{
int i = (int)key;
if (i >= 0 && i < Blah::Input::max_keyboard_keys)
{
g_next_state.keyboard.down[i] = false;
g_next_state.keyboard.released[i] = true;
}
}
void InputBackend::on_text_utf8(const char* text)
{
g_next_state.keyboard.text += text;
}
void InputBackend::on_controller_connect(int index, const char* name, int is_gamepad, int button_count, int axis_count, u16 vendor, u16 product, u16 version)
{
if (index < Blah::Input::max_controllers)
{
ControllerState* controller = &(g_next_state.controllers[index]);
*controller = g_empty_controller;
controller->name = name;
controller->is_connected = true;
controller->is_gamepad = is_gamepad;
controller->button_count = button_count;
controller->axis_count = axis_count;
controller->vendor = vendor;
controller->product = product;
controller->version = version;
}
}
void InputBackend::on_controller_disconnect(int index)
{
if (index < Blah::Input::max_controllers)
g_next_state.controllers[index] = g_empty_controller;
}
void InputBackend::on_button_down(int index, int button)
{
if (index < Blah::Input::max_controllers &&
button < Blah::Input::max_controller_buttons &&
g_next_state.controllers[index].is_connected &&
button < g_next_state.controllers[index].button_count)
{
g_next_state.controllers[index].down[button] = true;
g_next_state.controllers[index].pressed[button] = true;
g_next_state.controllers[index].button_timestamp[button] = Time::ticks;
}
}
void InputBackend::on_button_up(int index, int button)
{
if (index < Blah::Input::max_controllers &&
button < Blah::Input::max_controller_buttons &&
g_next_state.controllers[index].is_connected &&
button < g_next_state.controllers[index].button_count)
{
g_next_state.controllers[index].down[button] = false;
g_next_state.controllers[index].released[button] = true;
}
}
void InputBackend::on_axis_move(int index, int axis, float value)
{
if (index < Blah::Input::max_controllers &&
axis < Blah::Input::max_controller_axis &&
g_next_state.controllers[index].is_connected &&
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::ticks;
}
}
const InputState* Input::state()
{
return &g_curr_state;
}
const InputState* Input::last_state()
{
return &g_last_state;
}
Vec2 Input::mouse()
{
return g_curr_state.mouse.position;
}
Vec2 Input::mouse_draw()
{
return Vec2(g_curr_state.mouse.draw_position);
}
Vec2 Input::mouse_screen()
{
return Vec2(g_curr_state.mouse.screen_position);
}
bool Input::pressed(MouseButton button)
{
int i = (int)button;
return i >= 0 && i < Blah::Input::max_mouse_buttons&& g_curr_state.mouse.pressed[i];
}
bool Input::down(MouseButton button)
{
int i = (int)button;
return i >= 0 && i < Blah::Input::max_mouse_buttons&& g_curr_state.mouse.down[i];
}
bool Input::released(MouseButton button)
{
int i = (int)button;
return i >= 0 && i < Blah::Input::max_mouse_buttons&& g_curr_state.mouse.released[i];
}
Point Input::mouse_wheel()
{
return g_curr_state.mouse.wheel;
}
bool Input::pressed(Key key)
{
int i = (int)key;
return i > 0 && i < Blah::Input::max_keyboard_keys&& g_curr_state.keyboard.pressed[i];
}
bool Input::down(Key key)
{
int i = (int)key;
return i > 0 && i < Blah::Input::max_keyboard_keys&& g_curr_state.keyboard.down[i];
}
bool Input::released(Key key)
{
int i = (int)key;
return i > 0 && i < Blah::Input::max_keyboard_keys&& g_curr_state.keyboard.released[i];
}
bool Input::ctrl()
{
return down(Key::LeftControl) || down(Key::RightControl);
}
bool Input::shift()
{
return down(Key::LeftShift) || down(Key::RightShift);
}
bool Input::alt()
{
return down(Key::LeftAlt) || down(Key::RightAlt);
}
const char* Input::text()
{
return g_curr_state.keyboard.text;
}
const ControllerState* Input::controller(int controllerIndex)
{
if (controllerIndex >= Blah::Input::max_controllers)
{
Log::warn("Trying to access a out-of-range controller at %i", controllerIndex);
return &g_empty_controller;
}
else if (!g_curr_state.controllers[controllerIndex].is_connected)
{
return &g_empty_controller;
}
else
{
return &g_curr_state.controllers[controllerIndex];
}
}
bool Input::pressed(int controllerIndex, Button button)
{
int i = (int)button;
if (controllerIndex < Blah::Input::max_controllers && i >= 0 && i < Blah::Input::max_controller_buttons)
return g_curr_state.controllers[controllerIndex].pressed[i];
return false;
}
bool Input::down(int controllerIndex, Button button)
{
int i = (int)button;
if (controllerIndex < Blah::Input::max_controllers && i >= 0 && i < Blah::Input::max_controller_buttons)
return g_curr_state.controllers[controllerIndex].down[i];
return false;
}
bool Input::released(int controllerIndex, Button button)
{
int i = (int)button;
if (controllerIndex < Blah::Input::max_controllers && i >= 0 && i < Blah::Input::max_controller_buttons)
return g_curr_state.controllers[controllerIndex].released[i];
return false;
}
float Input::axis_check(int controllerIndex, Axis axis)
{
int i = (int)axis;
if (controllerIndex < Blah::Input::max_controllers && i >= 0 && i < Blah::Input::max_controller_axis)
return g_curr_state.controllers[controllerIndex].axis[i];
return 0;
}
int Input::axis_check(int fallback, Key negative, Key positive)
{
if (Input::pressed(positive))
return 1;
else if (Input::pressed(negative))
return -1;
else
{
bool pos = Input::down(positive);
bool neg = Input::down(negative);
if (pos && neg)
return fallback;
else if (pos)
return 1;
else if (neg)
return -1;
else
return 0;
}
}
int Input::axis_check(int fallback, int controllerIndex, Button negative, Button positive)
{
if (Input::pressed(controllerIndex, positive))
return 1;
else if (Input::pressed(controllerIndex, negative))
return -1;
else
{
bool pos = Input::down(controllerIndex, positive);
bool neg = Input::down(controllerIndex, negative);
if (pos && neg)
return fallback;
else if (pos)
return 1;
else if (neg)
return -1;
else
return 0;
}
}
const char* Input::name_of(Key key)
{
switch (key)
{
#define DEFINE_KEY(name, value) case Key::name: return #name;
BLAH_KEY_DEFINITIONS
#undef DEFINE_KEY
}
return "Unknown";
}
const char* Input::name_of(Button button)
{
switch (button)
{
#define DEFINE_BTN(name, value) case Button::name: return #name;
BLAH_BUTTON_DEFINITIONS
#undef DEFINE_BTN
}
return "Unknown";
}
InputBindingRef Input::register_binding(const InputBinding& binding)
{
auto result = std::make_shared<InputBinding>(binding);
g_bindings.push_back(WeakRef<InputBinding>(result));
return result;
}
AxisBindingRef Input::register_binding(const AxisBinding& binding)
{
auto result = std::make_shared<AxisBinding>(binding);
g_axes.push_back(WeakRef<AxisBinding>(result));
return result;
}
StickBindingRef Input::register_binding(const StickBinding& binding)
{
auto result = std::make_shared<StickBinding>(binding);
g_sticks.push_back(WeakRef<StickBinding>(result));
return result;
}
InputBinding::TriggerBind::TriggerBind(Axis axis)
: axis(axis)
{
}
InputBinding::TriggerBind::TriggerBind(int controller, Axis axis, float threshold, bool positive)
: controller(controller), axis(axis), threshold(threshold), positive(positive)
{
}
bool InputBinding::TriggerBind::is_down(float axis_value) const
{
if ((axis_value > 0 && positive) || (axis_value < 0 && !positive))
{
if (Calc::abs(axis_value) >= threshold)
return true;
}
return false;
}
InputBinding::ButtonBind::ButtonBind(Button button)
: button(button) {}
InputBinding::ButtonBind::ButtonBind(int controller, Button button)
: controller(controller), button(button) {}
bool InputBinding::pressed() const
{
if (m_press_consumed)
return false;
if (m_last_press_time >= 0 && (Time::seconds - m_last_press_time) <= press_buffer)
return true;
return m_pressed;
}
bool InputBinding::released() const
{
if (m_release_consumed)
return false;
if (m_last_release_time >= 0 && (Time::seconds - m_last_release_time) <= release_buffer)
return true;
return m_released;
}
bool InputBinding::down() const
{
return m_down;
}
float InputBinding::value() const
{
return m_value;
}
int InputBinding::sign() const
{
return (int)Calc::sign(m_value);
}
double InputBinding::timestamp() const
{
return m_last_timestamp;
}
void InputBinding::update()
{
m_press_consumed = false;
m_release_consumed = false;
if (get_pressed())
{
m_last_timestamp = Time::seconds;
m_last_press_time = Time::seconds;
m_pressed = true;
}
else
{
m_pressed = false;
}
if (get_released())
{
m_last_release_time = Time::seconds;
m_released = true;
}
else
{
m_released = false;
}
m_down = get_down();
m_value = get_value();
}
void InputBinding::consume_press()
{
m_press_consumed = true;
m_last_press_time = -1;
}
void InputBinding::consume_release()
{
m_release_consumed = true;
m_last_release_time = -1;
}
InputBinding& InputBinding::add(Key key)
{
keys.push_back(key);
return *this;
}
InputBinding& InputBinding::add(ButtonBind button)
{
buttons.push_back(button);
return *this;
}
InputBinding& InputBinding::add(TriggerBind trigger)
{
triggers.push_back(trigger);
return *this;
}
InputBinding& InputBinding::add(MouseButton button)
{
mouse.push_back(button);
return *this;
}
InputBinding& InputBinding::add_left_trigger(int controller, float threshold)
{
triggers.push_back(TriggerBind(controller, Axis::LeftTrigger, threshold, true));
return *this;
}
InputBinding& InputBinding::add_right_trigger(int controller, float threshold)
{
triggers.push_back(TriggerBind(controller, Axis::RightTrigger, threshold, true));
return *this;
}
InputBinding& InputBinding::set_controller(int index)
{
for (auto& it : buttons)
it.controller = index;
for (auto& it : triggers)
it.controller = index;
return *this;
}
void InputBinding::clear()
{
keys.clear();
buttons.clear();
triggers.clear();
mouse.clear();
}
bool InputBinding::get_pressed() const
{
for (auto& it : keys)
if (Input::pressed(it))
return true;
for (auto& it : mouse)
if (Input::pressed(it))
return true;
for (auto& it : buttons)
if (Input::pressed(it.controller, it.button))
return true;
for (auto& it : triggers)
{
if (it.controller < 0 || it.controller >= Input::max_controllers)
continue;
if ((int)it.axis < 0 || (int)it.axis >= Input::max_controller_axis)
continue;
if (it.is_down(Input::state()->controllers[it.controller].axis[(int)it.axis]) &&
!it.is_down(Input::last_state()->controllers[it.controller].axis[(int)it.axis]))
return true;
}
return false;
}
bool InputBinding::get_released() const
{
for (auto& it : keys)
if (Input::released(it))
return true;
for (auto& it : mouse)
if (Input::released(it))
return true;
for (auto& it : buttons)
if (Input::released(it.controller, it.button))
return true;
for (auto& it : triggers)
{
if (it.controller < 0 || it.controller >= Input::max_controllers)
continue;
if ((int)it.axis < 0 || (int)it.axis >= Input::max_controller_axis)
continue;
if (!it.is_down(Input::state()->controllers[it.controller].axis[(int)it.axis]) &&
it.is_down(Input::last_state()->controllers[it.controller].axis[(int)it.axis]))
return true;
}
return false;
}
bool InputBinding::get_down() const
{
for (auto& it : keys)
if (Input::down(it))
return true;
for (auto& it : mouse)
if (Input::down(it))
return true;
for (auto& it : buttons)
if (Input::down(it.controller, it.button))
return true;
for (auto& it : triggers)
{
if (it.controller < 0 || it.controller >= Input::max_controllers)
continue;
if ((int)it.axis < 0 || (int)it.axis >= Input::max_controller_axis)
continue;
if (it.is_down(Input::state()->controllers[it.controller].axis[(int)it.axis]))
return true;
}
return false;
}
float InputBinding::get_value() const
{
for (auto& it : keys)
if (Input::down(it))
return 1.0f;
for (auto& it : mouse)
if (Input::down(it))
return 1.0f;
for (auto& it : buttons)
if (Input::down(it.controller, it.button))
return 1.0f;
float highest = 0;
for (auto& it : triggers)
{
if (it.controller < 0 || it.controller >= Input::max_controllers)
continue;
if ((int)it.axis < 0 || (int)it.axis >= Input::max_controller_axis)
continue;
float raw_value = Input::state()->controllers[it.controller].axis[(int)it.axis];
if (it.is_down(raw_value))
{
float mapped_value = Calc::clamped_map(Calc::abs(raw_value), it.threshold, 1.0f, 0.0f, 1.0f);
if (mapped_value > highest)
highest = mapped_value;
}
}
return highest;
}
float AxisBinding::value() const
{
float neg = negative.value();
float pos = positive.value();
// neither are down
if (neg <= 0 && pos <= 0)
return 0;
// negative-only is down
if (neg > 0 && pos <= 0)
return -neg;
// positive-only is down
if (pos > 0 && neg <= 0)
return pos;
// both are down:
// overlap cancel out
if (overlap == Overlap::Cancel)
return 0;
// overlap takes older
if (overlap == Overlap::Older)
{
if (negative.timestamp() < positive.timestamp())
return -neg;
else
return pos;
}
// overlap takes newer
if (negative.timestamp() > positive.timestamp())
return -neg;
else
return pos;
}
int AxisBinding::sign() const
{
return (int)Calc::sign(value());
}
void AxisBinding::update()
{
negative.update();
positive.update();
}
void AxisBinding::consume_press()
{
negative.consume_press();
positive.consume_press();
}
void AxisBinding::consume_release()
{
negative.consume_release();
positive.consume_release();
}
AxisBinding& AxisBinding::add_left_stick_x(int controller, float threshold)
{
negative.add(InputBinding::TriggerBind(controller, Axis::LeftX, threshold, false));
positive.add(InputBinding::TriggerBind(controller, Axis::LeftX, threshold, true));
return *this;
}
AxisBinding& AxisBinding::add_left_stick_y(int controller, float threshold)
{
negative.add(InputBinding::TriggerBind(controller, Axis::LeftY, threshold, false));
positive.add(InputBinding::TriggerBind(controller, Axis::LeftY, threshold, true));
return *this;
}
AxisBinding& AxisBinding::add_right_stick_x(int controller, float threshold)
{
negative.add(InputBinding::TriggerBind(controller, Axis::RightX, threshold, false));
positive.add(InputBinding::TriggerBind(controller, Axis::RightX, threshold, true));
return *this;
}
AxisBinding& AxisBinding::add_right_stick_y(int controller, float threshold)
{
negative.add(InputBinding::TriggerBind(controller, Axis::RightY, threshold, false));
positive.add(InputBinding::TriggerBind(controller, Axis::RightY, threshold, true));
return *this;
}
AxisBinding& AxisBinding::set_controller(int index)
{
negative.set_controller(index);
positive.set_controller(index);
return *this;
}
void AxisBinding::clear()
{
negative.clear();
positive.clear();
}
Vec2 StickBinding::value() const
{
Vec2 result = Vec2(x.value(), y.value());
if (round_threshold > 0 && result.length() < round_threshold)
return Vec2::zero;
return result;
}
Point StickBinding::sign() const
{
Vec2 result = value();
return Point((int)Calc::sign(result.x), (int)Calc::sign(result.y));
}
void StickBinding::update()
{
x.update();
y.update();
}
void StickBinding::consume_press()
{
x.consume_press();
y.consume_press();
}
void StickBinding::consume_release()
{
x.consume_release();
y.consume_release();
}
StickBinding& StickBinding::add_dpad(int controller)
{
x.negative.add(InputBinding::ButtonBind(controller, Button::Left));
x.positive.add(InputBinding::ButtonBind(controller, Button::Right));
y.negative.add(InputBinding::ButtonBind(controller, Button::Up));
y.positive.add(InputBinding::ButtonBind(controller, Button::Down));
return *this;
}
StickBinding& StickBinding::add_left_stick(int controller, float threshold)
{
x.add_left_stick_x(controller, threshold);
y.add_left_stick_y(controller, threshold);
return *this;
}
StickBinding& StickBinding::add_right_stick(int controller, float threshold)
{
x.add_right_stick_x(controller, threshold);
y.add_right_stick_y(controller, threshold);
return *this;
}
StickBinding& StickBinding::set_controller(int index)
{
x.set_controller(index);
y.set_controller(index);
return *this;
}
void StickBinding::clear()
{
x.clear();
y.clear();
}

View File

@ -1,469 +0,0 @@
#include <blah/input/binding.h>
#include <blah/math/calc.h>
#include <blah/core/time.h>
using namespace Blah;
Binding::TriggerBind::TriggerBind(Axis axis)
: axis(axis)
{
}
Binding::TriggerBind::TriggerBind(int controller, Axis axis, float threshold, bool positive)
: controller(controller), axis(axis), threshold(threshold), positive(positive)
{
}
bool Binding::TriggerBind::is_down(float axis_value) const
{
if ((axis_value > 0 && positive) || (axis_value < 0 && !positive))
{
if (Calc::abs(axis_value) >= threshold)
return true;
}
return false;
}
Binding::ButtonBind::ButtonBind(Button button)
: button(button) {}
Binding::ButtonBind::ButtonBind(int controller, Button button)
: controller(controller), button(button) {}
bool Binding::pressed() const
{
if (m_press_consumed)
return false;
if (m_last_press_time >= 0 && (Time::seconds - m_last_press_time) <= press_buffer)
return true;
return m_pressed;
}
bool Binding::released() const
{
if (m_release_consumed)
return false;
if (m_last_release_time >= 0 && (Time::seconds - m_last_release_time) <= release_buffer)
return true;
return m_released;
}
bool Binding::down() const
{
return m_down;
}
float Binding::value() const
{
return m_value;
}
int Binding::sign() const
{
return (int)Calc::sign(m_value);
}
double Binding::timestamp() const
{
return m_last_timestamp;
}
void Binding::update()
{
m_press_consumed = false;
m_release_consumed = false;
if (get_pressed())
{
m_last_timestamp = Time::seconds;
m_last_press_time = Time::seconds;
m_pressed = true;
}
else
{
m_pressed = false;
}
if (get_released())
{
m_last_release_time = Time::seconds;
m_released = true;
}
else
{
m_released = false;
}
m_down = get_down();
m_value = get_value();
}
void Binding::consume_press()
{
m_press_consumed = true;
m_last_press_time = -1;
}
void Binding::consume_release()
{
m_release_consumed = true;
m_last_release_time = -1;
}
Binding& Binding::add(Key key)
{
keys.push_back(key);
return *this;
}
Binding& Binding::add(ButtonBind button)
{
buttons.push_back(button);
return *this;
}
Binding& Binding::add(TriggerBind trigger)
{
triggers.push_back(trigger);
return *this;
}
Binding& Binding::add(MouseButton button)
{
mouse.push_back(button);
return *this;
}
Binding& Binding::add_left_trigger(int controller, float threshold)
{
triggers.push_back(TriggerBind(controller, Axis::LeftTrigger, threshold, true));
return *this;
}
Binding& Binding::add_right_trigger(int controller, float threshold)
{
triggers.push_back(TriggerBind(controller, Axis::RightTrigger, threshold, true));
return *this;
}
Binding& Binding::set_controller(int index)
{
for (auto& it : buttons)
it.controller = index;
for (auto& it : triggers)
it.controller = index;
return *this;
}
void Binding::clear()
{
keys.clear();
buttons.clear();
triggers.clear();
mouse.clear();
}
bool Binding::get_pressed() const
{
for (auto& it : keys)
if (Input::pressed(it))
return true;
for (auto& it : mouse)
if (Input::pressed(it))
return true;
for (auto& it : buttons)
if (Input::pressed(it.controller, it.button))
return true;
for (auto& it : triggers)
{
if (it.controller < 0 || it.controller >= Input::max_controllers)
continue;
if ((int)it.axis < 0 || (int)it.axis >= Input::max_controller_axis)
continue;
if (it.is_down(Input::state()->controllers[it.controller].axis[(int)it.axis]) &&
!it.is_down(Input::last_state()->controllers[it.controller].axis[(int)it.axis]))
return true;
}
return false;
}
bool Binding::get_released() const
{
for (auto& it : keys)
if (Input::released(it))
return true;
for (auto& it : mouse)
if (Input::released(it))
return true;
for (auto& it : buttons)
if (Input::released(it.controller, it.button))
return true;
for (auto& it : triggers)
{
if (it.controller < 0 || it.controller >= Input::max_controllers)
continue;
if ((int)it.axis < 0 || (int)it.axis >= Input::max_controller_axis)
continue;
if (!it.is_down(Input::state()->controllers[it.controller].axis[(int)it.axis]) &&
it.is_down(Input::last_state()->controllers[it.controller].axis[(int)it.axis]))
return true;
}
return false;
}
bool Binding::get_down() const
{
for (auto& it : keys)
if (Input::down(it))
return true;
for (auto& it : mouse)
if (Input::down(it))
return true;
for (auto& it : buttons)
if (Input::down(it.controller, it.button))
return true;
for (auto& it : triggers)
{
if (it.controller < 0 || it.controller >= Input::max_controllers)
continue;
if ((int)it.axis < 0 || (int)it.axis >= Input::max_controller_axis)
continue;
if (it.is_down(Input::state()->controllers[it.controller].axis[(int)it.axis]))
return true;
}
return false;
}
float Binding::get_value() const
{
for (auto& it : keys)
if (Input::down(it))
return 1.0f;
for (auto& it : mouse)
if (Input::down(it))
return 1.0f;
for (auto& it : buttons)
if (Input::down(it.controller, it.button))
return 1.0f;
float highest = 0;
for (auto& it : triggers)
{
if (it.controller < 0 || it.controller >= Input::max_controllers)
continue;
if ((int)it.axis < 0 || (int)it.axis >= Input::max_controller_axis)
continue;
float raw_value = Input::state()->controllers[it.controller].axis[(int)it.axis];
if (it.is_down(raw_value))
{
float mapped_value = Calc::clamped_map(Calc::abs(raw_value), it.threshold, 1.0f, 0.0f, 1.0f);
if (mapped_value > highest)
highest = mapped_value;
}
}
return highest;
}
float AxisBinding::value() const
{
float neg = negative.value();
float pos = positive.value();
// neither are down
if (neg <= 0 && pos <= 0)
return 0;
// negative-only is down
if (neg > 0 && pos <= 0)
return -neg;
// positive-only is down
if (pos > 0 && neg <= 0)
return pos;
// both are down:
// overlap cancel out
if (overlap == Overlap::Cancel)
return 0;
// overlap takes older
if (overlap == Overlap::Older)
{
if (negative.timestamp() < positive.timestamp())
return -neg;
else
return pos;
}
// overlap takes newer
if (negative.timestamp() > positive.timestamp())
return -neg;
else
return pos;
}
int AxisBinding::sign() const
{
return (int)Calc::sign(value());
}
void AxisBinding::update()
{
negative.update();
positive.update();
}
void AxisBinding::consume_press()
{
negative.consume_press();
positive.consume_press();
}
void AxisBinding::consume_release()
{
negative.consume_release();
positive.consume_release();
}
AxisBinding& AxisBinding::add_left_stick_x(int controller, float threshold)
{
negative.add(Binding::TriggerBind(controller, Axis::LeftX, threshold, false));
positive.add(Binding::TriggerBind(controller, Axis::LeftX, threshold, true));
return *this;
}
AxisBinding& AxisBinding::add_left_stick_y(int controller, float threshold)
{
negative.add(Binding::TriggerBind(controller, Axis::LeftY, threshold, false));
positive.add(Binding::TriggerBind(controller, Axis::LeftY, threshold, true));
return *this;
}
AxisBinding& AxisBinding::add_right_stick_x(int controller, float threshold)
{
negative.add(Binding::TriggerBind(controller, Axis::RightX, threshold, false));
positive.add(Binding::TriggerBind(controller, Axis::RightX, threshold, true));
return *this;
}
AxisBinding& AxisBinding::add_right_stick_y(int controller, float threshold)
{
negative.add(Binding::TriggerBind(controller, Axis::RightY, threshold, false));
positive.add(Binding::TriggerBind(controller, Axis::RightY, threshold, true));
return *this;
}
AxisBinding& AxisBinding::set_controller(int index)
{
negative.set_controller(index);
positive.set_controller(index);
return *this;
}
void AxisBinding::clear()
{
negative.clear();
positive.clear();
}
Vec2 StickBinding::value() const
{
Vec2 result = Vec2(x.value(), y.value());
if (round_threshold > 0 && result.length() < round_threshold)
return Vec2::zero;
return result;
}
Point StickBinding::sign() const
{
Vec2 result = value();
return Point((int)Calc::sign(result.x), (int)Calc::sign(result.y));
}
void StickBinding::update()
{
x.update();
y.update();
}
void StickBinding::consume_press()
{
x.consume_press();
y.consume_press();
}
void StickBinding::consume_release()
{
x.consume_release();
y.consume_release();
}
StickBinding& StickBinding::add_dpad(int controller)
{
x.negative.add(Binding::ButtonBind(controller, Button::Left));
x.positive.add(Binding::ButtonBind(controller, Button::Right));
y.negative.add(Binding::ButtonBind(controller, Button::Up));
y.positive.add(Binding::ButtonBind(controller, Button::Down));
return *this;
}
StickBinding& StickBinding::add_left_stick(int controller, float threshold)
{
x.add_left_stick_x(controller, threshold);
y.add_left_stick_y(controller, threshold);
return *this;
}
StickBinding& StickBinding::add_right_stick(int controller, float threshold)
{
x.add_right_stick_x(controller, threshold);
y.add_right_stick_y(controller, threshold);
return *this;
}
StickBinding& StickBinding::set_controller(int index)
{
x.set_controller(index);
y.set_controller(index);
return *this;
}
void StickBinding::clear()
{
x.clear();
y.clear();
}

View File

@ -1,70 +0,0 @@
#include <blah/input/binding_registry.h>
using namespace Blah;
Vector<std::weak_ptr<Binding>> BindingRegistry::bindings;
Vector<std::weak_ptr<AxisBinding>> BindingRegistry::axes;
Vector<std::weak_ptr<StickBinding>> BindingRegistry::sticks;
BindingRef BindingRegistry::register_binding(const Binding& binding)
{
auto result = std::make_shared<Binding>(binding);
bindings.push_back(std::weak_ptr<Binding>(result));
return result;
}
AxisBindingRef BindingRegistry::register_axis(const AxisBinding& binding)
{
auto result = std::make_shared<AxisBinding>(binding);
axes.push_back(std::weak_ptr<AxisBinding>(result));
return result;
}
StickBindingRef BindingRegistry::register_stick(const StickBinding& binding)
{
auto result = std::make_shared<StickBinding>(binding);
sticks.push_back(std::weak_ptr<StickBinding>(result));
return result;
}
void BindingRegistry::update()
{
for (int i = 0; i < bindings.size(); i++)
{
if (bindings[i].use_count() <= 0)
{
bindings.erase(i);
i--;
}
else if (auto binding = bindings[i].lock())
{
binding->update();
}
}
for (int i = 0; i < axes.size(); i++)
{
if (axes[i].use_count() <= 0)
{
axes.erase(i);
i--;
}
else if (auto binding = axes[i].lock())
{
binding->update();
}
}
for (int i = 0; i < sticks.size(); i++)
{
if (sticks[i].use_count() <= 0)
{
sticks.erase(i);
i--;
}
else if (auto binding = sticks[i].lock())
{
binding->update();
}
}
}

View File

@ -1,406 +0,0 @@
#include <blah/input/input.h>
#include <blah/input/binding_registry.h>
#include <blah/core/app.h>
#include <blah/core/time.h>
#include <blah/core/common.h>
#include <blah/math/point.h>
#include "../internal/input_backend.h"
#include <cstring>
using namespace Blah;
namespace
{
InputState g_last_state;
InputState g_curr_state;
InputState g_next_state;
InputState g_empty_state;
ControllerState g_empty_controller;
}
void InputBackend::init()
{
g_empty_controller.name = "Disconnected";
for (int i = 0; i < Blah::Input::max_controllers; i++)
g_empty_state.controllers[i].name = g_empty_controller.name;
g_last_state = g_empty_state;
g_curr_state = g_empty_state;
g_next_state = g_empty_state;
}
void InputBackend::frame()
{
// cycle states
g_last_state = g_curr_state;
g_curr_state = g_next_state;
// copy state, clear pressed / released values
{
for (int i = 0; i < Blah::Input::max_keyboard_keys; i++)
{
g_next_state.keyboard.pressed[i] = false;
g_next_state.keyboard.released[i] = false;
}
for (int i = 0; i < Blah::Input::max_mouse_buttons; i++)
{
g_next_state.mouse.pressed[i] = false;
g_next_state.mouse.released[i] = false;
}
g_next_state.mouse.wheel = Point::zero;
g_next_state.keyboard.text.clear();
for (int i = 0; i < Blah::Input::max_controllers; i++)
{
ControllerState* controller = &(g_next_state.controllers[i]);
if (!controller->is_connected)
controller->name = nullptr;
for (int j = 0; j < Blah::Input::max_controller_buttons; j++)
{
controller->pressed[j] = false;
controller->released[j] = false;
}
}
}
// update bindings
BindingRegistry::update();
}
void InputBackend::on_mouse_move(float x, float y)
{
g_next_state.mouse.position.x = x;
g_next_state.mouse.position.y = y;
Point size = Point(App::width(), App::height());
Point draw = Point(App::draw_width(), App::draw_height());
g_next_state.mouse.draw_position.x = (x / (float)size.x) * draw.x;
g_next_state.mouse.draw_position.y = (y / (float)size.y) * draw.y;
}
void InputBackend::on_mouse_screen_move(float x, float y)
{
g_next_state.mouse.screen_position.x = x;
g_next_state.mouse.screen_position.y = y;
}
void InputBackend::on_mouse_down(MouseButton button)
{
int i = (int)button;
if (i >= 0 && i < Blah::Input::max_mouse_buttons)
{
g_next_state.mouse.down[i] = true;
g_next_state.mouse.pressed[i] = true;
g_next_state.mouse.timestamp[i] = Time::ticks;
}
}
void InputBackend::on_mouse_up(MouseButton button)
{
int i = (int)button;
if (i >= 0 && i < Blah::Input::max_mouse_buttons)
{
g_next_state.mouse.down[i] = false;
g_next_state.mouse.released[i] = true;
}
}
void InputBackend::on_key_down(Key key)
{
int i = (int)key;
if (i >= 0 && i < Blah::Input::max_keyboard_keys)
{
g_next_state.keyboard.down[i] = true;
g_next_state.keyboard.pressed[i] = true;
g_next_state.keyboard.timestamp[i] = Time::ticks;
}
}
void InputBackend::on_mouse_wheel(Point wheel)
{
g_next_state.mouse.wheel = wheel;
}
void InputBackend::on_key_up(Key key)
{
int i = (int)key;
if (i >= 0 && i < Blah::Input::max_keyboard_keys)
{
g_next_state.keyboard.down[i] = false;
g_next_state.keyboard.released[i] = true;
}
}
void InputBackend::on_text_utf8(const char* text)
{
g_next_state.keyboard.text += text;
}
void InputBackend::on_controller_connect(int index, const char* name, int is_gamepad, int button_count, int axis_count, u16 vendor, u16 product, u16 version)
{
if (index < Blah::Input::max_controllers)
{
ControllerState* controller = &(g_next_state.controllers[index]);
*controller = g_empty_controller;
controller->name = name;
controller->is_connected = true;
controller->is_gamepad = is_gamepad;
controller->button_count = button_count;
controller->axis_count = axis_count;
controller->vendor = vendor;
controller->product = product;
controller->version = version;
}
}
void InputBackend::on_controller_disconnect(int index)
{
if (index < Blah::Input::max_controllers)
g_next_state.controllers[index] = g_empty_controller;
}
void InputBackend::on_button_down(int index, int button)
{
if (index < Blah::Input::max_controllers &&
button < Blah::Input::max_controller_buttons &&
g_next_state.controllers[index].is_connected &&
button < g_next_state.controllers[index].button_count)
{
g_next_state.controllers[index].down[button] = true;
g_next_state.controllers[index].pressed[button] = true;
g_next_state.controllers[index].button_timestamp[button] = Time::ticks;
}
}
void InputBackend::on_button_up(int index, int button)
{
if (index < Blah::Input::max_controllers &&
button < Blah::Input::max_controller_buttons &&
g_next_state.controllers[index].is_connected &&
button < g_next_state.controllers[index].button_count)
{
g_next_state.controllers[index].down[button] = false;
g_next_state.controllers[index].released[button] = true;
}
}
void InputBackend::on_axis_move(int index, int axis, float value)
{
if (index < Blah::Input::max_controllers &&
axis < Blah::Input::max_controller_axis &&
g_next_state.controllers[index].is_connected &&
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::ticks;
}
}
const InputState* Input::state()
{
return &g_curr_state;
}
const InputState* Input::last_state()
{
return &g_last_state;
}
Vec2 Input::mouse()
{
return g_curr_state.mouse.position;
}
Vec2 Input::mouse_draw()
{
return Vec2(g_curr_state.mouse.draw_position);
}
Vec2 Input::mouse_screen()
{
return Vec2(g_curr_state.mouse.screen_position);
}
bool Input::pressed(MouseButton button)
{
int i = (int)button;
return i >= 0 && i < Blah::Input::max_mouse_buttons&& g_curr_state.mouse.pressed[i];
}
bool Input::down(MouseButton button)
{
int i = (int)button;
return i >= 0 && i < Blah::Input::max_mouse_buttons&& g_curr_state.mouse.down[i];
}
bool Input::released(MouseButton button)
{
int i = (int)button;
return i >= 0 && i < Blah::Input::max_mouse_buttons&& g_curr_state.mouse.released[i];
}
Point Input::mouse_wheel()
{
return g_curr_state.mouse.wheel;
}
bool Input::pressed(Key key)
{
int i = (int)key;
return i > 0 && i < Blah::Input::max_keyboard_keys&& g_curr_state.keyboard.pressed[i];
}
bool Input::down(Key key)
{
int i = (int)key;
return i > 0 && i < Blah::Input::max_keyboard_keys&& g_curr_state.keyboard.down[i];
}
bool Input::released(Key key)
{
int i = (int)key;
return i > 0 && i < Blah::Input::max_keyboard_keys&& g_curr_state.keyboard.released[i];
}
bool Input::ctrl()
{
return down(Key::LeftControl) || down(Key::RightControl);
}
bool Input::shift()
{
return down(Key::LeftShift) || down(Key::RightShift);
}
bool Input::alt()
{
return down(Key::LeftAlt) || down(Key::RightAlt);
}
const char* Input::text()
{
return g_curr_state.keyboard.text;
}
const ControllerState* Input::controller(int controllerIndex)
{
if (controllerIndex >= Blah::Input::max_controllers)
{
Log::warn("Trying to access a out-of-range controller at %i", controllerIndex);
return &g_empty_controller;
}
else if (!g_curr_state.controllers[controllerIndex].is_connected)
{
return &g_empty_controller;
}
else
{
return &g_curr_state.controllers[controllerIndex];
}
}
bool Input::pressed(int controllerIndex, Button button)
{
int i = (int)button;
if (controllerIndex < Blah::Input::max_controllers && i >= 0 && i < Blah::Input::max_controller_buttons)
return g_curr_state.controllers[controllerIndex].pressed[i];
return false;
}
bool Input::down(int controllerIndex, Button button)
{
int i = (int)button;
if (controllerIndex < Blah::Input::max_controllers && i >= 0 && i < Blah::Input::max_controller_buttons)
return g_curr_state.controllers[controllerIndex].down[i];
return false;
}
bool Input::released(int controllerIndex, Button button)
{
int i = (int)button;
if (controllerIndex < Blah::Input::max_controllers && i >= 0 && i < Blah::Input::max_controller_buttons)
return g_curr_state.controllers[controllerIndex].released[i];
return false;
}
float Input::axis_check(int controllerIndex, Axis axis)
{
int i = (int)axis;
if (controllerIndex < Blah::Input::max_controllers && i >= 0 && i < Blah::Input::max_controller_axis)
return g_curr_state.controllers[controllerIndex].axis[i];
return 0;
}
int Input::axis_check(int fallback, Key negative, Key positive)
{
if (Input::pressed(positive))
return 1;
else if (Input::pressed(negative))
return -1;
else
{
bool pos = Input::down(positive);
bool neg = Input::down(negative);
if (pos && neg)
return fallback;
else if (pos)
return 1;
else if (neg)
return -1;
else
return 0;
}
}
int Input::axis_check(int fallback, int controllerIndex, Button negative, Button positive)
{
if (Input::pressed(controllerIndex, positive))
return 1;
else if (Input::pressed(controllerIndex, negative))
return -1;
else
{
bool pos = Input::down(controllerIndex, positive);
bool neg = Input::down(controllerIndex, negative);
if (pos && neg)
return fallback;
else if (pos)
return 1;
else if (neg)
return -1;
else
return 0;
}
}
const char* Input::name_of(Key key)
{
switch (key)
{
#define DEFINE_KEY(name, value) case Key::name: return #name;
BLAH_KEY_DEFINITIONS
#undef DEFINE_KEY
}
return "Unknown";
}
const char* Input::name_of(Button button)
{
switch (button)
{
#define DEFINE_BTN(name, value) case Button::name: return #name;
BLAH_BUTTON_DEFINITIONS
#undef DEFINE_BTN
}
return "Unknown";
}

View File

@ -1,12 +1,12 @@
#pragma once
#include <blah/core/app.h>
#include <blah/app.h>
#include <blah/graphics/renderpass.h>
#include <blah/graphics/texture.h>
#include <blah/graphics/framebuffer.h>
#include <blah/graphics/target.h>
#include <blah/graphics/shader.h>
#include <blah/graphics/mesh.h>
#include <blah/graphics/material.h>
#include <blah/math/color.h>
#include <blah/numerics/color.h>
namespace Blah
{
@ -45,9 +45,9 @@ namespace Blah
// if the Texture is invalid, this should return an empty reference.
TextureRef create_texture(int width, int height, TextureFormat format);
// Creates a new FrameBuffer.
// if the FrameBuffer is invalid, this should return an empty reference.
FrameBufferRef create_framebuffer(int width, int height, const TextureFormat* attachments, int attachment_count);
// Creates a new Target.
// if the Target is invalid, this should return an empty reference.
TargetRef create_target(int width, int height, const TextureFormat* attachments, int attachment_count);
// Creates a new Shader.
// if the Shader is invalid, this should return an empty reference.

View File

@ -5,7 +5,7 @@
#include "../internal/graphics_backend.h"
#include "../internal/platform_backend.h"
#include <blah/core/common.h>
#include <blah/common.h>
#include <cstdio>
#include <cstring>
#include <cstddef>
@ -252,7 +252,7 @@ namespace Blah
hr = state.device->CreateTexture2D(&desc, NULL, &staging);
if (!SUCCEEDED(hr))
{
BLAH_ERROR("Failed to create staging texture to get data");
BLAH_ASSERT(false, "Failed to create staging texture to get data");
return;
}
}
@ -270,7 +270,7 @@ namespace Blah
if (!SUCCEEDED(hr))
{
BLAH_ERROR("Failed to get texture data");
BLAH_ASSERT(false, "Failed to get texture data");
return;
}
@ -285,16 +285,16 @@ namespace Blah
};
class D3D11_FrameBuffer : public FrameBuffer
class D3D11_Target : public Target
{
private:
Attachments m_attachments;
public:
StackVector<ID3D11RenderTargetView*, Attachments::MaxCapacity - 1> color_views;
StackVector<ID3D11RenderTargetView*, Attachments::capacity - 1> color_views;
ID3D11DepthStencilView* depth_view = nullptr;
D3D11_FrameBuffer(int width, int height, const TextureFormat* attachments, int attachment_count)
D3D11_Target(int width, int height, const TextureFormat* attachments, int attachment_count)
{
for (int i = 0; i < attachment_count; i++)
{
@ -315,19 +315,19 @@ namespace Blah
}
}
~D3D11_FrameBuffer()
~D3D11_Target()
{
for (auto& it : color_views)
it->Release();
color_views.clear();
}
Attachments& attachments() override
Attachments& textures() override
{
return m_attachments;
}
const Attachments& attachments() const override
const Attachments& textures() const override
{
return m_attachments;
}
@ -841,9 +841,9 @@ namespace Blah
return TextureRef();
}
FrameBufferRef GraphicsBackend::create_framebuffer(int width, int height, const TextureFormat* attachments, int attachment_count)
TargetRef GraphicsBackend::create_target(int width, int height, const TextureFormat* attachments, int attachment_count)
{
return FrameBufferRef(new D3D11_FrameBuffer(width, height, attachments, attachment_count));
return TargetRef(new D3D11_Target(width, height, attachments, attachment_count));
}
ShaderRef GraphicsBackend::create_shader(const ShaderData* data)
@ -876,7 +876,7 @@ namespace Blah
}
else
{
auto target = (D3D11_FrameBuffer*)(pass.target.get());
auto target = (D3D11_Target*)(pass.target.get());
ctx->OMSetRenderTargets(target->color_views.size(), target->color_views.begin(), target->depth_view);
}

View File

@ -2,7 +2,7 @@
#include "../internal/graphics_backend.h"
#include "../internal/platform_backend.h"
#include <blah/core/common.h>
#include <blah/common.h>
namespace Blah
{
@ -56,14 +56,14 @@ namespace Blah
};
class Dummy_FrameBuffer : public FrameBuffer
class Dummy_Target : public Target
{
private:
Attachments m_attachments;
public:
Dummy_FrameBuffer(int width, int height, const TextureFormat* attachments, int attachmentCount)
Dummy_Target(int width, int height, const TextureFormat* attachments, int attachmentCount)
{
for (int i = 0; i < attachmentCount; i++)
{
@ -73,12 +73,12 @@ namespace Blah
}
}
virtual Attachments& attachments() override
virtual Attachments& textures() override
{
return m_attachments;
}
virtual const Attachments& attachments() const override
virtual const Attachments& textures() const override
{
return m_attachments;
}
@ -186,9 +186,9 @@ namespace Blah
return TextureRef(new Dummy_Texture(width, height, format, false));
}
FrameBufferRef GraphicsBackend::create_framebuffer(int width, int height, const TextureFormat* attachments, int attachmentCount)
TargetRef GraphicsBackend::create_target(int width, int height, const TextureFormat* attachments, int attachmentCount)
{
return FrameBufferRef(new Dummy_FrameBuffer(width, height, attachments, attachmentCount));
return TargetRef(new Dummy_Target(width, height, attachments, attachmentCount));
}
ShaderRef GraphicsBackend::create_shader(const ShaderData* data)

View File

@ -1,5 +1,5 @@
#pragma once
#include <blah/input/input.h>
#include <blah/input.h>
namespace Blah
{

View File

@ -1,6 +1,6 @@
#pragma once
#include <blah/core/common.h>
#include <blah/core/filesystem.h>
#include <blah/common.h>
#include <blah/filesystem.h>
#include <blah/containers/vector.h>
namespace Blah
@ -66,6 +66,9 @@ namespace Blah
// Returns the absolute path to the user directory where save data and settings should be stored
const char* user_path();
// Opens a file and sets the handle, or returns an empty handle if it fails
FileRef file_open(const char* path, FileMode mode);
// Returns true if a file with the given path exists
bool file_exists(const char* path);
@ -87,27 +90,6 @@ namespace Blah
// opens a directory in the OS file explorer / finder
void dir_explore(const char* path);
// Opens a file and sets the handle. returns true if the file was successfully opened
bool file_open(const char* path, FileHandle* handle, FileMode mode);
// Returns the length of the file
i64 file_length(FileHandle file);
// Returns the Position of the file
i64 file_position(FileHandle file);
// Seeks the Position of the file and returns the new position from the start of the file
i64 file_seek(FileHandle file, i64 seekTo);
// Reads a specific number of elements of a given size from the file into ptr
i64 file_read(FileHandle file, void* ptr, i64 size);
// Writes a specific number of elements of the given size from ptr to the file
i64 file_write(FileHandle file, const void* ptr, i64 size);
// Closes a file
void file_close(FileHandle file);
// OpenGL Methods
void* gl_get_func(const char* name);
void* gl_context_create();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +0,0 @@
#include <blah/math/stopwatch.h>
#include <chrono>
using namespace std::chrono;
using namespace Blah;
Stopwatch::Stopwatch()
{
reset();
}
void Stopwatch::reset()
{
start_time = std::chrono::duration_cast<std::chrono::microseconds>(system_clock::now().time_since_epoch()).count();
}
u64 Stopwatch::milliseconds()
{
return microseconds() / 1000;
}
u64 Stopwatch::microseconds()
{
return std::chrono::duration_cast<std::chrono::microseconds>(system_clock::now().time_since_epoch()).count() - start_time;
}

View File

@ -1,4 +1,4 @@
#include <blah/math/calc.h>
#include <blah/numerics/calc.h>
#include <cmath>
#include <cstdlib>

View File

@ -1,5 +1,5 @@
#include <blah/math/circle.h>
#include <blah/math/calc.h>
#include <blah/numerics/circle.h>
#include <blah/numerics/calc.h>
using namespace Blah;

View File

@ -1,6 +1,6 @@
#include <blah/math/color.h>
#include <blah/math/vec3.h>
#include <blah/math/vec4.h>
#include <blah/numerics/color.h>
#include <blah/numerics/vec3.h>
#include <blah/numerics/vec4.h>
using namespace Blah;

View File

@ -1,7 +1,7 @@
#include <blah/math/line.h>
#include <blah/math/rect.h>
#include <blah/math/vec2.h>
#include <blah/math/calc.h>
#include <blah/numerics/line.h>
#include <blah/numerics/rect.h>
#include <blah/numerics/vec2.h>
#include <blah/numerics/calc.h>
using namespace Blah;

View File

@ -1,7 +1,7 @@
#include <blah/math/mat3x2.h>
#include <blah/math/vec2.h>
#include <blah/numerics/mat3x2.h>
#include <blah/numerics/vec2.h>
#include <blah/numerics/calc.h>
#include <cstring>
#include <cmath>
using namespace Blah;
@ -132,8 +132,8 @@ Mat3x2 Mat3x2::create_scale(float scaleX, float scaleY, Vec2 centerPoint)
Mat3x2 Mat3x2::create_rotation(float radians)
{
float c = cosf(radians);
float s = sinf(radians);
float c = Calc::cos(radians);
float s = Calc::sin(radians);
return Mat3x2(c, s, -s, c, 0, 0);
}

View File

@ -1,5 +1,5 @@
#include <blah/math/mat4x4.h>
#include <blah/core/common.h>
#include <blah/numerics/mat4x4.h>
#include <blah/common.h>
using namespace Blah;

View File

@ -1,6 +1,6 @@
#include <blah/math/vec2.h>
#include <blah/math/mat3x2.h>
#include <math.h>
#include <blah/numerics/vec2.h>
#include <blah/numerics/mat3x2.h>
#include <blah/numerics/calc.h>
using namespace Blah;
@ -33,7 +33,7 @@ bool Point::operator !=(const Point& rhs) { return x != rhs.x || y != rhs.y; }
float Point::length() const
{
return sqrtf((float)(x * x + y * y));
return Calc::sqrt((float)(x * x + y * y));
}
int Point::length_squared() const

View File

@ -1,5 +1,5 @@
#include <blah/math/quad.h>
#include <blah/math/calc.h>
#include <blah/numerics/quad.h>
#include <blah/numerics/calc.h>
namespace Blah
{

View File

@ -1,9 +1,9 @@
#include <blah/math/rect.h>
#include <blah/math/point.h>
#include <blah/math/rectI.h>
#include <blah/math/vec2.h>
#include <blah/math/calc.h>
#include <blah/math/mat3x2.h>
#include <blah/numerics/rect.h>
#include <blah/numerics/point.h>
#include <blah/numerics/rectI.h>
#include <blah/numerics/vec2.h>
#include <blah/numerics/calc.h>
#include <blah/numerics/mat3x2.h>
using namespace Blah;

View File

@ -1,8 +1,8 @@
#include <blah/math/rectI.h>
#include <blah/math/rect.h>
#include <blah/math/point.h>
#include <blah/math/vec2.h>
#include <blah/math/calc.h>
#include <blah/numerics/rectI.h>
#include <blah/numerics/rect.h>
#include <blah/numerics/point.h>
#include <blah/numerics/vec2.h>
#include <blah/numerics/calc.h>
using namespace Blah;

View File

@ -1,7 +1,6 @@
#include <blah/math/vec2.h>
#include <blah/math/mat3x2.h>
#include <blah/math/calc.h>
#include <math.h>
#include <blah/numerics/vec2.h>
#include <blah/numerics/mat3x2.h>
#include <blah/numerics/calc.h>
using namespace Blah;

View File

@ -42,7 +42,7 @@ BufferStream::~BufferStream()
delete[] m_buffer;
}
i64 BufferStream::read_into(void* ptr, i64 len)
size_t BufferStream::read_into(void* ptr, size_t len)
{
if (m_buffer == nullptr || ptr == nullptr)
return 0;
@ -58,7 +58,7 @@ i64 BufferStream::read_into(void* ptr, i64 len)
return len;
}
i64 BufferStream::write_from(const void* ptr, i64 len)
size_t BufferStream::write_from(const void* ptr, size_t len)
{
if (len < 0)
return 0;
@ -78,7 +78,7 @@ i64 BufferStream::write_from(const void* ptr, i64 len)
return len;
}
void BufferStream::resize(i64 length)
void BufferStream::resize(size_t length)
{
if (m_capacity > length)
{

View File

@ -1,5 +1,5 @@
#include <blah/streams/filestream.h>
#include <blah/core/common.h>
#include <blah/common.h>
#include "../internal/platform_backend.h"
#include <cstring>
@ -7,105 +7,90 @@ using namespace Blah;
FileStream::FileStream()
{
m_handle = nullptr;
m_mode = FileMode::OpenRead;
}
FileStream::FileStream(const FilePath& path, FileMode mode)
: m_mode(mode)
, m_file(File::open(path, mode))
{
if (!PlatformBackend::file_open(path, &m_handle, mode))
m_handle = nullptr;
}
FileStream::FileStream(FileStream&& src) noexcept
{
m_handle = src.m_handle;
m_file = src.m_file;
m_mode = src.m_mode;
src.m_handle = nullptr;
}
FileStream& FileStream::operator=(FileStream&& src) noexcept
{
m_handle = src.m_handle;
m_file = src.m_file;
m_mode = src.m_mode;
src.m_handle = nullptr;
return *this;
}
FileStream::~FileStream()
size_t FileStream::length() const
{
if (m_handle != nullptr)
PlatformBackend::file_close(m_handle);
if (m_file)
return m_file->length();
return 0;
}
i64 FileStream::length() const
size_t FileStream::position() const
{
if (m_handle == nullptr)
return 0;
return PlatformBackend::file_length(m_handle);
if (m_file)
return m_file->position();
return 0;
}
i64 FileStream::position() const
size_t FileStream::seek(size_t seek_to)
{
if (m_handle == nullptr)
return 0;
return PlatformBackend::file_position(m_handle);
}
i64 FileStream::seek(i64 seek_to)
{
if (m_handle == nullptr)
return 0;
return PlatformBackend::file_seek(m_handle, seek_to);
if (m_file)
return m_file->seek(seek_to);
return 0;
}
bool FileStream::is_open() const
{
return m_handle != nullptr;
return m_file.get();
}
bool FileStream::is_readable() const
{
return m_handle != nullptr && (m_mode != FileMode::CreateWrite);
return m_file.get() && (m_mode != FileMode::CreateWrite);
}
bool FileStream::is_writable() const
{
return m_handle != nullptr && (m_mode != FileMode::OpenRead);
return m_file.get() && (m_mode != FileMode::OpenRead);
}
i64 FileStream::read_into(void* ptr, i64 length)
{
if (m_handle == nullptr)
{
BLAH_ERROR("Unable to read from Stream");
return 0;
}
return PlatformBackend::file_read(m_handle, ptr, length);
}
i64 FileStream::write_from(const void* ptr, i64 length)
size_t FileStream::read_into(void* ptr, size_t length)
{
if (length <= 0)
return 0;
if (m_handle == nullptr)
{
BLAH_ERROR("Unable to write to Stream");
return 0;
}
if (m_file)
return m_file->read((unsigned char*)ptr, length);
return PlatformBackend::file_write(m_handle, ptr, length);
BLAH_ASSERT(false, "Unable to read from Stream");
return 0;
}
size_t FileStream::write_from(const void* ptr, size_t length)
{
if (length <= 0)
return 0;
if (m_file)
return m_file->write((const unsigned char*)ptr, length);
BLAH_ASSERT(false, "Unable to write to Stream");
return 0;
}
void FileStream::close()
{
if (m_handle != nullptr)
PlatformBackend::file_close(m_handle);
m_handle = nullptr;
m_file.reset();
}

View File

@ -6,7 +6,7 @@ using namespace Blah;
MemoryStream::MemoryStream()
: m_data(nullptr), m_length(0), m_position(0) {}
MemoryStream::MemoryStream(char* data, i64 length)
MemoryStream::MemoryStream(char* data, size_t length)
: m_data(data), m_length(length), m_position(0) {}
MemoryStream::MemoryStream(MemoryStream&& src) noexcept
@ -28,7 +28,7 @@ MemoryStream& MemoryStream::operator=(MemoryStream&& src) noexcept
return *this;
}
i64 MemoryStream::read_into(void* ptr, i64 len)
size_t MemoryStream::read_into(void* ptr, size_t len)
{
if (len < 0 || ptr == nullptr)
return 0;
@ -41,7 +41,7 @@ i64 MemoryStream::read_into(void* ptr, i64 len)
return len;
}
i64 MemoryStream::write_from(const void* ptr, i64 len)
size_t MemoryStream::write_from(const void* ptr, size_t len)
{
if (len < 0 || ptr == nullptr)
return 0;

View File

@ -4,10 +4,10 @@
using namespace Blah;
i64 Stream::pipe(Stream& stream, i64 length)
size_t Stream::pipe(Stream& stream, size_t length)
{
const int BUFFER_LENGTH = 4096;
i64 result = 0;
size_t result = 0;
char buffer[BUFFER_LENGTH];
while (length > 0)
@ -59,12 +59,12 @@ String Stream::read_line()
return result;
}
i64 Stream::write(const void* buffer, i64 length)
size_t Stream::write(const void* buffer, size_t length)
{
return write_from(buffer, length);
}
i64 Stream::write(const String& string)
size_t Stream::write(const String& string)
{
return write_from(string.begin(), string.length());
}

View File

@ -1,14 +1,8 @@
#include <blah/core/time.h>
#include <blah/time.h>
#include <chrono>
using namespace Blah;
namespace
{
double modf(double x, double m)
{
return x - (int)(x / m) * m;
}
}
using namespace std::chrono;
u64 Time::ticks = 0;
u64 Time::previous_ticks = 0;
@ -48,6 +42,11 @@ bool Time::on_time(double time, double timestamp)
bool Time::between_interval(double time, float interval, float offset)
{
static const auto modf = [](double x, double m)
{
return x - (int)(x / m) * m;
};
return modf(time - offset, ((double)interval) * 2) >= interval;
}
@ -55,3 +54,23 @@ bool Time::between_interval(float interval, float offset)
{
return between_interval(Time::seconds, interval, offset);
}
Stopwatch::Stopwatch()
{
reset();
}
void Stopwatch::reset()
{
start_time = std::chrono::duration_cast<std::chrono::microseconds>(system_clock::now().time_since_epoch()).count();
}
u64 Stopwatch::milliseconds()
{
return microseconds() / 1000;
}
u64 Stopwatch::microseconds()
{
return std::chrono::duration_cast<std::chrono::microseconds>(system_clock::now().time_since_epoch()).count() - start_time;
}