mirror of
				https://github.com/NoelFB/blah.git
				synced 2025-11-04 01:41:34 +08:00 
			
		
		
		
	large spatial / numerics refactor to allow double/integer vector types
This commit is contained in:
		@ -1,7 +1,6 @@
 | 
			
		||||
#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.h"
 | 
			
		||||
#include "internal/graphics.h"
 | 
			
		||||
@ -142,6 +141,10 @@ bool App::run(const Config* c)
 | 
			
		||||
	// input
 | 
			
		||||
	Input::init();
 | 
			
		||||
 | 
			
		||||
	// prepare by updating input & platform once
 | 
			
		||||
	Input::update_state();
 | 
			
		||||
	Platform::update(Input::state);
 | 
			
		||||
 | 
			
		||||
	// startup
 | 
			
		||||
	if (app_config.on_startup != nullptr)
 | 
			
		||||
		app_config.on_startup();
 | 
			
		||||
 | 
			
		||||
@ -218,7 +218,7 @@ Str& Str::append_utf16(const u16* start, const u16* end, bool swap_endian)
 | 
			
		||||
	const u16 surrogate_min = 0xd800u;
 | 
			
		||||
	const u16 surrogate_max = 0xdbffu;
 | 
			
		||||
 | 
			
		||||
	while (start != end)
 | 
			
		||||
	while ((end == nullptr && *start != 0) || (end != nullptr && start != end))
 | 
			
		||||
	{
 | 
			
		||||
		u16 next = (*start++);
 | 
			
		||||
		if (swap_endian)
 | 
			
		||||
 | 
			
		||||
@ -128,25 +128,22 @@ namespace
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
	static Vec2 batch_shape_intersection(const Vec2& p0, const Vec2& p1, const Vec2& q0, const Vec2& q1)
 | 
			
		||||
	static Vec2f batch_shape_intersection(const Vec2f& p0, const Vec2f& p1, const Vec2f& q0, const Vec2f& q1)
 | 
			
		||||
	{
 | 
			
		||||
		const auto aa = p1 - p0;
 | 
			
		||||
		const auto bb = q0 - q1;
 | 
			
		||||
		const auto cc = q0 - p0;
 | 
			
		||||
		const auto t = (bb.x * cc.y - bb.y * cc.x) / (aa.y * bb.x - aa.x * bb.y);
 | 
			
		||||
 | 
			
		||||
		return Vec2(p0.x + t * (p1.x - p0.x), p0.y + t * (p1.y - p0.y));
 | 
			
		||||
		return Vec2f(p0.x + t * (p1.x - p0.x), p0.y + t * (p1.y - p0.y));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MAKE_VERTEX(vert, mat, px, py, tx, ty, c, m, w, f) \
 | 
			
		||||
	(vert)->pos.x = ((px) * (mat).m11) + ((py) * (mat).m21) + (mat).m31; \
 | 
			
		||||
	(vert)->pos.y = ((px) * (mat).m12) + ((py) * (mat).m22) + (mat).m32; \
 | 
			
		||||
	(vert)->tex.x = tx;  \
 | 
			
		||||
	if (m_batch.flip_vertically) \
 | 
			
		||||
		(vert)->tex.y = 1.0f - (ty); \
 | 
			
		||||
	else \
 | 
			
		||||
		(vert)->tex.y = ty; \
 | 
			
		||||
#define MAKE_VERTEX(vert, mat, px, py, tx, ty, c, m, w, f, cast) \
 | 
			
		||||
	(vert)->pos.x = cast(((px) * (mat).m11) + ((py) * (mat).m21) + (mat).m31); \
 | 
			
		||||
	(vert)->pos.y = cast(((px) * (mat).m12) + ((py) * (mat).m22) + (mat).m32); \
 | 
			
		||||
	(vert)->tex.x = (tx); \
 | 
			
		||||
	(vert)->tex.y = m_batch.flip_vertically ? 1.0f - (ty) : (ty); \
 | 
			
		||||
	(vert)->col = c; \
 | 
			
		||||
	(vert)->mult = m; \
 | 
			
		||||
	(vert)->wash = w; \
 | 
			
		||||
@ -163,10 +160,17 @@ namespace
 | 
			
		||||
		*_i++ = (u32)m_vertices.size() + 2; \
 | 
			
		||||
		*_i++ = (u32)m_vertices.size() + 3; \
 | 
			
		||||
		Vertex* _v = m_vertices.expand(4); \
 | 
			
		||||
		MAKE_VERTEX(_v, m_matrix, px0, py0, tx0, ty0, col0, mult, fill, wash); _v++; \
 | 
			
		||||
		MAKE_VERTEX(_v, m_matrix, px1, py1, tx1, ty1, col1, mult, fill, wash); _v++; \
 | 
			
		||||
		MAKE_VERTEX(_v, m_matrix, px2, py2, tx2, ty2, col2, mult, fill, wash); _v++; \
 | 
			
		||||
		MAKE_VERTEX(_v, m_matrix, px3, py3, tx3, ty3, col3, mult, fill, wash); \
 | 
			
		||||
		if (integerize) { \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px0, py0, tx0, ty0, col0, mult, fill, wash, std::round); _v++; \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px1, py1, tx1, ty1, col1, mult, fill, wash, std::round); _v++; \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px2, py2, tx2, ty2, col2, mult, fill, wash, std::round); _v++; \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px3, py3, tx3, ty3, col3, mult, fill, wash, std::round); \
 | 
			
		||||
		} else { \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px0, py0, tx0, ty0, col0, mult, fill, wash, float); _v++; \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px1, py1, tx1, ty1, col1, mult, fill, wash, float); _v++; \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px2, py2, tx2, ty2, col2, mult, fill, wash, float); _v++; \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px3, py3, tx3, ty3, col3, mult, fill, wash, float); \
 | 
			
		||||
		} \
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#define PUSH_TRIANGLE(px0, py0, px1, py1, px2, py2, tx0, ty0, tx1, ty1, tx2, ty2, col0, col1, col2, mult, fill, wash) \
 | 
			
		||||
@ -177,9 +181,15 @@ namespace
 | 
			
		||||
		*_i++ = (u32)m_vertices.size() + 1; \
 | 
			
		||||
		*_i++ = (u32)m_vertices.size() + 2; \
 | 
			
		||||
		Vertex* _v = m_vertices.expand(3); \
 | 
			
		||||
		MAKE_VERTEX(_v, m_matrix, px0, py0, tx0, ty0, col0, mult, fill, wash); _v++; \
 | 
			
		||||
		MAKE_VERTEX(_v, m_matrix, px1, py1, tx1, ty1, col1, mult, fill, wash); _v++; \
 | 
			
		||||
		MAKE_VERTEX(_v, m_matrix, px2, py2, tx2, ty2, col2, mult, fill, wash); \
 | 
			
		||||
		if (integerize) { \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px0, py0, tx0, ty0, col0, mult, fill, wash, std::floor); _v++; \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px1, py1, tx1, ty1, col1, mult, fill, wash, std::floor); _v++; \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px2, py2, tx2, ty2, col2, mult, fill, wash, std::floor); \
 | 
			
		||||
		} else { \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px0, py0, tx0, ty0, col0, mult, fill, wash, float); _v++; \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px1, py1, tx1, ty1, col1, mult, fill, wash, float); _v++; \
 | 
			
		||||
			MAKE_VERTEX(_v, m_matrix, px2, py2, tx2, ty2, col2, mult, fill, wash, float); \
 | 
			
		||||
		} \
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#define INSERT_BATCH() \
 | 
			
		||||
@ -213,7 +223,7 @@ Batch::~Batch()
 | 
			
		||||
	dispose();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::push_matrix(const Mat3x2& matrix, bool absolute)
 | 
			
		||||
void Batch::push_matrix(const Mat3x2f& matrix, bool absolute)
 | 
			
		||||
{
 | 
			
		||||
	m_matrix_stack.push_back(m_matrix);
 | 
			
		||||
	if (absolute)
 | 
			
		||||
@ -222,33 +232,33 @@ void Batch::push_matrix(const Mat3x2& matrix, bool absolute)
 | 
			
		||||
		m_matrix = matrix * m_matrix;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat3x2 Batch::pop_matrix()
 | 
			
		||||
Mat3x2f Batch::pop_matrix()
 | 
			
		||||
{
 | 
			
		||||
	auto was = m_matrix;
 | 
			
		||||
	m_matrix = m_matrix_stack.pop();
 | 
			
		||||
	return was;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat3x2 Batch::peek_matrix() const
 | 
			
		||||
Mat3x2f Batch::peek_matrix() const
 | 
			
		||||
{
 | 
			
		||||
	return m_matrix;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::push_scissor(const Rect& scissor)
 | 
			
		||||
void Batch::push_scissor(const Rectf& scissor)
 | 
			
		||||
{
 | 
			
		||||
	m_scissor_stack.push_back(m_batch.scissor);
 | 
			
		||||
	SET_BATCH_VAR(scissor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Rect Batch::pop_scissor()
 | 
			
		||||
Rectf Batch::pop_scissor()
 | 
			
		||||
{
 | 
			
		||||
	Rect was = m_batch.scissor;
 | 
			
		||||
	Rect scissor = m_scissor_stack.pop();
 | 
			
		||||
	Rectf was = m_batch.scissor;
 | 
			
		||||
	Rectf scissor = m_scissor_stack.pop();
 | 
			
		||||
	SET_BATCH_VAR(scissor);
 | 
			
		||||
	return was;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Rect Batch::peek_scissor() const
 | 
			
		||||
Rectf Batch::peek_scissor() const
 | 
			
		||||
{
 | 
			
		||||
	return m_batch.scissor;
 | 
			
		||||
}
 | 
			
		||||
@ -388,10 +398,10 @@ void Batch::render(const TargetRef& target)
 | 
			
		||||
	else
 | 
			
		||||
		size = Point(target->width(), target->height());
 | 
			
		||||
 | 
			
		||||
	render(target, Mat4x4::create_ortho_offcenter(0, (float)size.x, (float)size.y, 0, 0.01f, 1000.0f));
 | 
			
		||||
	render(target, Mat4x4f::create_ortho_offcenter(0, (float)size.x, (float)size.y, 0, 0.01f, 1000.0f));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::render(const TargetRef& target, const Mat4x4& matrix)
 | 
			
		||||
void Batch::render(const TargetRef& target, const Mat4x4f& matrix)
 | 
			
		||||
{
 | 
			
		||||
	// nothing to draw
 | 
			
		||||
	if ((m_batches.size() <= 0 && m_batch.elements <= 0) || m_indices.size() <= 0)
 | 
			
		||||
@ -422,7 +432,7 @@ void Batch::render(const TargetRef& target, const Mat4x4& matrix)
 | 
			
		||||
	pass.target = target;
 | 
			
		||||
	pass.mesh = m_mesh;
 | 
			
		||||
	pass.has_viewport = false;
 | 
			
		||||
	pass.viewport = Rect();
 | 
			
		||||
	pass.viewport = Rectf();
 | 
			
		||||
	pass.instance_count = 0;
 | 
			
		||||
	pass.depth = Compare::None;
 | 
			
		||||
	pass.cull = Cull::None;
 | 
			
		||||
@ -443,7 +453,7 @@ void Batch::render(const TargetRef& target, const Mat4x4& matrix)
 | 
			
		||||
		render_single_batch(pass, m_batch, matrix);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::render_single_batch(RenderPass& pass, const DrawBatch& b, const Mat4x4& matrix)
 | 
			
		||||
void Batch::render_single_batch(RenderPass& pass, const DrawBatch& b, const Mat4x4f& matrix)
 | 
			
		||||
{
 | 
			
		||||
	// get the material
 | 
			
		||||
	pass.material = b.material;
 | 
			
		||||
@ -462,7 +472,7 @@ void Batch::render_single_batch(RenderPass& pass, const DrawBatch& b, const Mat4
 | 
			
		||||
		pass.material->set_sampler(0, b.sampler);
 | 
			
		||||
 | 
			
		||||
	// assign the matrix uniform
 | 
			
		||||
	pass.material->set_value(matrix_uniform, &matrix.m11, 16);
 | 
			
		||||
	pass.material->set_value(matrix_uniform, matrix);
 | 
			
		||||
	
 | 
			
		||||
	pass.blend = b.blend;
 | 
			
		||||
	pass.has_scissor = b.scissor.w >= 0 && b.scissor.h >= 0;
 | 
			
		||||
@ -475,7 +485,7 @@ void Batch::render_single_batch(RenderPass& pass, const DrawBatch& b, const Mat4
 | 
			
		||||
 | 
			
		||||
void Batch::clear()
 | 
			
		||||
{
 | 
			
		||||
	m_matrix = Mat3x2::identity;
 | 
			
		||||
	m_matrix = Mat3x2f::identity;
 | 
			
		||||
	m_color_mode = ColorMode::Normal;
 | 
			
		||||
	m_tex_mult = 255;
 | 
			
		||||
	m_tex_wash = 0;
 | 
			
		||||
@ -522,22 +532,22 @@ void Batch::dispose()
 | 
			
		||||
	m_mesh.reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::line(const Vec2& from, const Vec2& to, float t, Color color)
 | 
			
		||||
void Batch::line(const Vec2f& from, const Vec2f& to, float t, Color color)
 | 
			
		||||
{
 | 
			
		||||
	line(from, to, t, color, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::line(const Vec2& from, const Vec2& to, float t, Color fromColor, Color toColor)
 | 
			
		||||
void Batch::line(const Vec2f& from, const Vec2f& to, float t, Color fromColor, Color toColor)
 | 
			
		||||
{
 | 
			
		||||
	if (from.x == to.x && from.y == to.y)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	Vec2 normal = (to - from).normal();
 | 
			
		||||
	Vec2 perp = Vec2(normal.y, -normal.x);
 | 
			
		||||
	Vec2 pos0 = from + perp * t * 0.5f;
 | 
			
		||||
	Vec2 pos1 = to + perp * t * 0.5f;
 | 
			
		||||
	Vec2 pos2 = to - perp * t * 0.5f;
 | 
			
		||||
	Vec2 pos3 = from - perp * t * 0.5f;
 | 
			
		||||
	Vec2f normal = (to - from).normal();
 | 
			
		||||
	Vec2f perp = Vec2f(normal.y, -normal.x);
 | 
			
		||||
	Vec2f pos0 = from + perp * t * 0.5f;
 | 
			
		||||
	Vec2f pos1 = to + perp * t * 0.5f;
 | 
			
		||||
	Vec2f pos2 = to - perp * t * 0.5f;
 | 
			
		||||
	Vec2f pos3 = from - perp * t * 0.5f;
 | 
			
		||||
 | 
			
		||||
	PUSH_QUAD(
 | 
			
		||||
		pos0.x, pos0.y, pos1.x, pos1.y, pos2.x, pos2.y, pos3.x, pos3.y,
 | 
			
		||||
@ -546,14 +556,14 @@ void Batch::line(const Vec2& from, const Vec2& to, float t, Color fromColor, Col
 | 
			
		||||
		0, 0, 255);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::bezier_line(const Vec2& from, const Vec2& b, const Vec2& to, int steps, float t, Color color)
 | 
			
		||||
void Batch::bezier_line(const Vec2f& from, const Vec2f& b, const Vec2f& to, int steps, float t, Color color)
 | 
			
		||||
{
 | 
			
		||||
	Vec2 prev = from;
 | 
			
		||||
	Vec2f prev = from;
 | 
			
		||||
	float add = 1.0f / steps;
 | 
			
		||||
 | 
			
		||||
	for (int i = 1; i < steps; i++)
 | 
			
		||||
	{
 | 
			
		||||
		Vec2 at = Vec2::lerp_bezier(from, b, to, add * i);
 | 
			
		||||
		Vec2f at = Vec2f::lerp_bezier(from, b, to, add * i);
 | 
			
		||||
		line(prev, at, t, color);
 | 
			
		||||
		prev = at;
 | 
			
		||||
	}
 | 
			
		||||
@ -561,14 +571,14 @@ void Batch::bezier_line(const Vec2& from, const Vec2& b, const Vec2& to, int ste
 | 
			
		||||
	line(prev, to, t, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::bezier_line(const Vec2& from, const Vec2& b, const Vec2& c, const Vec2& to, int steps, float t, Color color)
 | 
			
		||||
void Batch::bezier_line(const Vec2f& from, const Vec2f& b, const Vec2f& c, const Vec2f& to, int steps, float t, Color color)
 | 
			
		||||
{
 | 
			
		||||
	Vec2 prev = from;
 | 
			
		||||
	Vec2f prev = from;
 | 
			
		||||
	float add = 1.0f / steps;
 | 
			
		||||
 | 
			
		||||
	for (int i = 1; i < steps; i++)
 | 
			
		||||
	{
 | 
			
		||||
		Vec2 at = Vec2::lerp_bezier(from, b, c, to, add * i);
 | 
			
		||||
		Vec2f at = Vec2f::lerp_bezier(from, b, c, to, add * i);
 | 
			
		||||
		line(prev, at, t, color);
 | 
			
		||||
		prev = at;
 | 
			
		||||
	}
 | 
			
		||||
@ -576,7 +586,7 @@ void Batch::bezier_line(const Vec2& from, const Vec2& b, const Vec2& c, const Ve
 | 
			
		||||
	line(prev, to, t, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::tri(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, Color color)
 | 
			
		||||
void Batch::tri(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, Color color)
 | 
			
		||||
{
 | 
			
		||||
	PUSH_TRIANGLE(
 | 
			
		||||
		pos0.x, pos0.y, pos1.x, pos1.y, pos2.x, pos2.y,
 | 
			
		||||
@ -585,7 +595,7 @@ void Batch::tri(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, Color colo
 | 
			
		||||
		0, 0, 255);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::tri(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, Color col0, Color col1, Color col2)
 | 
			
		||||
void Batch::tri(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, Color col0, Color col1, Color col2)
 | 
			
		||||
{
 | 
			
		||||
	PUSH_TRIANGLE(
 | 
			
		||||
		pos0.x, pos0.y, pos1.x, pos1.y, pos2.x, pos2.y,
 | 
			
		||||
@ -594,7 +604,7 @@ void Batch::tri(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, Color col0
 | 
			
		||||
		0, 0, 255);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::tri(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec2& tex0, const Vec2& tex1, const Vec2& tex2, Color color)
 | 
			
		||||
void Batch::tri(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, const Vec2f& tex0, const Vec2f& tex1, const Vec2f& tex2, Color color)
 | 
			
		||||
{
 | 
			
		||||
	PUSH_TRIANGLE(
 | 
			
		||||
		pos0.x, pos0.y, pos1.x, pos1.y, pos2.x, pos2.y,
 | 
			
		||||
@ -603,7 +613,7 @@ void Batch::tri(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec2
 | 
			
		||||
		m_tex_mult, m_tex_wash, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::tri(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec2& tex0, const Vec2& tex1, const Vec2& tex2, Color col0, Color col1, Color col2)
 | 
			
		||||
void Batch::tri(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, const Vec2f& tex0, const Vec2f& tex1, const Vec2f& tex2, Color col0, Color col1, Color col2)
 | 
			
		||||
{
 | 
			
		||||
	PUSH_TRIANGLE(
 | 
			
		||||
		pos0.x, pos0.y, pos1.x, pos1.y, pos2.x, pos2.y,
 | 
			
		||||
@ -612,7 +622,7 @@ void Batch::tri(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec2
 | 
			
		||||
		m_tex_mult, m_tex_wash, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::tri_line(const Vec2& a, const Vec2& b, const Vec2& c, float t, Color color)
 | 
			
		||||
void Batch::tri_line(const Vec2f& a, const Vec2f& b, const Vec2f& c, float t, Color color)
 | 
			
		||||
{
 | 
			
		||||
	// TODO:
 | 
			
		||||
	// Detect if the thickness of the line fills the entire shape
 | 
			
		||||
@ -635,7 +645,7 @@ void Batch::tri_line(const Vec2& a, const Vec2& b, const Vec2& c, float t, Color
 | 
			
		||||
	quad(cc, c, a, aa, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::rect(const Rect& rect, Color color)
 | 
			
		||||
void Batch::rect(const Rectf& rect, Color color)
 | 
			
		||||
{
 | 
			
		||||
	PUSH_QUAD(
 | 
			
		||||
		rect.x, rect.y,
 | 
			
		||||
@ -647,7 +657,7 @@ void Batch::rect(const Rect& rect, Color color)
 | 
			
		||||
		0, 0, 255);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::rect_line(const Rect& rect, float t, Color color)
 | 
			
		||||
void Batch::rect_line(const Rectf& rect, float t, Color color)
 | 
			
		||||
{
 | 
			
		||||
	if (t >= rect.w || t >= rect.h)
 | 
			
		||||
	{
 | 
			
		||||
@ -693,12 +703,12 @@ void Batch::rect_line(const Rect& rect, float t, Color color)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::rect_rounded(const Rect& rect, float radius, int steps, Color color)
 | 
			
		||||
void Batch::rect_rounded(const Rectf& rect, float radius, int steps, Color color)
 | 
			
		||||
{
 | 
			
		||||
	rect_rounded(rect, radius, steps, radius, steps, radius, steps, radius, steps, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::rect_rounded(const Rect& rect, float rtl, int rtl_steps, float rtr, int rtr_steps, float rbr, int rbr_steps, float rbl, int rbl_steps, Color color)
 | 
			
		||||
void Batch::rect_rounded(const Rectf& rect, float rtl, int rtl_steps, float rtr, int rtr_steps, float rbr, int rbr_steps, float rbl, int rbl_steps, Color color)
 | 
			
		||||
{
 | 
			
		||||
	// clamp
 | 
			
		||||
	rtl = Calc::min(Calc::min(Calc::max(0.0f, rtl), rect.w / 2.0f), rect.h / 2.0f);
 | 
			
		||||
@ -713,10 +723,10 @@ void Batch::rect_rounded(const Rect& rect, float rtl, int rtl_steps, float rtr,
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		// get corners
 | 
			
		||||
		Rect tl = Rect(rect.top_left(), Vec2(rtl, rtl));
 | 
			
		||||
		Rect tr = Rect(rect.top_right() + Vec2(-rtr, 0.0f), Vec2(rtr, rtr));
 | 
			
		||||
		Rect bl = Rect(rect.bottom_left() + Vec2(0.0f, -rbl), Vec2(rbl, rbl));
 | 
			
		||||
		Rect br = Rect(rect.bottom_right() + Vec2(-rbr, -rbr), Vec2(rbr, rbr));
 | 
			
		||||
		Rectf tl = Rectf(rect.x, rect.y, rtl, rtl);
 | 
			
		||||
		Rectf tr = Rectf(rect.x + rect.w - rtr, rect.y, rtr, rtr);
 | 
			
		||||
		Rectf bl = Rectf(rect.x, rect.y + rect.h - rbl, rbl, rbl);
 | 
			
		||||
		Rectf br = Rectf(rect.x + rect.w - rbr, rect.y + rect.h - rbr, rbr, rbr);
 | 
			
		||||
 | 
			
		||||
		// rounded corners
 | 
			
		||||
		semi_circle(tl.bottom_right(), Calc::UP, Calc::LEFT, rtl, rtl_steps, color);
 | 
			
		||||
@ -733,12 +743,12 @@ void Batch::rect_rounded(const Rect& rect, float rtl, int rtl_steps, float rtr,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::rect_rounded_line(const Rect & rect, float radius, int steps, float t, Color color)
 | 
			
		||||
void Batch::rect_rounded_line(const Rectf & rect, float radius, int steps, float t, Color color)
 | 
			
		||||
{
 | 
			
		||||
	rect_rounded_line(rect, radius, steps, radius, steps, radius, steps, radius, steps, t, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::rect_rounded_line(const Rect& r, float rtl, int rtl_steps, float rtr, int rtr_steps, float rbr, int rbr_steps, float rbl, int rbl_steps, float t, Color color)
 | 
			
		||||
void Batch::rect_rounded_line(const Rectf& r, float rtl, int rtl_steps, float rtr, int rtr_steps, float rbr, int rbr_steps, float rbl, int rbl_steps, float t, Color color)
 | 
			
		||||
{
 | 
			
		||||
	// clamp
 | 
			
		||||
	rtl = Calc::min(Calc::min(Calc::max(0.0f, rtl), r.w / 2.0f), r.h / 2.0f);
 | 
			
		||||
@ -753,42 +763,42 @@ void Batch::rect_rounded_line(const Rect& r, float rtl, int rtl_steps, float rtr
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		// rounded corners
 | 
			
		||||
		semi_circle_line(Vec2(r.x + rtl, r.y + rtl), Calc::UP, Calc::LEFT, rtl, rtl_steps, t, color);
 | 
			
		||||
		semi_circle_line(Vec2(r.x + r.w - rtr, r.y + rtr), Calc::UP, Calc::UP + Calc::TAU * 0.25f, rtr, rtr_steps, t, color);
 | 
			
		||||
		semi_circle_line(Vec2(r.x + rbl, r.y + r.h - rbl), Calc::DOWN, Calc::LEFT, rbl, rbl_steps, t, color);
 | 
			
		||||
		semi_circle_line(Vec2(r.x + r.w - rbr, r.y + r.h - rbr), Calc::DOWN, Calc::RIGHT, rbr, rbr_steps, t, color);
 | 
			
		||||
		semi_circle_line(Vec2f(r.x + rtl, r.y + rtl), Calc::UP, Calc::LEFT, rtl, rtl_steps, t, color);
 | 
			
		||||
		semi_circle_line(Vec2f(r.x + r.w - rtr, r.y + rtr), Calc::UP, Calc::UP + Calc::TAU * 0.25f, rtr, rtr_steps, t, color);
 | 
			
		||||
		semi_circle_line(Vec2f(r.x + rbl, r.y + r.h - rbl), Calc::DOWN, Calc::LEFT, rbl, rbl_steps, t, color);
 | 
			
		||||
		semi_circle_line(Vec2f(r.x + r.w - rbr, r.y + r.h - rbr), Calc::DOWN, Calc::RIGHT, rbr, rbr_steps, t, color);
 | 
			
		||||
 | 
			
		||||
		// connect sides that aren't touching
 | 
			
		||||
		if (r.h > rtl + rbl)
 | 
			
		||||
			rect(Rect(r.x, r.y + rtl, t, r.h - rtl - rbl), color);
 | 
			
		||||
			rect(Rectf(r.x, r.y + rtl, t, r.h - rtl - rbl), color);
 | 
			
		||||
		if (r.h > rtr + rbr)
 | 
			
		||||
			rect(Rect(r.x + r.w - t, r.y + rtr, t, r.h - rtr - rbr), color);
 | 
			
		||||
			rect(Rectf(r.x + r.w - t, r.y + rtr, t, r.h - rtr - rbr), color);
 | 
			
		||||
		if (r.w > rtl + rtr)
 | 
			
		||||
			rect(Rect(r.x + rtl, r.y, r.w - rtl - rtr, t), color);
 | 
			
		||||
			rect(Rectf(r.x + rtl, r.y, r.w - rtl - rtr, t), color);
 | 
			
		||||
		if (r.w > rbl + rbr)
 | 
			
		||||
			rect(Rect(r.x + rbl, r.y + r.h - t, r.w - rbl - rbr, t), color);
 | 
			
		||||
			rect(Rectf(r.x + rbl, r.y + r.h - t, r.w - rbl - rbr, t), color);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::semi_circle(const Vec2& center, float start_radians, float end_radians, float radius, int steps, Color centerColor, Color edgeColor)
 | 
			
		||||
void Batch::semi_circle(const Vec2f& center, float start_radians, float end_radians, float radius, int steps, Color centerColor, Color edgeColor)
 | 
			
		||||
{
 | 
			
		||||
	Vec2 last = Vec2::from_angle(start_radians, radius);
 | 
			
		||||
	Vec2f last = Vec2f::from_angle(start_radians, radius);
 | 
			
		||||
	float add = Calc::angle_diff(start_radians, end_radians);
 | 
			
		||||
 | 
			
		||||
	for (int i = 1; i <= steps; i++)
 | 
			
		||||
	{
 | 
			
		||||
		Vec2 next = Vec2::from_angle(start_radians + add * (i / (float)steps), radius);
 | 
			
		||||
		Vec2f next = Vec2f::from_angle(start_radians + add * (i / (float)steps), radius);
 | 
			
		||||
		tri(center + last, center + next, center, edgeColor, edgeColor, centerColor);
 | 
			
		||||
		last = next;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::semi_circle(const Vec2& center, float start_radians, float end_radians, float radius, int steps, Color color)
 | 
			
		||||
void Batch::semi_circle(const Vec2f& center, float start_radians, float end_radians, float radius, int steps, Color color)
 | 
			
		||||
{
 | 
			
		||||
	semi_circle(center, start_radians, end_radians, radius, steps, color, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::semi_circle_line(const Vec2& center, float start_radians, float end_radians, float radius, int steps, float t, Color color)
 | 
			
		||||
void Batch::semi_circle_line(const Vec2f& center, float start_radians, float end_radians, float radius, int steps, float t, Color color)
 | 
			
		||||
{
 | 
			
		||||
	if (t >= radius)
 | 
			
		||||
	{
 | 
			
		||||
@ -798,13 +808,13 @@ void Batch::semi_circle_line(const Vec2& center, float start_radians, float end_
 | 
			
		||||
	{
 | 
			
		||||
		const auto add = Calc::angle_diff(start_radians, end_radians);
 | 
			
		||||
 | 
			
		||||
		Vec2 last_inner = Vec2::from_angle(start_radians, radius - t);
 | 
			
		||||
		Vec2 last_outer = Vec2::from_angle(start_radians, radius);
 | 
			
		||||
		Vec2f last_inner = Vec2f::from_angle(start_radians, radius - t);
 | 
			
		||||
		Vec2f last_outer = Vec2f::from_angle(start_radians, radius);
 | 
			
		||||
 | 
			
		||||
		for (int i = 1; i <= steps; i++)
 | 
			
		||||
		{
 | 
			
		||||
			const auto next_inner = Vec2::from_angle(start_radians + add * (i / (float)steps), radius - t);
 | 
			
		||||
			const auto next_outer = Vec2::from_angle(start_radians + add * (i / (float)steps), radius);
 | 
			
		||||
			const auto next_inner = Vec2f::from_angle(start_radians + add * (i / (float)steps), radius - t);
 | 
			
		||||
			const auto next_outer = Vec2f::from_angle(start_radians + add * (i / (float)steps), radius);
 | 
			
		||||
 | 
			
		||||
			quad(center + last_inner, center + last_outer, center + next_outer, center + next_inner, color);
 | 
			
		||||
 | 
			
		||||
@ -814,19 +824,19 @@ void Batch::semi_circle_line(const Vec2& center, float start_radians, float end_
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::circle(const Vec2& center, float radius, int steps, Color color)
 | 
			
		||||
void Batch::circle(const Vec2f& center, float radius, int steps, Color color)
 | 
			
		||||
{
 | 
			
		||||
	circle(center, radius, steps, color, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::circle(const Vec2& center, float radius, int steps, Color center_color, Color outer_color)
 | 
			
		||||
void Batch::circle(const Vec2f& center, float radius, int steps, Color center_color, Color outer_color)
 | 
			
		||||
{
 | 
			
		||||
	Vec2 last = Vec2(center.x + radius, center.y);
 | 
			
		||||
	Vec2f last = Vec2f(center.x + radius, center.y);
 | 
			
		||||
 | 
			
		||||
	for (int i = 1; i <= steps; i++)
 | 
			
		||||
	{
 | 
			
		||||
		const auto radians = (i / (float)steps) * Calc::TAU;
 | 
			
		||||
		const auto next = Vec2(center.x + Calc::cos(radians) * radius, center.y + Calc::sin(radians) * radius);
 | 
			
		||||
		const auto next = Vec2f(center.x + Calc::cos(radians) * radius, center.y + Calc::sin(radians) * radius);
 | 
			
		||||
 | 
			
		||||
		tri(last, next, center, outer_color, outer_color, center_color);
 | 
			
		||||
 | 
			
		||||
@ -834,7 +844,7 @@ void Batch::circle(const Vec2& center, float radius, int steps, Color center_col
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::circle_line(const Vec2& center, float radius, float t, int steps, Color color)
 | 
			
		||||
void Batch::circle_line(const Vec2f& center, float radius, float t, int steps, Color color)
 | 
			
		||||
{
 | 
			
		||||
	if (t >= radius)
 | 
			
		||||
	{
 | 
			
		||||
@ -842,16 +852,16 @@ void Batch::circle_line(const Vec2& center, float radius, float t, int steps, Co
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		Vec2 last_inner = Vec2(center.x + radius - t, center.y);
 | 
			
		||||
		Vec2 last_outer = Vec2(center.x + radius, center.y);
 | 
			
		||||
		Vec2f last_inner = Vec2f(center.x + radius - t, center.y);
 | 
			
		||||
		Vec2f last_outer = Vec2f(center.x + radius, center.y);
 | 
			
		||||
 | 
			
		||||
		for (int i = 1; i <= steps; i++)
 | 
			
		||||
		{
 | 
			
		||||
			const auto radians = (i / (float)steps) * Calc::TAU;
 | 
			
		||||
			const auto normal = Vec2(Calc::cos(radians), Calc::sin(radians));
 | 
			
		||||
			const auto normal = Vec2f(Calc::cos(radians), Calc::sin(radians));
 | 
			
		||||
 | 
			
		||||
			const auto next_inner = Vec2(center.x + normal.x * (radius - t), center.y + normal.y * (radius - t));
 | 
			
		||||
			const auto next_outer = Vec2(center.x + normal.x * radius, center.y + normal.y * radius);
 | 
			
		||||
			const auto next_inner = Vec2f(center.x + normal.x * (radius - t), center.y + normal.y * (radius - t));
 | 
			
		||||
			const auto next_outer = Vec2f(center.x + normal.x * radius, center.y + normal.y * radius);
 | 
			
		||||
 | 
			
		||||
			quad(last_inner, last_outer, next_outer, next_inner, color);
 | 
			
		||||
 | 
			
		||||
@ -861,7 +871,7 @@ void Batch::circle_line(const Vec2& center, float radius, float t, int steps, Co
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::quad(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec2& pos3, Color color)
 | 
			
		||||
void Batch::quad(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, const Vec2f& pos3, Color color)
 | 
			
		||||
{
 | 
			
		||||
	PUSH_QUAD(
 | 
			
		||||
		pos0.x, pos0.y, pos1.x, pos1.y, pos2.x, pos2.y, pos3.x, pos3.y,
 | 
			
		||||
@ -870,7 +880,7 @@ void Batch::quad(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec
 | 
			
		||||
		0, 0, 255);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::quad(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec2& pos3, Color col0, Color col1, Color col2, Color col3)
 | 
			
		||||
void Batch::quad(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, const Vec2f& pos3, Color col0, Color col1, Color col2, Color col3)
 | 
			
		||||
{
 | 
			
		||||
	PUSH_QUAD(
 | 
			
		||||
		pos0.x, pos0.y, pos1.x, pos1.y, pos2.x, pos2.y, pos3.x, pos3.y,
 | 
			
		||||
@ -879,7 +889,7 @@ void Batch::quad(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec
 | 
			
		||||
		0, 0, 255);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::quad(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec2& pos3, const Vec2& tex0, const Vec2& tex1, const Vec2& tex2, const Vec2& tex3, Color color)
 | 
			
		||||
void Batch::quad(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, const Vec2f& pos3, const Vec2f& tex0, const Vec2f& tex1, const Vec2f& tex2, const Vec2f& tex3, Color color)
 | 
			
		||||
{
 | 
			
		||||
	PUSH_QUAD(
 | 
			
		||||
		pos0.x, pos0.y, pos1.x, pos1.y, pos2.x, pos2.y, pos3.x, pos3.y,
 | 
			
		||||
@ -888,7 +898,7 @@ void Batch::quad(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec
 | 
			
		||||
		m_tex_mult, m_tex_wash, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::quad(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec2& pos3, const Vec2& tex0, const Vec2& tex1, const Vec2& tex2, const Vec2& tex3, Color col0, Color col1, Color col2, Color col3)
 | 
			
		||||
void Batch::quad(const Vec2f& pos0, const Vec2f& pos1, const Vec2f& pos2, const Vec2f& pos3, const Vec2f& tex0, const Vec2f& tex1, const Vec2f& tex2, const Vec2f& tex3, Color col0, Color col1, Color col2, Color col3)
 | 
			
		||||
{
 | 
			
		||||
	PUSH_QUAD(
 | 
			
		||||
		pos0.x, pos0.y, pos1.x, pos1.y, pos2.x, pos2.y, pos3.x, pos3.y,
 | 
			
		||||
@ -897,7 +907,7 @@ void Batch::quad(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec
 | 
			
		||||
		m_tex_mult, m_tex_wash, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::quad_line(const Vec2& a, const Vec2& b, const Vec2& c, const Vec2& d, float t, Color color)
 | 
			
		||||
void Batch::quad_line(const Vec2f& a, const Vec2f& b, const Vec2f& c, const Vec2f& d, float t, Color color)
 | 
			
		||||
{
 | 
			
		||||
	// TODO:
 | 
			
		||||
	// Detect if the thickness of the line fills the entire shape
 | 
			
		||||
@ -924,22 +934,22 @@ void Batch::quad_line(const Vec2& a, const Vec2& b, const Vec2& c, const Vec2& d
 | 
			
		||||
	quad(dd, d, a, aa, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::arrow_head(const Vec2& point_pos, float radians, float side_len, Color color)
 | 
			
		||||
void Batch::arrow_head(const Vec2f& point_pos, float radians, float side_len, Color color)
 | 
			
		||||
{
 | 
			
		||||
	arrow_head(point_pos, point_pos - Vec2::from_angle(radians), side_len, color);
 | 
			
		||||
	arrow_head(point_pos, point_pos - Vec2f::from_angle(radians), side_len, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::arrow_head(const Vec2& point_pos, const Vec2& from_pos, float side_len, Color color)
 | 
			
		||||
void Batch::arrow_head(const Vec2f& point_pos, const Vec2f& from_pos, float side_len, Color color)
 | 
			
		||||
{
 | 
			
		||||
	float height = sqrtf(side_len * side_len - powf(side_len / 2, 2));
 | 
			
		||||
	Vec2 dir = (point_pos - from_pos).normal();
 | 
			
		||||
	Vec2 perp = dir.perpendicular();
 | 
			
		||||
	Vec2 base = point_pos - dir * height;
 | 
			
		||||
	Vec2f dir = (point_pos - from_pos).normal();
 | 
			
		||||
	Vec2f perp = dir.turn_right();
 | 
			
		||||
	Vec2f base = point_pos - dir * height;
 | 
			
		||||
	
 | 
			
		||||
	tri(point_pos, base + perp * side_len / 2, base - perp * side_len / 2, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::tex(const TextureRef& texture, const Vec2& pos, Color color)
 | 
			
		||||
void Batch::tex(const TextureRef& texture, const Vec2f& pos, Color color)
 | 
			
		||||
{
 | 
			
		||||
	set_texture(texture);
 | 
			
		||||
 | 
			
		||||
@ -953,9 +963,9 @@ void Batch::tex(const TextureRef& texture, const Vec2& pos, Color color)
 | 
			
		||||
		m_tex_mult, m_tex_wash, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::tex(const TextureRef& texture, const Vec2& pos, const Vec2& origin, const Vec2& scale, float rotation, Color color)
 | 
			
		||||
void Batch::tex(const TextureRef& texture, const Vec2f& pos, const Vec2f& origin, const Vec2f& scale, float rotation, Color color)
 | 
			
		||||
{
 | 
			
		||||
	push_matrix(Mat3x2::create_transform(pos, origin, scale, rotation));
 | 
			
		||||
	push_matrix(Mat3x2f::create_transform(pos, origin, scale, rotation));
 | 
			
		||||
 | 
			
		||||
	set_texture(texture);
 | 
			
		||||
 | 
			
		||||
@ -971,9 +981,9 @@ void Batch::tex(const TextureRef& texture, const Vec2& pos, const Vec2& origin,
 | 
			
		||||
	pop_matrix();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::tex(const TextureRef& texture, const Rect& clip, const Vec2& pos, const Vec2& origin, const Vec2& scale, float rotation, Color color)
 | 
			
		||||
void Batch::tex(const TextureRef& texture, const Rectf& clip, const Vec2f& pos, const Vec2f& origin, const Vec2f& scale, float rotation, Color color)
 | 
			
		||||
{
 | 
			
		||||
	push_matrix(Mat3x2::create_transform(pos, origin, scale, rotation));
 | 
			
		||||
	push_matrix(Mat3x2f::create_transform(pos, origin, scale, rotation));
 | 
			
		||||
 | 
			
		||||
	set_texture(texture);
 | 
			
		||||
 | 
			
		||||
@ -993,7 +1003,7 @@ void Batch::tex(const TextureRef& texture, const Rect& clip, const Vec2& pos, co
 | 
			
		||||
	pop_matrix();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::tex(const Subtexture& sub, const Vec2& pos, Color color)
 | 
			
		||||
void Batch::tex(const Subtexture& sub, const Vec2f& pos, Color color)
 | 
			
		||||
{
 | 
			
		||||
	if (!sub.texture)
 | 
			
		||||
	{
 | 
			
		||||
@ -1024,9 +1034,9 @@ void Batch::tex(const Subtexture& sub, const Vec2& pos, Color color)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::tex(const Subtexture& sub, const Vec2& pos, const Vec2& origin, const Vec2& scale, float rotation, Color color)
 | 
			
		||||
void Batch::tex(const Subtexture& sub, const Vec2f& pos, const Vec2f& origin, const Vec2f& scale, float rotation, Color color)
 | 
			
		||||
{
 | 
			
		||||
	push_matrix(Mat3x2::create_transform(pos, origin, scale, rotation));
 | 
			
		||||
	push_matrix(Mat3x2f::create_transform(pos, origin, scale, rotation));
 | 
			
		||||
 | 
			
		||||
	if (!sub.texture)
 | 
			
		||||
	{
 | 
			
		||||
@ -1059,24 +1069,24 @@ void Batch::tex(const Subtexture& sub, const Vec2& pos, const Vec2& origin, cons
 | 
			
		||||
	pop_matrix();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::tex(const Subtexture& sub, const Rect& clip, const Vec2& pos, const Vec2& origin, const Vec2& scale, float rotation, Color color)
 | 
			
		||||
void Batch::tex(const Subtexture& sub, const Rectf& clip, const Vec2f& pos, const Vec2f& origin, const Vec2f& scale, float rotation, Color color)
 | 
			
		||||
{
 | 
			
		||||
	tex(sub.crop(clip), pos, origin, scale, rotation, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::str(const SpriteFont& font, const String& text, const Vec2& pos, Color color)
 | 
			
		||||
void Batch::str(const SpriteFont& font, const String& text, const Vec2f& pos, Color color)
 | 
			
		||||
{
 | 
			
		||||
	str(font, text, pos, TextAlign::TopLeft, font.size, color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Batch::str(const SpriteFont& font, const String& text, const Vec2& pos, TextAlign align, float size, Color color)
 | 
			
		||||
void Batch::str(const SpriteFont& font, const String& text, const Vec2f& pos, TextAlign align, float size, Color color)
 | 
			
		||||
{
 | 
			
		||||
	push_matrix(
 | 
			
		||||
		Mat3x2::create_scale(size / font.size) *
 | 
			
		||||
		Mat3x2::create_translation(pos)
 | 
			
		||||
		Mat3x2f::create_scale(size / font.size) *
 | 
			
		||||
		Mat3x2f::create_translation(pos)
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	Vec2 offset;
 | 
			
		||||
	Vec2f offset;
 | 
			
		||||
 | 
			
		||||
	if ((align & TextAlign::Left) == TextAlign::Left)
 | 
			
		||||
		offset.x = 0;
 | 
			
		||||
@ -1119,7 +1129,7 @@ void Batch::str(const SpriteFont& font, const String& text, const Vec2& pos, Tex
 | 
			
		||||
		// draw it, if the subtexture exists
 | 
			
		||||
		if (ch.subtexture.texture)
 | 
			
		||||
		{
 | 
			
		||||
			Vec2 at = offset + ch.offset;
 | 
			
		||||
			Vec2f at = offset + ch.offset;
 | 
			
		||||
 | 
			
		||||
			if (i > 0 && text[i - 1] != '\n')
 | 
			
		||||
				at.x += font.get_kerning(last, next);
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ using namespace Blah;
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
	int calc_uniform_size(const UniformInfo& uniform)
 | 
			
		||||
	int blah_calc_uniform_size(const UniformInfo& uniform)
 | 
			
		||||
	{
 | 
			
		||||
		int components = 0;
 | 
			
		||||
 | 
			
		||||
@ -27,16 +27,6 @@ namespace
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MaterialRef Material::create(const ShaderRef& shader)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT(shader, "The provided shader is invalid");
 | 
			
		||||
 | 
			
		||||
	if (shader)
 | 
			
		||||
		return MaterialRef(new Material(shader));
 | 
			
		||||
 | 
			
		||||
	return MaterialRef();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Material::Material(const ShaderRef& shader)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT(shader, "Material is being created with an invalid shader");
 | 
			
		||||
@ -64,12 +54,31 @@ Material::Material(const ShaderRef& shader)
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		float_size += calc_uniform_size(uniform);
 | 
			
		||||
		float_size += blah_calc_uniform_size(uniform);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_data.expand(float_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MaterialRef Material::create(const ShaderRef& shader)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT(shader, "The provided shader is invalid");
 | 
			
		||||
 | 
			
		||||
	if (shader)
 | 
			
		||||
		return MaterialRef(new Material(shader));
 | 
			
		||||
 | 
			
		||||
	return MaterialRef();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MaterialRef Material::clone() const
 | 
			
		||||
{
 | 
			
		||||
	auto copy = MaterialRef(new Material(m_shader));
 | 
			
		||||
	copy->m_textures = m_textures;
 | 
			
		||||
	copy->m_samplers = m_samplers;
 | 
			
		||||
	copy->m_data = m_data;
 | 
			
		||||
	return copy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ShaderRef Material::shader() const
 | 
			
		||||
{
 | 
			
		||||
	return m_shader;
 | 
			
		||||
@ -293,7 +302,7 @@ void Material::set_value(const char* name, const float* value, i64 length)
 | 
			
		||||
 | 
			
		||||
		if (strcmp(uniform.name, name) == 0)
 | 
			
		||||
		{
 | 
			
		||||
			auto max = calc_uniform_size(uniform);
 | 
			
		||||
			auto max = blah_calc_uniform_size(uniform);
 | 
			
		||||
			if (length > max)
 | 
			
		||||
			{
 | 
			
		||||
				Log::warn("Exceeding length of Uniform '%s' (%i / %i)", name, length, max);
 | 
			
		||||
@ -304,13 +313,73 @@ void Material::set_value(const char* name, const float* value, i64 length)
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		offset += calc_uniform_size(uniform);
 | 
			
		||||
		offset += blah_calc_uniform_size(uniform);
 | 
			
		||||
		index++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Log::warn("No Uniform '%s' exists", name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Material::set_value(const char* name, float value)
 | 
			
		||||
{
 | 
			
		||||
	set_value(name, &value, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Material::set_value(const char* name, const Vec2f& value)
 | 
			
		||||
{
 | 
			
		||||
	set_value(name, &value.x, 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Material::set_value(const char* name, const Vec3f& value)
 | 
			
		||||
{
 | 
			
		||||
	set_value(name, &value.x, 3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Material::set_value(const char* name, const Vec4f& value)
 | 
			
		||||
{
 | 
			
		||||
	set_value(name, &value.x, 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Material::set_value(const char* name, const Mat3x2f& value)
 | 
			
		||||
{
 | 
			
		||||
	set_value(name, &value.m11, 6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Material::set_value(const char* name, const Mat4x4f& value)
 | 
			
		||||
{
 | 
			
		||||
	set_value(name, &value.m11, 16);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Material::set_value(const char* name, const Vector<float>& value)
 | 
			
		||||
{
 | 
			
		||||
	set_value(name, value.data(), value.size());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Material::set_value(const char* name, const Vector<Vec2f>& value)
 | 
			
		||||
{
 | 
			
		||||
	set_value(name, (float*)value.data(), value.size() * 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Material::set_value(const char* name, const Vector<Vec3f>& value)
 | 
			
		||||
{
 | 
			
		||||
	set_value(name, (float*)value.data(), value.size() * 3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Material::set_value(const char* name, const Vector<Vec4f>& value)
 | 
			
		||||
{
 | 
			
		||||
	set_value(name, (float*)value.data(), value.size() * 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Material::set_value(const char* name, const Vector<Mat3x2f>& value)
 | 
			
		||||
{
 | 
			
		||||
	set_value(name, (float*)value.data(), value.size() * 6);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Material::set_value(const char* name, const Vector<Mat4x4f>& value)
 | 
			
		||||
{
 | 
			
		||||
	set_value(name, (float*)value.data(), value.size() * 16);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const float* Material::get_value(const char* name, i64* length) const
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT(m_shader, "Material Shader is invalid");
 | 
			
		||||
@ -327,12 +396,12 @@ const float* Material::get_value(const char* name, i64* length) const
 | 
			
		||||
		if (strcmp(uniform.name, name) == 0)
 | 
			
		||||
		{
 | 
			
		||||
			if (length != nullptr)
 | 
			
		||||
				*length = calc_uniform_size(uniform);
 | 
			
		||||
				*length = blah_calc_uniform_size(uniform);
 | 
			
		||||
			return m_data.begin() + offset;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		index++;
 | 
			
		||||
		offset += calc_uniform_size(uniform);
 | 
			
		||||
		offset += blah_calc_uniform_size(uniform);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Log::warn("No Uniform '%s' exists", name);
 | 
			
		||||
 | 
			
		||||
@ -12,8 +12,8 @@ RenderPass::RenderPass()
 | 
			
		||||
	material = MaterialRef();
 | 
			
		||||
	has_viewport = false;
 | 
			
		||||
	has_scissor = false;
 | 
			
		||||
	viewport = Rect();
 | 
			
		||||
	scissor = Rect();
 | 
			
		||||
	viewport = Rectf();
 | 
			
		||||
	scissor = Rectf();
 | 
			
		||||
	index_start = 0;
 | 
			
		||||
	index_count = 0;
 | 
			
		||||
	instance_count = 0;
 | 
			
		||||
@ -66,7 +66,7 @@ void RenderPass::perform()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// get the total drawable size
 | 
			
		||||
	auto draw_size = Vec2(pass.target->width(), pass.target->height());
 | 
			
		||||
	auto draw_size = Vec2f(pass.target->width(), pass.target->height());
 | 
			
		||||
 | 
			
		||||
	// Validate Viewport
 | 
			
		||||
	if (!pass.has_viewport)
 | 
			
		||||
@ -78,12 +78,12 @@ void RenderPass::perform()
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		pass.viewport = pass.viewport.overlap_rect(Rect(0, 0, draw_size.x, draw_size.y));
 | 
			
		||||
		pass.viewport = pass.viewport.overlap_rect(Rectf(0, 0, draw_size.x, draw_size.y));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Validate Scissor
 | 
			
		||||
	if (pass.has_scissor)
 | 
			
		||||
		pass.scissor = pass.scissor.overlap_rect(Rect(0, 0, draw_size.x, draw_size.y));
 | 
			
		||||
		pass.scissor = pass.scissor.overlap_rect(Rectf(0, 0, draw_size.x, draw_size.y));
 | 
			
		||||
 | 
			
		||||
	// perform render
 | 
			
		||||
	Graphics::render(pass);
 | 
			
		||||
 | 
			
		||||
@ -213,7 +213,7 @@ void SpriteFont::rebuild(const Font& font, float size, const CharSet& charset)
 | 
			
		||||
			// add character
 | 
			
		||||
			auto ch = font.get_character(glyph, scale);
 | 
			
		||||
			m_characters[i].advance = ch.advance;
 | 
			
		||||
			m_characters[i].offset = Vec2(ch.offset_x, ch.offset_y);
 | 
			
		||||
			m_characters[i].offset = Vec2f(ch.offset_x, ch.offset_y);
 | 
			
		||||
 | 
			
		||||
			// pack glyph
 | 
			
		||||
			if (ch.has_glyph)
 | 
			
		||||
 | 
			
		||||
@ -6,12 +6,12 @@ using namespace Blah;
 | 
			
		||||
Subtexture::Subtexture() {}
 | 
			
		||||
 | 
			
		||||
Subtexture::Subtexture(const TextureRef& texture)
 | 
			
		||||
	: Subtexture(texture, Rect(0, 0, (float)texture->width(), (float)texture->height())) {}
 | 
			
		||||
	: Subtexture(texture, Rectf(0, 0, (float)texture->width(), (float)texture->height())) {}
 | 
			
		||||
 | 
			
		||||
Subtexture::Subtexture(const TextureRef& texture, Rect source)
 | 
			
		||||
	: Subtexture(texture, source, Rect(0, 0, source.w, source.h)) {}
 | 
			
		||||
Subtexture::Subtexture(const TextureRef& texture, Rectf source)
 | 
			
		||||
	: Subtexture(texture, source, Rectf(0, 0, source.w, source.h)) {}
 | 
			
		||||
 | 
			
		||||
Subtexture::Subtexture(const TextureRef& texture, Rect source, Rect frame)
 | 
			
		||||
Subtexture::Subtexture(const TextureRef& texture, Rectf source, Rectf frame)
 | 
			
		||||
	: texture(texture), source(source), frame(frame)
 | 
			
		||||
{
 | 
			
		||||
	update();
 | 
			
		||||
@ -44,7 +44,7 @@ void Subtexture::update()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Subtexture::crop_info(const Rect& clip, Rect* dest_source, Rect* dest_frame) const
 | 
			
		||||
void Subtexture::crop_info(const Rectf& clip, Rectf* dest_source, Rectf* dest_frame) const
 | 
			
		||||
{
 | 
			
		||||
	*dest_source = (clip + source.top_left() + frame.top_left()).overlap_rect(source);
 | 
			
		||||
 | 
			
		||||
@ -54,7 +54,7 @@ void Subtexture::crop_info(const Rect& clip, Rect* dest_source, Rect* dest_frame
 | 
			
		||||
	dest_frame->h = clip.h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Subtexture Subtexture::crop(const Rect& clip) const
 | 
			
		||||
Subtexture Subtexture::crop(const Rectf& clip) const
 | 
			
		||||
{
 | 
			
		||||
	Subtexture dst;
 | 
			
		||||
	dst.texture = texture;
 | 
			
		||||
 | 
			
		||||
@ -193,7 +193,7 @@ void Image::premultiply()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Image::set_pixels(const RectI& rect, Color* data)
 | 
			
		||||
void Image::set_pixels(const Recti& rect, Color* data)
 | 
			
		||||
{
 | 
			
		||||
	for (int y = 0; y < rect.h; y++)
 | 
			
		||||
	{
 | 
			
		||||
@ -257,7 +257,7 @@ bool Image::save_jpg(Stream& stream, int quality) const
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Image::get_pixels(Color* dest, const Point& dest_pos, const Point& dest_size, RectI source_rect) const
 | 
			
		||||
void Image::get_pixels(Color* dest, const Point& dest_pos, const Point& dest_size, Recti source_rect) const
 | 
			
		||||
{
 | 
			
		||||
	// can't be outside of the source image
 | 
			
		||||
	if (source_rect.x < 0) source_rect.x = 0;
 | 
			
		||||
@ -279,7 +279,7 @@ void Image::get_pixels(Color* dest, const Point& dest_pos, const Point& dest_siz
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Image Image::get_sub_image(const RectI& source_rect)
 | 
			
		||||
Image Image::get_sub_image(const Recti& source_rect)
 | 
			
		||||
{
 | 
			
		||||
	Image img(source_rect.w, source_rect.h);
 | 
			
		||||
	get_pixels(img.pixels, Point::zero, Point(img.width, img.height), source_rect);
 | 
			
		||||
 | 
			
		||||
@ -43,15 +43,15 @@ Packer::~Packer()
 | 
			
		||||
 | 
			
		||||
void Packer::add(u64 id, int width, int height, const Color* pixels)
 | 
			
		||||
{
 | 
			
		||||
	add_entry(id, width, height, pixels, RectI(0, 0, width, height));
 | 
			
		||||
	add_entry(id, width, height, pixels, Recti(0, 0, width, height));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Packer::add(u64 id, const Image& image)
 | 
			
		||||
{
 | 
			
		||||
	add_entry(id, image.width, image.height, image.pixels, RectI(0, 0, image.width, image.height));
 | 
			
		||||
	add_entry(id, image.width, image.height, image.pixels, Recti(0, 0, image.width, image.height));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Packer::add(u64 id, const Image& image, const RectI& source)
 | 
			
		||||
void Packer::add(u64 id, const Image& image, const Recti& source)
 | 
			
		||||
{
 | 
			
		||||
	add_entry(id, image.width, image.height, image.pixels, source);
 | 
			
		||||
}
 | 
			
		||||
@ -61,11 +61,11 @@ void Packer::add(u64 id, const FilePath& path)
 | 
			
		||||
	add(id, Image(path.cstr()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Packer::add_entry(u64 id, int w, int h, const Color* pixels, const RectI& source)
 | 
			
		||||
void Packer::add_entry(u64 id, int w, int h, const Color* pixels, const Recti& source)
 | 
			
		||||
{
 | 
			
		||||
	m_dirty = true;
 | 
			
		||||
 | 
			
		||||
	Entry entry(id, RectI(0, 0, source.w, source.h));
 | 
			
		||||
	Entry entry(id, Recti(0, 0, source.w, source.h));
 | 
			
		||||
 | 
			
		||||
	// trim
 | 
			
		||||
	int top = source.y, left = source.x, right = source.x, bottom = source.y;
 | 
			
		||||
@ -115,7 +115,6 @@ void Packer::add_entry(u64 id, int w, int h, const Color* pixels, const RectI& s
 | 
			
		||||
		entry.packed.w = (right - left);
 | 
			
		||||
		entry.packed.h = (bottom - top);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		// create pixel data
 | 
			
		||||
		entry.memory_index = m_buffer.position();
 | 
			
		||||
 | 
			
		||||
@ -189,7 +188,7 @@ void Packer::pack()
 | 
			
		||||
 | 
			
		||||
			int from = packed;
 | 
			
		||||
			int index = 0;
 | 
			
		||||
			Node* root = nodes[index++].Reset(RectI(0, 0, sources[from]->packed.w + padding * 2 + spacing, sources[from]->packed.h + padding * 2 + spacing));
 | 
			
		||||
			Node* root = nodes[index++].Reset(Recti(0, 0, sources[from]->packed.w + padding * 2 + spacing, sources[from]->packed.h + padding * 2 + spacing));
 | 
			
		||||
 | 
			
		||||
			while (packed < count)
 | 
			
		||||
			{
 | 
			
		||||
@ -217,18 +216,18 @@ void Packer::pack()
 | 
			
		||||
						// grow right
 | 
			
		||||
						if (shouldGrowRight || (!shouldGrowDown && canGrowRight))
 | 
			
		||||
						{
 | 
			
		||||
							Node* next = nodes[index++].Reset(RectI(0, 0, root->rect.w + w, root->rect.h));
 | 
			
		||||
							Node* next = nodes[index++].Reset(Recti(0, 0, root->rect.w + w, root->rect.h));
 | 
			
		||||
							next->used = true;
 | 
			
		||||
							next->down = root;
 | 
			
		||||
							next->right = node = nodes[index++].Reset(RectI(root->rect.w, 0, w, root->rect.h));
 | 
			
		||||
							next->right = node = nodes[index++].Reset(Recti(root->rect.w, 0, w, root->rect.h));
 | 
			
		||||
							root = next;
 | 
			
		||||
						}
 | 
			
		||||
						// grow down
 | 
			
		||||
						else
 | 
			
		||||
						{
 | 
			
		||||
							Node* next = nodes[index++].Reset(RectI(0, 0, root->rect.w, root->rect.h + h));
 | 
			
		||||
							Node* next = nodes[index++].Reset(Recti(0, 0, root->rect.w, root->rect.h + h));
 | 
			
		||||
							next->used = true;
 | 
			
		||||
							next->down = node = nodes[index++].Reset(RectI(0, root->rect.h, root->rect.w, h));
 | 
			
		||||
							next->down = node = nodes[index++].Reset(Recti(0, root->rect.h, root->rect.w, h));
 | 
			
		||||
							next->right = root;
 | 
			
		||||
							root = next;
 | 
			
		||||
						}
 | 
			
		||||
@ -241,8 +240,8 @@ void Packer::pack()
 | 
			
		||||
 | 
			
		||||
				// add
 | 
			
		||||
				node->used = true;
 | 
			
		||||
				node->down = nodes[index++].Reset(RectI(node->rect.x, node->rect.y + h, node->rect.w, node->rect.h - h));
 | 
			
		||||
				node->right = nodes[index++].Reset(RectI(node->rect.x + w, node->rect.y, node->rect.w - w, h));
 | 
			
		||||
				node->down = nodes[index++].Reset(Recti(node->rect.x, node->rect.y + h, node->rect.w, node->rect.h - h));
 | 
			
		||||
				node->right = nodes[index++].Reset(Recti(node->rect.x + w, node->rect.y, node->rect.w - w, h));
 | 
			
		||||
 | 
			
		||||
				sources[packed]->packed.x = node->rect.x + padding;
 | 
			
		||||
				sources[packed]->packed.y = node->rect.y + padding;
 | 
			
		||||
@ -276,21 +275,26 @@ void Packer::pack()
 | 
			
		||||
					sources[i]->page = page;
 | 
			
		||||
					if (!sources[i]->empty)
 | 
			
		||||
					{
 | 
			
		||||
						RectI dst = sources[i]->packed;
 | 
			
		||||
						Recti dst = sources[i]->packed;
 | 
			
		||||
						Color* src = (Color*)(m_buffer.data() + sources[i]->memory_index);
 | 
			
		||||
 | 
			
		||||
						// TODO:
 | 
			
		||||
						// Optimize this?
 | 
			
		||||
						if (padding > 0)
 | 
			
		||||
						{
 | 
			
		||||
							pages[page].set_pixels(RectI(dst.x - padding, dst.y, dst.w, dst.h), src);
 | 
			
		||||
							pages[page].set_pixels(RectI(dst.x + padding, dst.y, dst.w, dst.h), src);
 | 
			
		||||
							pages[page].set_pixels(RectI(dst.x, dst.y - padding, dst.w, dst.h), src);
 | 
			
		||||
							pages[page].set_pixels(RectI(dst.x, dst.y + padding, dst.w, dst.h), src);
 | 
			
		||||
							Image& image = pages[page];
 | 
			
		||||
							for (int x = -padding; x < dst.w + padding * 2; x++)
 | 
			
		||||
								for (int y = -padding; y < dst.h + padding * 2; y++)
 | 
			
		||||
								{
 | 
			
		||||
									int sx = (x < 0 ? 0 : (x > dst.w - 1 ? dst.w - 1 : x));
 | 
			
		||||
									int sy = (y < 0 ? 0 : (y > dst.h - 1 ? dst.h - 1 : y));
 | 
			
		||||
									image.pixels[dst.x + x + (dst.y + y) * image.width] = src[sx + sy * dst.w];
 | 
			
		||||
								}
 | 
			
		||||
						}
 | 
			
		||||
						else
 | 
			
		||||
						{
 | 
			
		||||
							pages[page].set_pixels(dst, src);
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						pages[page].set_pixels(dst, src);
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
@ -335,7 +339,7 @@ Packer::Node* Packer::Node::Find(int w, int h)
 | 
			
		||||
	return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Packer::Node* Packer::Node::Reset(const RectI& rect)
 | 
			
		||||
Packer::Node* Packer::Node::Reset(const Recti& rect)
 | 
			
		||||
{
 | 
			
		||||
	used = false;
 | 
			
		||||
	this->rect = rect;
 | 
			
		||||
 | 
			
		||||
@ -2,9 +2,9 @@
 | 
			
		||||
#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.h"
 | 
			
		||||
#include "internal/platform.h"
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
using namespace Blah;
 | 
			
		||||
@ -16,11 +16,15 @@ namespace
 | 
			
		||||
	Vector<WeakRef<ButtonBinding>> g_buttons;
 | 
			
		||||
	Vector<WeakRef<AxisBinding>> g_axes;
 | 
			
		||||
	Vector<WeakRef<StickBinding>> g_sticks;
 | 
			
		||||
	String g_clipboard;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
InputState Blah::Input::state;
 | 
			
		||||
InputState Blah::Input::last_state;
 | 
			
		||||
 | 
			
		||||
float Blah::Input::repeat_delay = 0.35f;
 | 
			
		||||
float Blah::Input::repeat_interval = 0.025f;
 | 
			
		||||
 | 
			
		||||
void Input::init()
 | 
			
		||||
{
 | 
			
		||||
	g_empty_controller.name = "Disconnected";
 | 
			
		||||
@ -68,6 +72,9 @@ void Input::update_state()
 | 
			
		||||
			controller.released[j] = false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// get clipboard
 | 
			
		||||
	g_clipboard = Platform::get_clipboard();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Input::update_bindings()
 | 
			
		||||
@ -112,7 +119,7 @@ void Input::update_bindings()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MouseState::on_move(const Vec2& pos, const Vec2& screen_pos)
 | 
			
		||||
void MouseState::on_move(const Vec2f& pos, const Vec2f& screen_pos)
 | 
			
		||||
{
 | 
			
		||||
	position = pos;
 | 
			
		||||
	screen_position = screen_pos;
 | 
			
		||||
@ -223,17 +230,17 @@ bool KeyboardState::alt()
 | 
			
		||||
	return down[Key::LeftAlt] || down[Key::RightAlt];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Vec2 Input::mouse()
 | 
			
		||||
Vec2f Input::mouse()
 | 
			
		||||
{
 | 
			
		||||
	return state.mouse.position;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Vec2 Input::mouse_draw()
 | 
			
		||||
Vec2f Input::mouse_draw()
 | 
			
		||||
{
 | 
			
		||||
	return state.mouse.draw_position;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Vec2 Input::mouse_screen()
 | 
			
		||||
Vec2f Input::mouse_screen()
 | 
			
		||||
{
 | 
			
		||||
	return state.mouse.screen_position;
 | 
			
		||||
}
 | 
			
		||||
@ -273,6 +280,26 @@ bool Input::released(Key key)
 | 
			
		||||
	return state.keyboard.released[key];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Input::repeating(Key key)
 | 
			
		||||
{
 | 
			
		||||
	if (state.keyboard.pressed[key])
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	if (state.keyboard.down[key])
 | 
			
		||||
	{
 | 
			
		||||
		double timestamp = state.keyboard.timestamp[key] / (double)Time::ticks_per_second;
 | 
			
		||||
		double current_time = Time::ticks / (double)Time::ticks_per_second;
 | 
			
		||||
 | 
			
		||||
		if (current_time > timestamp + Input::repeat_delay)
 | 
			
		||||
		{
 | 
			
		||||
			if (Time::on_interval(current_time - timestamp, Time::delta, Input::repeat_interval, 0.0f))
 | 
			
		||||
				return true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Input::ctrl()
 | 
			
		||||
{
 | 
			
		||||
	return state.keyboard.ctrl();
 | 
			
		||||
@ -312,6 +339,17 @@ const char* Input::name_of(Button button)
 | 
			
		||||
	return "Unknown";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const String& Input::get_clipboard()
 | 
			
		||||
{
 | 
			
		||||
	return g_clipboard;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Input::set_clipboard(const String& text)
 | 
			
		||||
{
 | 
			
		||||
	g_clipboard = text;
 | 
			
		||||
	return Platform::set_clipboard(text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ButtonBindingRef Input::register_binding(const ButtonBinding& binding)
 | 
			
		||||
{
 | 
			
		||||
	auto result = std::make_shared<ButtonBinding>(binding);
 | 
			
		||||
@ -730,17 +768,17 @@ void AxisBinding::clear()
 | 
			
		||||
	positive.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Vec2 StickBinding::value() const
 | 
			
		||||
Vec2f StickBinding::value() const
 | 
			
		||||
{
 | 
			
		||||
	Vec2 result = Vec2(x.value(), y.value());
 | 
			
		||||
	Vec2f result = Vec2f(x.value(), y.value());
 | 
			
		||||
	if (round_threshold > 0 && result.length() < round_threshold)
 | 
			
		||||
		return Vec2::zero;
 | 
			
		||||
		return Vec2f::zero;
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Point StickBinding::sign() const
 | 
			
		||||
{
 | 
			
		||||
	Vec2 result = value();
 | 
			
		||||
	Vec2f result = value();
 | 
			
		||||
	return Point((int)Calc::sign(result.x), (int)Calc::sign(result.y));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1420,7 +1420,7 @@ namespace Blah
 | 
			
		||||
 | 
			
		||||
		// Viewport
 | 
			
		||||
		{
 | 
			
		||||
			Rect viewport = pass.viewport;
 | 
			
		||||
			Rectf viewport = pass.viewport;
 | 
			
		||||
			viewport.y = size.y - viewport.y - viewport.h;
 | 
			
		||||
 | 
			
		||||
			gl.Viewport((GLint)viewport.x, (GLint)viewport.y, (GLint)viewport.w, (GLint)viewport.h);
 | 
			
		||||
@ -1434,7 +1434,7 @@ namespace Blah
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				Rect scissor = pass.scissor;
 | 
			
		||||
				Rectf scissor = pass.scissor;
 | 
			
		||||
				scissor.y = size.y - scissor.y - scissor.h;
 | 
			
		||||
 | 
			
		||||
				if (scissor.w < 0)
 | 
			
		||||
 | 
			
		||||
@ -88,6 +88,12 @@ namespace Blah
 | 
			
		||||
		// opens a directory in the OS file explorer / finder
 | 
			
		||||
		void dir_explore(const char* path);
 | 
			
		||||
 | 
			
		||||
		// sets the contents of the clipboard
 | 
			
		||||
		void set_clipboard(const char* text);
 | 
			
		||||
 | 
			
		||||
		// gets the contents of the clipboard into the given string
 | 
			
		||||
		const char* get_clipboard();
 | 
			
		||||
 | 
			
		||||
		// OpenGL Methods
 | 
			
		||||
		void* gl_get_func(const char* name);
 | 
			
		||||
		void* gl_context_create();
 | 
			
		||||
 | 
			
		||||
@ -261,8 +261,8 @@ void Platform::update(InputState& state)
 | 
			
		||||
		SDL_GetGlobalMouseState(&x, &y);
 | 
			
		||||
 | 
			
		||||
		state.mouse.on_move(
 | 
			
		||||
			Vec2((float)(x - win_x), (float)(y - win_y)),
 | 
			
		||||
			Vec2((float)x, (float)y));
 | 
			
		||||
			Vec2f((float)(x - win_x), (float)(y - win_y)),
 | 
			
		||||
			Vec2f((float)x, (float)y));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// poll normal events
 | 
			
		||||
@ -722,6 +722,17 @@ void Platform::dir_explore(const char* path)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// clipboard
 | 
			
		||||
void Platform::set_clipboard(const char* text)
 | 
			
		||||
{
 | 
			
		||||
	SDL_SetClipboardText(text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* Platform::get_clipboard()
 | 
			
		||||
{
 | 
			
		||||
	return SDL_GetClipboardText();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* Platform::gl_get_func(const char* name)
 | 
			
		||||
{
 | 
			
		||||
	return SDL_GL_GetProcAddress(name);
 | 
			
		||||
 | 
			
		||||
@ -360,7 +360,7 @@ LRESULT CALLBACK Blah::win32_window_procedure(HWND hwnd, UINT msg, WPARAM wParam
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case WM_MOUSEMOVE:
 | 
			
		||||
		g_platform.input_state->mouse.on_move(Vec2((float)((u16)lParam), (float)(lParam >> 16)), Vec2::zero);
 | 
			
		||||
		g_platform.input_state->mouse.on_move(Vec2f((float)((u16)lParam), (float)(lParam >> 16)), Vec2f::zero);
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case WM_MOUSEWHEEL:
 | 
			
		||||
@ -628,6 +628,17 @@ FileRef Platform::file_open(const char* path, FileMode mode)
 | 
			
		||||
	return FileRef(new Win32File(result));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// clipboard
 | 
			
		||||
void Platform::set_clipboard(const char* text)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT(false, "Not Implemented Yet");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* Platform::get_clipboard()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT(false, "Not Implemented Yet");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* Platform::gl_get_func(const char* name)
 | 
			
		||||
{
 | 
			
		||||
	// this check is taken from https://www.khronos.org/opengl/wiki/Load_OpenGL_Functions
 | 
			
		||||
 | 
			
		||||
@ -1,49 +1,15 @@
 | 
			
		||||
#include <blah/numerics/calc.h>
 | 
			
		||||
#include <blah/numerics/vec2.h>
 | 
			
		||||
#include <blah/numerics/spatial.h>
 | 
			
		||||
#include <cmath>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
 | 
			
		||||
using namespace Blah;
 | 
			
		||||
 | 
			
		||||
float Calc::rand_float(float min, float maxExc)
 | 
			
		||||
{
 | 
			
		||||
	return min + rand_float(maxExc - min);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float Calc::rand_float(float maxExc)
 | 
			
		||||
{
 | 
			
		||||
	return (rand() / (float)RAND_MAX) * maxExc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Calc::rand_int(int min, int maxExc)
 | 
			
		||||
{
 | 
			
		||||
	return min + rand_int(maxExc - min);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Calc::rand_int(int maxExc)
 | 
			
		||||
{
 | 
			
		||||
	if (maxExc <= 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
	return rand() % maxExc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Calc::rand_int()
 | 
			
		||||
{
 | 
			
		||||
	return rand();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float Calc::approach(float t, float target, float delta)
 | 
			
		||||
{
 | 
			
		||||
	return t < target ? min(t + delta, target) : max(t - delta, target);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Vec2 Calc::approach(const Vec2& t, const Vec2& target, float delta)
 | 
			
		||||
{
 | 
			
		||||
	if ((target - t).length() <= delta)
 | 
			
		||||
		return target;
 | 
			
		||||
	return t + (target - t).normal() * delta;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float Calc::map(float t, float old_min, float old_max, float new_min, float new_max)
 | 
			
		||||
{
 | 
			
		||||
	return new_min + ((t - old_min) / (old_max - old_min)) * (new_max - new_min);
 | 
			
		||||
 | 
			
		||||
@ -30,4 +30,14 @@ String Color::to_hex_rgb() const
 | 
			
		||||
	str[4] = hex[(b & 0xF0) >> 4];
 | 
			
		||||
	str[5] = hex[(b & 0x0F) >> 0];
 | 
			
		||||
	return str;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
const Color Color::red = Color(255, 0, 0, 255);
 | 
			
		||||
const Color Color::green = Color(0, 255, 0, 255);
 | 
			
		||||
const Color Color::blue = Color(0, 0, 255, 255);
 | 
			
		||||
const Color Color::yellow = Color(255, 255, 0, 255);
 | 
			
		||||
const Color Color::purple = Color(255, 0, 255, 255);
 | 
			
		||||
const Color Color::teal = Color(0, 255, 255, 255);
 | 
			
		||||
@ -1,133 +0,0 @@
 | 
			
		||||
#include <blah/numerics/line.h>
 | 
			
		||||
#include <blah/numerics/rect.h>
 | 
			
		||||
#include <blah/numerics/vec2.h>
 | 
			
		||||
#include <blah/numerics/calc.h>
 | 
			
		||||
 | 
			
		||||
using namespace Blah;
 | 
			
		||||
 | 
			
		||||
Rect Line::bounds() const
 | 
			
		||||
{
 | 
			
		||||
	Vec2 pos = Vec2(Calc::min(a.x, b.x), Calc::min(a.y, b.y));
 | 
			
		||||
 | 
			
		||||
	return Rect(
 | 
			
		||||
		pos,
 | 
			
		||||
		Vec2(Calc::max(a.x, b.x) - pos.x, Calc::max(a.y, b.y) - pos.y)
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Vec2 Line::closest_point(const Vec2& pt) const
 | 
			
		||||
{
 | 
			
		||||
	Vec2 v = b - a;
 | 
			
		||||
	Vec2 w = pt - a;
 | 
			
		||||
	float t = Vec2::dot(w, v) / Vec2::dot(v, v);
 | 
			
		||||
	t = Calc::clamp(t, 0.0f, 1.0f);
 | 
			
		||||
 | 
			
		||||
	return v * t + a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Line::intersects(const Rect& rect) const
 | 
			
		||||
{
 | 
			
		||||
	char ca = rect.get_sector(a);
 | 
			
		||||
	char cb = rect.get_sector(b);
 | 
			
		||||
 | 
			
		||||
	if (ca == cb || (ca & cb) != 0)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	char both = ca | cb;
 | 
			
		||||
 | 
			
		||||
	// top
 | 
			
		||||
	if ((both & 0b0100) != 0 && intersects(rect.top_line()))
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	// bottom
 | 
			
		||||
	if ((both & 0b1000) != 0 && intersects(rect.bottom_line()))
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	// left
 | 
			
		||||
	if ((both & 0b0001) != 0 && intersects(rect.left_line()))
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	// right
 | 
			
		||||
	if ((both & 0b0010) != 0 && intersects(rect.right_line()))
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Line::intersects(const Rect& rect, Vec2* out_intersection_point) const
 | 
			
		||||
{
 | 
			
		||||
	char ca = rect.get_sector(a);
 | 
			
		||||
	char cb = rect.get_sector(b);
 | 
			
		||||
 | 
			
		||||
	if (ca == cb || (ca & cb) != 0)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	char both = ca | cb;
 | 
			
		||||
 | 
			
		||||
	// top
 | 
			
		||||
	if ((both & 0b0100) != 0 && intersects(rect.top_line(), out_intersection_point))
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	// bottom
 | 
			
		||||
	if ((both & 0b1000) != 0 && intersects(rect.bottom_line(), out_intersection_point))
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	// left
 | 
			
		||||
	if ((both & 0b0001) != 0 && intersects(rect.left_line(), out_intersection_point))
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	// right
 | 
			
		||||
	if ((both & 0b0010) != 0 && intersects(rect.right_line(), out_intersection_point))
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Line::intersects(const Line& line) const
 | 
			
		||||
{
 | 
			
		||||
	Vec2 e = b - a;
 | 
			
		||||
	Vec2 d = line.b - line.a;
 | 
			
		||||
	float e_dot_d_perp = e.x * d.y - e.y * d.x;
 | 
			
		||||
 | 
			
		||||
	// if e dot d == 0, it means the lines are parallel
 | 
			
		||||
	// so have infinite intersection points
 | 
			
		||||
	if (e_dot_d_perp < 0.0001 && e_dot_d_perp > -0.0001)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	Vec2 c = line.a - a;
 | 
			
		||||
	float t = (c.x * d.y - c.y * d.x) / e_dot_d_perp;
 | 
			
		||||
	if (t < 0 || t > 1)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	float u = (c.x * e.y - c.y * e.x) / e_dot_d_perp;
 | 
			
		||||
	if (u < 0 || u > 1)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Line::intersects(const Line& line, Vec2* intersection_point) const
 | 
			
		||||
{
 | 
			
		||||
	Vec2 e = b - a;
 | 
			
		||||
	Vec2 d = line.b - line.a;
 | 
			
		||||
	float e_dot_d_perp = e.x * d.y - e.y * d.x;
 | 
			
		||||
 | 
			
		||||
	// if e dot d == 0, it means the lines are parallel
 | 
			
		||||
	// so have infinite intersection points
 | 
			
		||||
	if (e_dot_d_perp < 0.0001 && e_dot_d_perp > -0.0001)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	Vec2 c = line.a - a;
 | 
			
		||||
	float t = (c.x * d.y - c.y * d.x) / e_dot_d_perp;
 | 
			
		||||
	if (t < 0 || t > 1)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	float u = (c.x * e.y - c.y * e.x) / e_dot_d_perp;
 | 
			
		||||
	if (u < 0 || u > 1)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	Vec2 i = (e * t) + a;
 | 
			
		||||
	intersection_point->x = i.x;
 | 
			
		||||
	intersection_point->y = i.y;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
@ -1,95 +0,0 @@
 | 
			
		||||
#include <blah/numerics/mat3x2.h>
 | 
			
		||||
#include <blah/numerics/vec2.h>
 | 
			
		||||
#include <blah/numerics/calc.h>
 | 
			
		||||
 | 
			
		||||
using namespace Blah;
 | 
			
		||||
 | 
			
		||||
float Mat3x2::scaling_factor() const
 | 
			
		||||
{
 | 
			
		||||
	return Calc::sqrt(m11 * m11 + m12 * m12);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat3x2 Mat3x2::create_translation(const Vec2& position)
 | 
			
		||||
{
 | 
			
		||||
	return create_translation(position.x, position.y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat3x2 Mat3x2::create_scale(const Vec2& scale)
 | 
			
		||||
{
 | 
			
		||||
	return create_scale(scale.x, scale.y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat3x2 Mat3x2::create_scale(float scale, const Vec2& center_point)
 | 
			
		||||
{
 | 
			
		||||
	Mat3x2 result;
 | 
			
		||||
 | 
			
		||||
	float tx = center_point.x * (1 - scale);
 | 
			
		||||
	float ty = center_point.y * (1 - scale);
 | 
			
		||||
 | 
			
		||||
	result.m11 = scale;
 | 
			
		||||
	result.m12 = 0.0f;
 | 
			
		||||
	result.m21 = 0.0f;
 | 
			
		||||
	result.m22 = scale;
 | 
			
		||||
	result.m31 = tx;
 | 
			
		||||
	result.m32 = ty;
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat3x2 Mat3x2::create_scale(const Vec2& scale, const Vec2& center_point)
 | 
			
		||||
{
 | 
			
		||||
	Mat3x2 result;
 | 
			
		||||
 | 
			
		||||
	float tx = center_point.x * (1 - scale.x);
 | 
			
		||||
	float ty = center_point.y * (1 - scale.y);
 | 
			
		||||
 | 
			
		||||
	result.m11 = scale.x;
 | 
			
		||||
	result.m12 = 0.0f;
 | 
			
		||||
	result.m21 = 0.0f;
 | 
			
		||||
	result.m22 = scale.y;
 | 
			
		||||
	result.m31 = tx;
 | 
			
		||||
	result.m32 = ty;
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat3x2 Mat3x2::create_scale(float scale_x, float scale_y, const Vec2& center_point)
 | 
			
		||||
{
 | 
			
		||||
	Mat3x2 result;
 | 
			
		||||
 | 
			
		||||
	float tx = center_point.x * (1 - scale_x);
 | 
			
		||||
	float ty = center_point.y * (1 - scale_y);
 | 
			
		||||
 | 
			
		||||
	result.m11 = scale_x;
 | 
			
		||||
	result.m12 = 0.0f;
 | 
			
		||||
	result.m21 = 0.0f;
 | 
			
		||||
	result.m22 = scale_y;
 | 
			
		||||
	result.m31 = tx;
 | 
			
		||||
	result.m32 = ty;
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat3x2 Mat3x2::create_rotation(float radians)
 | 
			
		||||
{
 | 
			
		||||
	float c = Calc::cos(radians);
 | 
			
		||||
	float s = Calc::sin(radians);
 | 
			
		||||
 | 
			
		||||
	return Mat3x2(c, s, -s, c, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat3x2 Mat3x2::create_transform(const Vec2& position, const Vec2& origin, const Vec2& scale, float rotation)
 | 
			
		||||
{
 | 
			
		||||
	Mat3x2 matrix = identity;
 | 
			
		||||
 | 
			
		||||
	if (origin.x != 0 || origin.y != 0)
 | 
			
		||||
		matrix = create_translation(-origin.x, -origin.y);
 | 
			
		||||
	if (scale.x != 1 || scale.y != 1)
 | 
			
		||||
		matrix = matrix * create_scale(scale);
 | 
			
		||||
	if (rotation != 0)
 | 
			
		||||
		matrix = matrix * create_rotation(rotation);
 | 
			
		||||
	if (position.x != 0 || position.y != 0)
 | 
			
		||||
		matrix = matrix * create_translation(position);
 | 
			
		||||
	
 | 
			
		||||
	return matrix;
 | 
			
		||||
}
 | 
			
		||||
@ -1,161 +0,0 @@
 | 
			
		||||
#include <blah/numerics/mat4x4.h>
 | 
			
		||||
#include <blah/common.h>
 | 
			
		||||
 | 
			
		||||
using namespace Blah;
 | 
			
		||||
 | 
			
		||||
Mat4x4::Mat4x4() :
 | 
			
		||||
	m11(0.0f), m12(0.0f), m13(0.0f), m14(0.0f),
 | 
			
		||||
	m21(0.0f), m22(0.0f), m23(0.0f), m24(0.0f),
 | 
			
		||||
	m31(0.0f), m32(0.0f), m33(0.0f), m34(0.0f),
 | 
			
		||||
	m41(0.0f), m42(0.0f), m43(0.0f), m44(0.0f) {}
 | 
			
		||||
 | 
			
		||||
Mat4x4::Mat4x4(
 | 
			
		||||
	float m11, float m12, float m13, float m14,
 | 
			
		||||
	float m21, float m22, float m23, float m24,
 | 
			
		||||
	float m31, float m32, float m33, float m34,
 | 
			
		||||
	float m41, float m42, float m43, float m44) :
 | 
			
		||||
	m11(m11), m12(m12), m13(m13), m14(m14),
 | 
			
		||||
	m21(m21), m22(m22), m23(m23), m24(m24),
 | 
			
		||||
	m31(m31), m32(m32), m33(m33), m34(m34),
 | 
			
		||||
	m41(m41), m42(m42), m43(m43), m44(m44) {}
 | 
			
		||||
 | 
			
		||||
const Mat4x4 Mat4x4::identity = Mat4x4(
 | 
			
		||||
	1.0f, 0.0f, 0.0f, 0.0f,
 | 
			
		||||
	0.0f, 1.0f, 0.0f, 0.0f,
 | 
			
		||||
	0.0f, 0.0f, 1.0f, 0.0f,
 | 
			
		||||
	0.0f, 0.0f, 0.0f, 1.0f);
 | 
			
		||||
 | 
			
		||||
Mat4x4 Mat4x4::create_ortho(float width, float height, float z_near_plane, float z_far_plane)
 | 
			
		||||
{
 | 
			
		||||
	Mat4x4 result = identity;
 | 
			
		||||
 | 
			
		||||
	result.m11 = 2.0f / width;
 | 
			
		||||
	result.m12 = result.m13 = result.m14 = 0.0f;
 | 
			
		||||
	result.m22 = -2.0f / height;
 | 
			
		||||
	result.m21 = result.m23 = result.m24 = 0.0f;
 | 
			
		||||
	result.m33 = 1.0f / (z_near_plane - z_far_plane);
 | 
			
		||||
	result.m31 = result.m32 = result.m34 = 0.0f;
 | 
			
		||||
	result.m41 = result.m42 = 0.0f;
 | 
			
		||||
	result.m43 = z_near_plane / (z_near_plane - z_far_plane);
 | 
			
		||||
	result.m44 = 1.0f;
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat4x4 Mat4x4::create_ortho_offcenter(float left, float right, float bottom, float top, float z_near_plane, float z_far_plane)
 | 
			
		||||
{
 | 
			
		||||
	Mat4x4 result = identity;
 | 
			
		||||
 | 
			
		||||
	result.m11 = 2.0f / (right - left);
 | 
			
		||||
	result.m12 = result.m13 = result.m14 = 0.0f;
 | 
			
		||||
	result.m22 = 2.0f / (top - bottom);
 | 
			
		||||
	result.m21 = result.m23 = result.m24 = 0.0f;
 | 
			
		||||
	result.m33 = 1.0f / (z_near_plane - z_far_plane);
 | 
			
		||||
	result.m31 = result.m32 = result.m34 = 0.0f;
 | 
			
		||||
	result.m41 = (left + right) / (left - right);
 | 
			
		||||
	result.m42 = (top + bottom) / (bottom - top);
 | 
			
		||||
	result.m43 = z_near_plane / (z_near_plane - z_far_plane);
 | 
			
		||||
	result.m44 = 1.0f;
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat4x4 Mat4x4::create_perspective(float field_of_view, float ratio, float z_near_plane, float z_far_plane)
 | 
			
		||||
{
 | 
			
		||||
	float yScale = 1.0f / (float)Calc::tan(field_of_view * 0.5f);
 | 
			
		||||
	float xScale = yScale / ratio;
 | 
			
		||||
 | 
			
		||||
	Mat4x4 result;
 | 
			
		||||
 | 
			
		||||
	result.m11 = xScale;
 | 
			
		||||
	result.m12 = result.m13 = result.m14 = 0.0f;
 | 
			
		||||
 | 
			
		||||
	result.m22 = yScale;
 | 
			
		||||
	result.m21 = result.m23 = result.m24 = 0.0f;
 | 
			
		||||
 | 
			
		||||
	result.m31 = result.m32 = 0.0f;
 | 
			
		||||
	result.m33 = z_far_plane / (z_near_plane - z_far_plane);
 | 
			
		||||
	result.m34 = -1.0f;
 | 
			
		||||
 | 
			
		||||
	result.m41 = result.m42 = result.m44 = 0.0f;
 | 
			
		||||
	result.m43 = z_near_plane * z_far_plane / (z_near_plane - z_far_plane);
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat4x4 Mat4x4::create_translation(float x, float y, float z)
 | 
			
		||||
{
 | 
			
		||||
	Mat4x4 result = identity;
 | 
			
		||||
 | 
			
		||||
	result.m41 = x;
 | 
			
		||||
	result.m42 = y;
 | 
			
		||||
	result.m43 = z;
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat4x4 Mat4x4::create_scale(float x, float y, float z)
 | 
			
		||||
{
 | 
			
		||||
	Mat4x4 result = identity;
 | 
			
		||||
 | 
			
		||||
	result.m11 = x;
 | 
			
		||||
	result.m22 = y;
 | 
			
		||||
	result.m33 = z;
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat4x4 Mat4x4::create_lookat(Vec3 position, Vec3 target, Vec3 up)
 | 
			
		||||
{
 | 
			
		||||
	Vec3 zaxis = (position - target).normal();
 | 
			
		||||
	Vec3 xaxis = Vec3::cross(up, zaxis).normal();
 | 
			
		||||
	Vec3 yaxis = Vec3::cross(zaxis, xaxis);
 | 
			
		||||
 | 
			
		||||
	Mat4x4 result;
 | 
			
		||||
 | 
			
		||||
	result.m11 = xaxis.x;
 | 
			
		||||
	result.m12 = yaxis.x;
 | 
			
		||||
	result.m13 = zaxis.x;
 | 
			
		||||
	result.m14 = 0.0f;
 | 
			
		||||
	result.m21 = xaxis.y;
 | 
			
		||||
	result.m22 = yaxis.y;
 | 
			
		||||
	result.m23 = zaxis.y;
 | 
			
		||||
	result.m24 = 0.0f;
 | 
			
		||||
	result.m31 = xaxis.z;
 | 
			
		||||
	result.m32 = yaxis.z;
 | 
			
		||||
	result.m33 = zaxis.z;
 | 
			
		||||
	result.m34 = 0.0f;
 | 
			
		||||
	result.m41 = -Vec3::dot(xaxis, position);
 | 
			
		||||
	result.m42 = -Vec3::dot(yaxis, position);
 | 
			
		||||
	result.m43 = -Vec3::dot(zaxis, position);
 | 
			
		||||
	result.m44 = 1.0f;
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Mat4x4 Mat4x4::operator*(const Mat4x4& rhs)
 | 
			
		||||
{
 | 
			
		||||
	Mat4x4 m;
 | 
			
		||||
 | 
			
		||||
	m.m11 = m11 * rhs.m11 + m12 * rhs.m21 + m13 * rhs.m31 + m14 * rhs.m41;
 | 
			
		||||
	m.m12 = m11 * rhs.m12 + m12 * rhs.m22 + m13 * rhs.m32 + m14 * rhs.m42;
 | 
			
		||||
	m.m13 = m11 * rhs.m13 + m12 * rhs.m23 + m13 * rhs.m33 + m14 * rhs.m43;
 | 
			
		||||
	m.m14 = m11 * rhs.m14 + m12 * rhs.m24 + m13 * rhs.m34 + m14 * rhs.m44;
 | 
			
		||||
 | 
			
		||||
	m.m21 = m21 * rhs.m11 + m22 * rhs.m21 + m23 * rhs.m31 + m24 * rhs.m41;
 | 
			
		||||
	m.m22 = m21 * rhs.m12 + m22 * rhs.m22 + m23 * rhs.m32 + m24 * rhs.m42;
 | 
			
		||||
	m.m23 = m21 * rhs.m13 + m22 * rhs.m23 + m23 * rhs.m33 + m24 * rhs.m43;
 | 
			
		||||
	m.m24 = m21 * rhs.m14 + m22 * rhs.m24 + m23 * rhs.m34 + m24 * rhs.m44;
 | 
			
		||||
 | 
			
		||||
	m.m31 = m31 * rhs.m11 + m32 * rhs.m21 + m33 * rhs.m31 + m34 * rhs.m41;
 | 
			
		||||
	m.m32 = m31 * rhs.m12 + m32 * rhs.m22 + m33 * rhs.m32 + m34 * rhs.m42;
 | 
			
		||||
	m.m33 = m31 * rhs.m13 + m32 * rhs.m23 + m33 * rhs.m33 + m34 * rhs.m43;
 | 
			
		||||
	m.m34 = m31 * rhs.m14 + m32 * rhs.m24 + m33 * rhs.m34 + m34 * rhs.m44;
 | 
			
		||||
 | 
			
		||||
	m.m41 = m41 * rhs.m11 + m42 * rhs.m21 + m43 * rhs.m31 + m44 * rhs.m41;
 | 
			
		||||
	m.m42 = m41 * rhs.m12 + m42 * rhs.m22 + m43 * rhs.m32 + m44 * rhs.m42;
 | 
			
		||||
	m.m43 = m41 * rhs.m13 + m42 * rhs.m23 + m43 * rhs.m33 + m44 * rhs.m43;
 | 
			
		||||
	m.m44 = m41 * rhs.m14 + m42 * rhs.m24 + m43 * rhs.m34 + m44 * rhs.m44;
 | 
			
		||||
 | 
			
		||||
	return m;
 | 
			
		||||
}
 | 
			
		||||
@ -1,61 +0,0 @@
 | 
			
		||||
#include <blah/numerics/rect.h>
 | 
			
		||||
#include <blah/numerics/calc.h>
 | 
			
		||||
 | 
			
		||||
using namespace Blah;
 | 
			
		||||
 | 
			
		||||
Rect Rect::overlap_rect(const Rect& against) const
 | 
			
		||||
{
 | 
			
		||||
	Rect result(0, 0, 0, 0);
 | 
			
		||||
 | 
			
		||||
	if (x + w >= against.x && x < against.x + against.w)
 | 
			
		||||
	{
 | 
			
		||||
		result.x = Calc::max(x, against.x);
 | 
			
		||||
		result.w = Calc::min(x + w, against.x + against.w) - result.x;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (y + h >= against.y && y < against.y + against.h)
 | 
			
		||||
	{
 | 
			
		||||
		result.y = Calc::max(y, against.y);
 | 
			
		||||
		result.h = Calc::min(y + h, against.y + against.h) - result.y;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Rect::intersects(const Line& line) const
 | 
			
		||||
{
 | 
			
		||||
	return line.intersects(*this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Rect::intersects(const Line& line, Vec2* out_intersection_point) const
 | 
			
		||||
{
 | 
			
		||||
	return line.intersects(*this, out_intersection_point);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Rect::intersects(const Vec2& line_from, const Vec2& line_to) const
 | 
			
		||||
{
 | 
			
		||||
	return intersects(Line(line_from, line_to));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Rect::intersects(const Vec2& line_from, const Vec2& line_to, Vec2* out_intersection_point) const
 | 
			
		||||
{
 | 
			
		||||
	return intersects(Line(line_from, line_to), out_intersection_point);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Vec2 Rect::intersection_point(const Line& line) const
 | 
			
		||||
{
 | 
			
		||||
	Vec2 ret;
 | 
			
		||||
	if (line.intersects(*this, &ret))
 | 
			
		||||
		return ret;
 | 
			
		||||
	else
 | 
			
		||||
		return Vec2::zero;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Vec2 Rect::intersection_point(const Vec2& line_from, const Vec2& line_to) const
 | 
			
		||||
{
 | 
			
		||||
	Vec2 ret;
 | 
			
		||||
	if (Line(line_from, line_to).intersects(*this, &ret))
 | 
			
		||||
		return ret;
 | 
			
		||||
	else
 | 
			
		||||
		return Vec2::zero;
 | 
			
		||||
}
 | 
			
		||||
@ -1,202 +0,0 @@
 | 
			
		||||
#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;
 | 
			
		||||
 | 
			
		||||
RectI::RectI()
 | 
			
		||||
{
 | 
			
		||||
	x = y = w = h = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RectI::RectI(int rx, int ry, int rw, int rh)
 | 
			
		||||
{
 | 
			
		||||
	x = rx;
 | 
			
		||||
	y = ry;
 | 
			
		||||
	w = rw;
 | 
			
		||||
	h = rh;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RectI::RectI(Point pos, Point size)
 | 
			
		||||
{
 | 
			
		||||
	x = pos.x;
 | 
			
		||||
	y = pos.y;
 | 
			
		||||
	w = size.x;
 | 
			
		||||
	h = size.y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int RectI::left() const
 | 
			
		||||
{
 | 
			
		||||
	return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int RectI::right() const
 | 
			
		||||
{
 | 
			
		||||
	return x + w;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int RectI::top() const
 | 
			
		||||
{
 | 
			
		||||
	return y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int RectI::bottom() const
 | 
			
		||||
{
 | 
			
		||||
	return y + h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int RectI::center_x() const
 | 
			
		||||
{
 | 
			
		||||
	return x + w / 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int RectI::center_y() const
 | 
			
		||||
{
 | 
			
		||||
	return y + h / 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Point RectI::center() const
 | 
			
		||||
{
 | 
			
		||||
	return Point(x + w / 2, y + h / 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Point RectI::top_left() const
 | 
			
		||||
{
 | 
			
		||||
	return Point(x, y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Point RectI::top_right() const
 | 
			
		||||
{
 | 
			
		||||
	return Point(x + w, y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Point RectI::bottom_left() const
 | 
			
		||||
{
 | 
			
		||||
	return Point(x, y + h);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Point RectI::bottom_right() const
 | 
			
		||||
{
 | 
			
		||||
	return Point(x + w, y + h);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RectI::overlaps(const RectI& other) const
 | 
			
		||||
{
 | 
			
		||||
	return x < other.x + other.w
 | 
			
		||||
		&& other.x < x + w
 | 
			
		||||
		&& y < other.y + other.h
 | 
			
		||||
		&& other.y < y + h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RectI RectI::overlap_rect(const Rect& against) const
 | 
			
		||||
{
 | 
			
		||||
	RectI result = *this;
 | 
			
		||||
 | 
			
		||||
	if (x + w >= against.x && x < against.x + against.w)
 | 
			
		||||
	{
 | 
			
		||||
		result.x = Calc::max(x, (int)against.x);
 | 
			
		||||
		result.w = Calc::min(x + w, (int)(against.x + against.w)) - result.x;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (y + h >= against.y && y < against.y + against.h)
 | 
			
		||||
	{
 | 
			
		||||
		result.y = Calc::max(y, (int)against.y);
 | 
			
		||||
		result.h = Calc::min(y + h, (int)(against.y + against.h)) - result.y;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RectI::contains(const Point& point) const
 | 
			
		||||
{
 | 
			
		||||
	return point.x >= x && point.x < x + w && point.y >= y && point.y < y + h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RectI::contains(const Vec2& point) const
 | 
			
		||||
{
 | 
			
		||||
	return point.x >= x && point.x < x + w && point.y >= y && point.y < y + h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char RectI::get_sector(const Point& pt) const
 | 
			
		||||
{
 | 
			
		||||
	char h;
 | 
			
		||||
	if (pt.x < left())
 | 
			
		||||
		h = 0b0001;
 | 
			
		||||
	else if (pt.x >= right())
 | 
			
		||||
		h = 0b0010;
 | 
			
		||||
	else
 | 
			
		||||
		h = 0;
 | 
			
		||||
 | 
			
		||||
	char v;
 | 
			
		||||
	if (pt.y < top())
 | 
			
		||||
		v = 0b0100;
 | 
			
		||||
	else if (pt.y >= bottom())
 | 
			
		||||
		v = 0b1000;
 | 
			
		||||
	else
 | 
			
		||||
		v = 0;
 | 
			
		||||
 | 
			
		||||
	return h | v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char RectI::get_sector(const Vec2& pt) const
 | 
			
		||||
{
 | 
			
		||||
	char h;
 | 
			
		||||
	if (pt.x < left())
 | 
			
		||||
		h = 0b0001;
 | 
			
		||||
	else if (pt.x >= right())
 | 
			
		||||
		h = 0b0010;
 | 
			
		||||
	else
 | 
			
		||||
		h = 0;
 | 
			
		||||
 | 
			
		||||
	char v;
 | 
			
		||||
	if (pt.y < top())
 | 
			
		||||
		v = 0b0100;
 | 
			
		||||
	else if (pt.y >= bottom())
 | 
			
		||||
		v = 0b1000;
 | 
			
		||||
	else
 | 
			
		||||
		v = 0;
 | 
			
		||||
 | 
			
		||||
	return h | v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RectI::operator==(const RectI& rhs) const
 | 
			
		||||
{
 | 
			
		||||
	return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RectI::operator!=(const RectI& rhs) const
 | 
			
		||||
{
 | 
			
		||||
	return !(*this == rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RectI RectI::operator+(const Point& rhs) const
 | 
			
		||||
{
 | 
			
		||||
	return RectI(x + rhs.x, y + rhs.y, w, h);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RectI RectI::operator-(const Point& rhs) const
 | 
			
		||||
{
 | 
			
		||||
	return RectI(x - rhs.x, y - rhs.y, w, h);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RectI RectI::operator*(const int& rhs) const
 | 
			
		||||
{
 | 
			
		||||
	return RectI(x * rhs, y * rhs, w * rhs, h * rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RectI RectI::operator/(const int& rhs) const
 | 
			
		||||
{
 | 
			
		||||
	return RectI(x / rhs, y / rhs, w / rhs, h / rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RectI& RectI::operator+=(const Point& rhs)
 | 
			
		||||
{
 | 
			
		||||
	x += rhs.x; y += rhs.y; return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RectI& RectI::operator-=(const Point& rhs)
 | 
			
		||||
{
 | 
			
		||||
	x -= rhs.x; y -= rhs.y; return *this;
 | 
			
		||||
}
 | 
			
		||||
@ -6,7 +6,7 @@ using namespace Blah;
 | 
			
		||||
MemoryStream::MemoryStream()
 | 
			
		||||
	: m_data(nullptr), m_length(0), m_position(0) {}
 | 
			
		||||
 | 
			
		||||
MemoryStream::MemoryStream(char* data, size_t length)
 | 
			
		||||
MemoryStream::MemoryStream(unsigned char* data, size_t length)
 | 
			
		||||
	: m_data(data), m_length(length), m_position(0) {}
 | 
			
		||||
 | 
			
		||||
MemoryStream::MemoryStream(MemoryStream&& src) noexcept
 | 
			
		||||
@ -89,12 +89,12 @@ void MemoryStream::close()
 | 
			
		||||
	m_data = nullptr; m_length = m_position = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* MemoryStream::data()
 | 
			
		||||
unsigned char* MemoryStream::data()
 | 
			
		||||
{
 | 
			
		||||
	return m_data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* MemoryStream::data() const
 | 
			
		||||
const unsigned char* MemoryStream::data() const
 | 
			
		||||
{
 | 
			
		||||
	return m_data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -65,12 +65,12 @@ void Stopwatch::reset()
 | 
			
		||||
	start_time = std::chrono::duration_cast<std::chrono::microseconds>(system_clock::now().time_since_epoch()).count();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 Stopwatch::milliseconds()
 | 
			
		||||
u64 Stopwatch::milliseconds() const
 | 
			
		||||
{
 | 
			
		||||
	return microseconds() / 1000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 Stopwatch::microseconds()
 | 
			
		||||
u64 Stopwatch::microseconds() const
 | 
			
		||||
{
 | 
			
		||||
	return std::chrono::duration_cast<std::chrono::microseconds>(system_clock::now().time_since_epoch()).count() - start_time;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user