mirror of
https://github.com/NoelFB/blah.git
synced 2025-06-29 19:25:26 +08:00
restructured project to match a more standard cmake setup
This commit is contained in:
54
include/blah.h
Normal file
54
include/blah.h
Normal file
@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "blah/core/app.h"
|
||||
#include "blah/core/filesystem.h"
|
||||
#include "blah/core/log.h"
|
||||
#include "blah/core/time.h"
|
||||
|
||||
#include "blah/containers/vector.h"
|
||||
#include "blah/containers/stackvector.h"
|
||||
#include "blah/containers/str.h"
|
||||
|
||||
#include "blah/drawing/batch.h"
|
||||
#include "blah/drawing/spritefont.h"
|
||||
#include "blah/drawing/subtexture.h"
|
||||
|
||||
#include "blah/graphics/blend.h"
|
||||
#include "blah/graphics/framebuffer.h"
|
||||
#include "blah/graphics/material.h"
|
||||
#include "blah/graphics/mesh.h"
|
||||
#include "blah/graphics/renderpass.h"
|
||||
#include "blah/graphics/sampler.h"
|
||||
#include "blah/graphics/shader.h"
|
||||
#include "blah/graphics/texture.h"
|
||||
|
||||
#include "blah/images/aseprite.h"
|
||||
#include "blah/images/font.h"
|
||||
#include "blah/images/image.h"
|
||||
#include "blah/images/packer.h"
|
||||
|
||||
#include "blah/input/input.h"
|
||||
#include "blah/input/virtual_stick.h"
|
||||
#include "blah/input/virtual_button.h"
|
||||
#include "blah/input/virtual_axis.h"
|
||||
|
||||
#include "blah/math/calc.h"
|
||||
#include "blah/math/circle.h"
|
||||
#include "blah/math/color.h"
|
||||
#include "blah/math/ease.h"
|
||||
#include "blah/math/line.h"
|
||||
#include "blah/math/mat3x2.h"
|
||||
#include "blah/math/mat4x4.h"
|
||||
#include "blah/math/point.h"
|
||||
#include "blah/math/quad.h"
|
||||
#include "blah/math/rect.h"
|
||||
#include "blah/math/rectI.h"
|
||||
#include "blah/math/stopwatch.h"
|
||||
#include "blah/math/vec2.h"
|
||||
#include "blah/math/vec4.h"
|
||||
|
||||
#include "blah/streams/bufferstream.h"
|
||||
#include "blah/streams/filestream.h"
|
||||
#include "blah/streams/memorystream.h"
|
||||
#include "blah/streams/stream.h"
|
||||
#include "blah/streams/endian.h"
|
279
include/blah/containers/stackvector.h
Normal file
279
include/blah/containers/stackvector.h
Normal file
@ -0,0 +1,279 @@
|
||||
#pragma once
|
||||
#include <blah/core/log.h>
|
||||
#include <new>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
// A mix between an std::vector and an std::array
|
||||
// The goal is to have an std::vector implementation that lives
|
||||
// on the stack instead of the heap
|
||||
template<class T, size_t Capacity>
|
||||
class StackVector
|
||||
{
|
||||
private:
|
||||
char m_buffer[sizeof(T) * Capacity];
|
||||
int m_count;
|
||||
|
||||
public:
|
||||
static inline constexpr size_t MaxCapacity = Capacity;
|
||||
|
||||
StackVector();
|
||||
StackVector(const std::initializer_list<T>& init);
|
||||
StackVector(const StackVector& src);
|
||||
StackVector(StackVector&& src) noexcept;
|
||||
~StackVector();
|
||||
|
||||
StackVector& operator=(const StackVector& src);
|
||||
StackVector& operator=(StackVector&& src) noexcept;
|
||||
|
||||
void clear();
|
||||
|
||||
int size() const;
|
||||
constexpr int capacity() { return Capacity; }
|
||||
|
||||
T* expand(int amount = 1);
|
||||
void push_back(const T& item);
|
||||
void push_back(T&& item);
|
||||
template<class ...Args>
|
||||
void emplace_back(Args&&...args);
|
||||
|
||||
T& operator[](int index);
|
||||
const T& operator[](int index) const;
|
||||
|
||||
T* data();
|
||||
const T* data() const;
|
||||
T* begin();
|
||||
const T* begin() const;
|
||||
T* end();
|
||||
const T* end() const;
|
||||
T& front();
|
||||
const T& front() const;
|
||||
T& back();
|
||||
const T& back() const;
|
||||
|
||||
void erase(int index, int elements = 1);
|
||||
T pop();
|
||||
};
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline StackVector<T, Capacity>::StackVector()
|
||||
{
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline StackVector<T, Capacity>::StackVector(const std::initializer_list<T>& init)
|
||||
{
|
||||
m_count = 0;
|
||||
for (auto& it : init)
|
||||
push_back(it);
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline StackVector<T, Capacity>::StackVector(const StackVector& src)
|
||||
{
|
||||
for (int i = 0; i < src.m_count; i++)
|
||||
new (data() + i) T(src.data()[i]);
|
||||
m_count = src.m_count;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline StackVector<T, Capacity>::StackVector(StackVector&& src) noexcept
|
||||
{
|
||||
for (int i = 0; i < src.m_count; i++)
|
||||
new (data() + i) T(std::move(src.data()[i]));
|
||||
m_count = src.m_count;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline StackVector<T, Capacity>::~StackVector()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline StackVector<T, Capacity>& StackVector<T, Capacity>::operator=(const StackVector& src)
|
||||
{
|
||||
clear();
|
||||
|
||||
for (int i = 0; i < src.m_count; i++)
|
||||
data()[i] = src.data()[i];
|
||||
m_count = src.m_count;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline StackVector<T, Capacity>& StackVector<T, Capacity>::operator=(StackVector&& src) noexcept
|
||||
{
|
||||
clear();
|
||||
|
||||
for (int i = 0; i < src.m_count; i++)
|
||||
data()[i] = std::move(src.data()[i]);
|
||||
m_count = src.m_count;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline void StackVector<T, Capacity>::clear()
|
||||
{
|
||||
for (int i = 0; i < m_count; i++)
|
||||
data()[i].~T();
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline int StackVector<T, Capacity>::size() const
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline T* StackVector<T, Capacity>::expand(int amount)
|
||||
{
|
||||
BLAH_ASSERT(m_count + amount <= Capacity, "Exceeded StackVector Capacity");
|
||||
|
||||
if (amount > 0)
|
||||
{
|
||||
int count = m_count;
|
||||
|
||||
for (int i = 0; i < amount; i++)
|
||||
new (data() + count + i) T();
|
||||
|
||||
m_count += amount;
|
||||
return &data()[count];
|
||||
}
|
||||
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline void StackVector<T, Capacity>::push_back(const T& item)
|
||||
{
|
||||
BLAH_ASSERT(m_count + 1 <= Capacity, "Exceeded StackVector Capacity");
|
||||
new (data() + m_count) T(item);
|
||||
m_count++;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline void StackVector<T, Capacity>::push_back(T&& item)
|
||||
{
|
||||
BLAH_ASSERT(m_count + 1 <= Capacity, "Exceeded StackVector Capacity");
|
||||
new (data() + m_count) T(std::move(item));
|
||||
m_count++;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
template<class ...Args>
|
||||
inline void StackVector<T, Capacity>::emplace_back(Args && ...args)
|
||||
{
|
||||
BLAH_ASSERT(m_count + 1 <= Capacity, "Exceeded StackVector Capacity");
|
||||
new (data() + m_count) T(std::forward<Args>(args)...);
|
||||
m_count++;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline T& StackVector<T, Capacity>::operator[](int index)
|
||||
{
|
||||
BLAH_ASSERT(index >= 0 && index < m_count, "Index out of range");
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline const T& StackVector<T, Capacity>::operator[](int index) const
|
||||
{
|
||||
BLAH_ASSERT(index >= 0 && index < m_count, "Index out of range");
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline T* StackVector<T, Capacity>::data()
|
||||
{
|
||||
return (T*)m_buffer;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline const T* StackVector<T, Capacity>::data() const
|
||||
{
|
||||
return (T*)m_buffer;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline T* StackVector<T, Capacity>::begin()
|
||||
{
|
||||
return (T*)m_buffer;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline const T* StackVector<T, Capacity>::begin() const
|
||||
{
|
||||
return (T*)m_buffer;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline T* StackVector<T, Capacity>::end()
|
||||
{
|
||||
return ((T*)m_buffer) + m_count;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline const T* StackVector<T, Capacity>::end() const
|
||||
{
|
||||
return ((T*)m_buffer) + m_count;
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline T& StackVector<T, Capacity>::front()
|
||||
{
|
||||
BLAH_ASSERT(m_count > 0, "Index out of range");
|
||||
return data()[0];
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline const T& StackVector<T, Capacity>::front() const
|
||||
{
|
||||
BLAH_ASSERT(m_count > 0, "Index out of range");
|
||||
return data()[0];
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline T& StackVector<T, Capacity>::back()
|
||||
{
|
||||
BLAH_ASSERT(m_count > 0, "Index out of range");
|
||||
return data()[m_count - 1];
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline const T& StackVector<T, Capacity>::back() const
|
||||
{
|
||||
BLAH_ASSERT(m_count > 0, "Index out of range");
|
||||
return data()[m_count - 1];
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline void StackVector<T, Capacity>::erase(int index, int elements)
|
||||
{
|
||||
BLAH_ASSERT(index >= 0 && index + elements <= m_count, "Index out of range");
|
||||
|
||||
if (elements >= 1)
|
||||
{
|
||||
for (int i = index; i < (m_count - elements); i++)
|
||||
data()[i] = std::move(data()[i + elements]);
|
||||
for (int i = m_count - elements; i < m_count; i++)
|
||||
data()[i].~T();
|
||||
m_count -= elements;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, size_t Capacity>
|
||||
inline T StackVector<T, Capacity>::pop()
|
||||
{
|
||||
BLAH_ASSERT(m_count > 0, "Index out of range");
|
||||
|
||||
T value = std::move(data()[m_count - 1]);
|
||||
data()[m_count - 1].~T();
|
||||
m_count--;
|
||||
return value;
|
||||
}
|
||||
}
|
228
include/blah/containers/str.h
Normal file
228
include/blah/containers/str.h
Normal file
@ -0,0 +1,228 @@
|
||||
#pragma once
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <blah/containers/vector.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
template<int T>
|
||||
class StrOf;
|
||||
using String = StrOf<64>;
|
||||
|
||||
class Str
|
||||
{
|
||||
public:
|
||||
Str() { m_buffer = empty_buffer; m_length = m_capacity = m_local_size = 0; }
|
||||
Str(const char* start, const char* end = nullptr) : Str() { set(start, end); }
|
||||
Str(const Str& str) : Str() { set(str); }
|
||||
|
||||
char& operator[](int index) { return data()[index]; }
|
||||
const char& operator[](int index) const { return data()[index]; }
|
||||
|
||||
// equality operators
|
||||
bool operator==(const Str& rhs) const;
|
||||
bool operator!=(const Str& rhs) const;
|
||||
bool operator==(const char* rhs) const;
|
||||
bool operator!=(const char* rhs) const;
|
||||
|
||||
// assignment operator
|
||||
Str& operator=(const Str& rhs) { set(rhs.cstr(), rhs.cstr() + rhs.m_length); return *this; }
|
||||
Str& operator=(const char* rhs) { set(rhs, nullptr); return *this; }
|
||||
|
||||
// append string
|
||||
Str& operator+=(const Str& rhs) { return append(rhs); }
|
||||
|
||||
// append cstr
|
||||
Str& operator+=(const char* rhs) { return append(rhs); }
|
||||
|
||||
// combine string
|
||||
Str operator+(const Str& rhs) { Str str; str.append(*this).append(rhs); return str; }
|
||||
|
||||
// combine cstr
|
||||
Str operator+(const char* rhs) { Str str; str.append(*this).append(rhs); return str; }
|
||||
|
||||
// implicit cast to cstr
|
||||
operator char* () { return cstr(); }
|
||||
|
||||
// implicit cast to cstr
|
||||
operator const char* () const { return cstr(); }
|
||||
|
||||
// returns a pointer to the null-terminated string buffer
|
||||
char* cstr() { return data(); }
|
||||
|
||||
// returns a pointer to the null-terminated string buffer
|
||||
const char* cstr() const { return data(); }
|
||||
|
||||
// returns a pointer to the start of the buffer
|
||||
const char* begin() const { return data(); }
|
||||
|
||||
// returns a pointer to the end of the buffer
|
||||
const char* end() const { return data() + m_length; }
|
||||
|
||||
// returns the length of the string
|
||||
int length() const { return m_length; }
|
||||
|
||||
// returns the capacity of the string
|
||||
int capacity() const { return m_capacity; }
|
||||
|
||||
// returns the capacity of the string's stack buffer
|
||||
int stack_capacity() const { return m_local_size; }
|
||||
|
||||
// sets the length of the string.
|
||||
// this does not set the value of the string!
|
||||
void set_length(int length);
|
||||
|
||||
// ensures the string has the given capacity
|
||||
void reserve(int capacity);
|
||||
|
||||
// appends the given character
|
||||
Str& append(char c);
|
||||
|
||||
// appends the given unicode character
|
||||
Str& append(uint32_t c);
|
||||
|
||||
// appends the given c string
|
||||
Str& append(const char* start, const char* end = nullptr);
|
||||
|
||||
// appends the given string
|
||||
Str& append(const Str& str, int start = 0, int end = -1);
|
||||
|
||||
// appends the given formatted string
|
||||
Str& append_fmt(const char* fmt, ...);
|
||||
|
||||
// appends a utf16 string
|
||||
Str& append_utf16(const uint16_t* start, const uint16_t* end = nullptr, bool swapEndian = false);
|
||||
|
||||
// trims whitespace
|
||||
Str& trim();
|
||||
|
||||
// returns true if the string begins with the given string
|
||||
bool starts_with(const Str& str, bool ignore_case = false) const { return starts_with(str.cstr(), ignore_case); }
|
||||
|
||||
// returns true if the string begins with the given string
|
||||
bool equals(const Str& str, bool ignore_case = false) const { return str.length() == length() && starts_with(str.cstr(), ignore_case); }
|
||||
|
||||
// returns true if the string begins with the given string
|
||||
bool starts_with(const char* str, bool ignore_case = false) const;
|
||||
|
||||
// returns true if the string contains with the given string
|
||||
bool contains(const Str& str, bool ignore_case = false) const { return contains(str.cstr(), ignore_case); }
|
||||
|
||||
// returns true if the string contains with the given string
|
||||
bool contains(const char* str, bool ignore_case = false) const;
|
||||
|
||||
// returns true if the string ends with the given string
|
||||
bool ends_with(const Str& str, bool ignore_case = false) const { return ends_with(str.cstr(), ignore_case); }
|
||||
|
||||
// returns true if the string ends with the given string
|
||||
bool ends_with(const char* str, bool ignore_case = false) const;
|
||||
|
||||
// returns the first index of the given character, or -1 if it isn't found
|
||||
int first_index_of(char ch) const;
|
||||
|
||||
// returns the last index of the given character, or -1 if it isn't found
|
||||
int last_index_of(char ch) const;
|
||||
|
||||
// returns a substring of the string
|
||||
String substr(int start) const;
|
||||
|
||||
// returns a substring of the string
|
||||
String substr(int start, int end) const;
|
||||
|
||||
Vector<String> split(char ch) const;
|
||||
|
||||
Str& replace(const Str& old_str, const Str& new_str);
|
||||
|
||||
// replaces all occurances of the given character in the string
|
||||
Str& replace(char c, char r);
|
||||
|
||||
// checks if the string has a length of 0
|
||||
bool empty() const { return m_length <= 0; }
|
||||
|
||||
// clears the string length to 0
|
||||
void clear();
|
||||
|
||||
// clears and disposes the internal string buffer
|
||||
void dispose();
|
||||
|
||||
~Str()
|
||||
{
|
||||
if (m_buffer != nullptr && m_buffer != empty_buffer)
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
protected:
|
||||
Str(int local_size)
|
||||
{
|
||||
m_buffer = nullptr;
|
||||
m_length = 0;
|
||||
m_capacity = local_size;
|
||||
m_local_size = local_size;
|
||||
}
|
||||
|
||||
// returns a pointer to the heap buffer or to our stack allocation
|
||||
char* data() { return (m_buffer != nullptr ? m_buffer : ((char*)(this) + sizeof(Str))); }
|
||||
const char* data() const { return (m_buffer != nullptr ? m_buffer : ((char*)(this) + sizeof(Str))); }
|
||||
|
||||
void set(const Str& str) { set(str.cstr(), str.cstr() + str.m_length); }
|
||||
void set(const char* start, const char* end = nullptr);
|
||||
|
||||
private:
|
||||
static char empty_buffer[1];
|
||||
char* m_buffer;
|
||||
int m_length;
|
||||
int m_capacity;
|
||||
int m_local_size;
|
||||
};
|
||||
|
||||
// combine string
|
||||
inline Str operator+(const Str& lhs, const Str& rhs) { Str str; str.append(lhs).append(rhs); return str; }
|
||||
|
||||
template<int T>
|
||||
class StrOf : public Str
|
||||
{
|
||||
private:
|
||||
char m_local_buffer[T];
|
||||
|
||||
public:
|
||||
StrOf() : Str(T) { m_local_buffer[0] = '\0'; }
|
||||
StrOf(const char* rhs, const char* end = nullptr) : Str(T) { m_local_buffer[0] = '\0'; set(rhs, end); }
|
||||
StrOf(const Str& rhs) : Str(T) { m_local_buffer[0] = '\0'; set(rhs); }
|
||||
StrOf(const StrOf& rhs) : Str(T) { m_local_buffer[0] = '\0'; set(rhs); }
|
||||
|
||||
// assignment operators
|
||||
StrOf& operator=(const char* rhs) { set(rhs); return *this; }
|
||||
StrOf& operator=(const Str& rhs) { set(rhs); return *this; }
|
||||
StrOf& operator=(const StrOf& rhs) { set(rhs); return *this; }
|
||||
|
||||
// creates a string from the format
|
||||
static StrOf fmt(const char* str, ...);
|
||||
};
|
||||
|
||||
template<int T>
|
||||
StrOf<T> StrOf<T>::fmt(const char* fmt, ...)
|
||||
{
|
||||
StrOf<T> str;
|
||||
|
||||
int add, diff;
|
||||
|
||||
// determine arg length
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
add = vsnprintf(NULL, 0, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
// reserve
|
||||
auto len = str.length();
|
||||
str.set_length(len + add);
|
||||
diff = str.capacity() - len;
|
||||
if (diff <= 0) diff = 0;
|
||||
|
||||
// print out
|
||||
va_start(args, fmt);
|
||||
vsnprintf(str.cstr() + len, (size_t)diff, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
337
include/blah/containers/vector.h
Normal file
337
include/blah/containers/vector.h
Normal file
@ -0,0 +1,337 @@
|
||||
#pragma once
|
||||
#include <blah/core/log.h>
|
||||
#include <type_traits>
|
||||
#include <new>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
template<class T>
|
||||
class Vector
|
||||
{
|
||||
private:
|
||||
T* m_buffer;
|
||||
int m_count;
|
||||
int m_capacity;
|
||||
|
||||
public:
|
||||
|
||||
Vector();
|
||||
Vector(int capacity);
|
||||
Vector(const Vector& src);
|
||||
Vector(Vector&& src) noexcept;
|
||||
~Vector();
|
||||
|
||||
Vector& operator=(const Vector& src);
|
||||
Vector& operator=(Vector&& src) noexcept;
|
||||
|
||||
void clear();
|
||||
void dispose();
|
||||
|
||||
int size() const;
|
||||
int capacity() const;
|
||||
|
||||
void reserve(int new_capacity);
|
||||
void resize(int new_count);
|
||||
T* expand(int amount = 1);
|
||||
|
||||
void push_back(const T& item);
|
||||
void push_back(T&& item);
|
||||
template<class ...Args>
|
||||
void emplace_back(Args&&...args);
|
||||
|
||||
T& operator[](int index);
|
||||
const T& operator[](int index) const;
|
||||
|
||||
T* data();
|
||||
const T* data() const;
|
||||
T* begin();
|
||||
const T* begin() const;
|
||||
T* end();
|
||||
const T* end() const;
|
||||
T& front();
|
||||
const T& front() const;
|
||||
T& back();
|
||||
const T& back() const;
|
||||
|
||||
void erase(int index, int elements = 1);
|
||||
T pop();
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
inline Vector<T>::Vector()
|
||||
{
|
||||
m_buffer = nullptr;
|
||||
m_count = m_capacity = 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline Vector<T>::Vector(int capacity)
|
||||
{
|
||||
m_buffer = nullptr;
|
||||
m_count = m_capacity = 0;
|
||||
reserve(capacity);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline Vector<T>::Vector(const Vector& src)
|
||||
{
|
||||
m_buffer = nullptr;
|
||||
m_count = m_capacity = 0;
|
||||
reserve(src.m_capacity);
|
||||
for (int i = 0; i < src.m_count; i++)
|
||||
m_buffer[i] = src.m_buffer[i];
|
||||
m_count = src.m_count;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline Vector<T>::Vector(Vector&& src) noexcept
|
||||
{
|
||||
m_buffer = src.m_buffer;
|
||||
m_capacity = src.m_capacity;
|
||||
m_count = src.m_count;
|
||||
src.m_buffer = nullptr;
|
||||
src.m_capacity = 0;
|
||||
src.m_count = 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline Vector<T>::~Vector()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline Vector<T>& Vector<T>::operator=(const Vector& src)
|
||||
{
|
||||
clear();
|
||||
reserve(src.m_capacity);
|
||||
for (int i = 0; i < src.m_count; i++)
|
||||
m_buffer[i] = src.m_buffer[i];
|
||||
m_count = src.m_count;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline Vector<T>& Vector<T>::operator=(Vector&& src) noexcept
|
||||
{
|
||||
dispose();
|
||||
m_buffer = src.m_buffer;
|
||||
m_capacity = src.m_capacity;
|
||||
m_count = src.m_count;
|
||||
src.m_buffer = nullptr;
|
||||
src.m_capacity = 0;
|
||||
src.m_count = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Vector<T>::clear()
|
||||
{
|
||||
for (int i = 0; i < m_count; i++)
|
||||
m_buffer[i].~T();
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Vector<T>::dispose()
|
||||
{
|
||||
clear();
|
||||
|
||||
::operator delete (m_buffer, sizeof(T) * m_capacity);
|
||||
|
||||
m_capacity = 0;
|
||||
m_buffer = nullptr;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline int Vector<T>::size() const
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline int Vector<T>::capacity() const
|
||||
{
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Vector<T>::reserve(int cap)
|
||||
{
|
||||
if (cap > m_capacity)
|
||||
{
|
||||
int new_capacity = m_capacity;
|
||||
if (new_capacity <= 0)
|
||||
new_capacity = 8;
|
||||
while (new_capacity < cap)
|
||||
new_capacity *= 2;
|
||||
|
||||
T* new_buffer = (T*)::operator new (sizeof(T) * new_capacity);
|
||||
|
||||
for (int i = 0; i < m_count; i++)
|
||||
{
|
||||
if (i < new_capacity)
|
||||
new (new_buffer + i) T(std::move(m_buffer[i]));
|
||||
m_buffer[i].~T();
|
||||
}
|
||||
|
||||
::operator delete (m_buffer, sizeof(T)* m_capacity);
|
||||
|
||||
m_buffer = new_buffer;
|
||||
m_capacity = new_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Vector<T>::resize(int new_count)
|
||||
{
|
||||
if (new_count < m_count)
|
||||
erase(new_count, m_count - new_count);
|
||||
else
|
||||
expand(new_count - m_count);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T* Vector<T>::expand(int amount)
|
||||
{
|
||||
if (amount > 0)
|
||||
{
|
||||
int count = m_count;
|
||||
|
||||
reserve(count + amount);
|
||||
for (int i = 0; i < amount; i++)
|
||||
new (m_buffer + count + i) T();
|
||||
|
||||
m_count += amount;
|
||||
return &m_buffer[count];
|
||||
}
|
||||
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Vector<T>::push_back(const T& item)
|
||||
{
|
||||
emplace_back(item);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Vector<T>::push_back(T&& item)
|
||||
{
|
||||
emplace_back(std::move(item));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<class ...Args>
|
||||
inline void Vector<T>::emplace_back(Args&& ...args)
|
||||
{
|
||||
reserve(m_count + 1);
|
||||
new (m_buffer + m_count) T(std::forward<Args>(args)...);
|
||||
m_count++;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T& Vector<T>::operator[](int index)
|
||||
{
|
||||
BLAH_ASSERT(index >= 0 && index < m_count, "Index out of range");
|
||||
return m_buffer[index];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline const T& Vector<T>::operator[](int index) const
|
||||
{
|
||||
BLAH_ASSERT(index >= 0 && index < m_count, "Index out of range");
|
||||
return m_buffer[index];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T* Vector<T>::data()
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline const T* Vector<T>::data() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T* Vector<T>::begin()
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline const T* Vector<T>::begin() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T* Vector<T>::end()
|
||||
{
|
||||
return m_buffer + m_count;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline const T* Vector<T>::end() const
|
||||
{
|
||||
return m_buffer + m_count;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T& Vector<T>::front()
|
||||
{
|
||||
BLAH_ASSERT(m_count > 0, "Index out of range");
|
||||
return m_buffer[0];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline const T& Vector<T>::front() const
|
||||
{
|
||||
BLAH_ASSERT(m_count > 0, "Index out of range");
|
||||
return m_buffer[0];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T& Vector<T>::back()
|
||||
{
|
||||
BLAH_ASSERT(m_count > 0, "Index out of range");
|
||||
return m_buffer[m_count - 1];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline const T& Vector<T>::back() const
|
||||
{
|
||||
BLAH_ASSERT(m_count > 0, "Index out of range");
|
||||
return m_buffer[m_count - 1];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Vector<T>::erase(int index, int elements)
|
||||
{
|
||||
BLAH_ASSERT(index >= 0 && index + elements <= m_count, "Index out of range");
|
||||
|
||||
if (elements >= 1)
|
||||
{
|
||||
for (int i = index; i < (m_count - elements); i++)
|
||||
m_buffer[i] = std::move(m_buffer[i + elements]);
|
||||
for (int i = m_count - elements; i < m_count; i++)
|
||||
m_buffer[i].~T();
|
||||
m_count -= elements;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T Vector<T>::pop()
|
||||
{
|
||||
BLAH_ASSERT(m_count > 0, "Index out of range");
|
||||
|
||||
T value = std::move(m_buffer[m_count - 1]);
|
||||
m_buffer[m_count - 1].~T();
|
||||
m_count--;
|
||||
return value;
|
||||
}
|
||||
}
|
93
include/blah/core/app.h
Normal file
93
include/blah/core/app.h
Normal file
@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
struct Config
|
||||
{
|
||||
const char* name;
|
||||
int width;
|
||||
int height;
|
||||
int max_updates;
|
||||
int target_framerate;
|
||||
|
||||
void (*on_startup)();
|
||||
void (*on_shutdown)();
|
||||
void (*on_update)();
|
||||
void (*on_render)();
|
||||
void (*on_exit_request)();
|
||||
|
||||
void (*on_info)(const char* text);
|
||||
void (*on_warn)(const char* text);
|
||||
void (*on_error)(const char* text);
|
||||
|
||||
Config();
|
||||
};
|
||||
|
||||
enum class Renderer
|
||||
{
|
||||
None = -1,
|
||||
OpenGL,
|
||||
D3D11,
|
||||
Metal,
|
||||
Count
|
||||
};
|
||||
|
||||
struct RendererFeatures
|
||||
{
|
||||
bool instancing = false;
|
||||
bool origin_bottom_left = false;
|
||||
int max_texture_size = 0;
|
||||
};
|
||||
|
||||
class FrameBuffer;
|
||||
using FrameBufferRef = std::shared_ptr<FrameBuffer>;
|
||||
|
||||
namespace App
|
||||
{
|
||||
// Runs the application
|
||||
bool run(const Config* config);
|
||||
|
||||
// Returns whether the application is running
|
||||
bool is_running();
|
||||
|
||||
// Exits the application
|
||||
void exit();
|
||||
|
||||
// Gets the config data used to run the application
|
||||
const Config* config();
|
||||
|
||||
// Gets the working path
|
||||
const char* path();
|
||||
|
||||
// Gets the user path
|
||||
const char* user_path();
|
||||
|
||||
// Gets the width of the window
|
||||
int width();
|
||||
|
||||
// Gets the height of the window
|
||||
int height();
|
||||
|
||||
// Gets the drawable width of the window
|
||||
int draw_width();
|
||||
|
||||
// Gets the drawable height of the window
|
||||
int draw_height();
|
||||
|
||||
// Gets the content scale based on the OS
|
||||
float content_scale();
|
||||
|
||||
// Toggles fullscreen
|
||||
void fullscreen(bool enabled);
|
||||
|
||||
// Returns the Rendering API in use
|
||||
Renderer renderer();
|
||||
|
||||
// Retrieves the Renderer Features
|
||||
const RendererFeatures& renderer_features();
|
||||
|
||||
// Reference to the window's back buffer
|
||||
extern const FrameBufferRef backbuffer;
|
||||
}
|
||||
}
|
41
include/blah/core/filesystem.h
Normal file
41
include/blah/core/filesystem.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include <blah/containers/str.h>
|
||||
#include <blah/containers/vector.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
using FilePath = StrOf<265>;
|
||||
|
||||
enum class FileMode
|
||||
{
|
||||
None = 0,
|
||||
Read = 1 << 1,
|
||||
Write = 1 << 2,
|
||||
ReadWrite = Read | Write,
|
||||
};
|
||||
|
||||
namespace Directory
|
||||
{
|
||||
bool create(const FilePath& path);
|
||||
bool exists(const FilePath& path);
|
||||
bool remove(const FilePath& path);
|
||||
Vector<FilePath> enumerate(const FilePath& str, bool recursive = true);
|
||||
void explore(const FilePath& path);
|
||||
}
|
||||
|
||||
namespace File
|
||||
{
|
||||
bool exists(const FilePath& path);
|
||||
bool remove(const FilePath& path);
|
||||
}
|
||||
|
||||
namespace Path
|
||||
{
|
||||
FilePath get_file_name(const FilePath& path);
|
||||
FilePath get_file_name_no_ext(const FilePath& path);
|
||||
FilePath get_path_no_ext(const FilePath& path);
|
||||
FilePath get_path_after(const FilePath& path, const FilePath& after);
|
||||
FilePath get_directory_name(const FilePath& path);
|
||||
FilePath normalize(const FilePath& path);
|
||||
}
|
||||
}
|
39
include/blah/core/log.h
Normal file
39
include/blah/core/log.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
// error / abort
|
||||
#ifdef DEBUG
|
||||
|
||||
#include <stdlib.h>
|
||||
#define BLAH_ERROR(message) \
|
||||
do { Log::error(message "\n\tin file: %s:%d", __FILE__, __LINE__); abort(); } while(0)
|
||||
|
||||
#define BLAH_ERROR_FMT(message, ...) \
|
||||
do { Log::error(message "\n\tin file: %s:%d", __VA_ARGS__, __FILE__, __LINE__); abort(); } while(0)
|
||||
|
||||
#else
|
||||
|
||||
#define BLAH_ERROR(message) \
|
||||
Log::error(message "\n\tin file: %s:%d", __FILE__, __LINE__)
|
||||
|
||||
#define BLAH_ERROR_FMT(message, ...) \
|
||||
Log::error(message "\n\tin file: %s:%d", __VA_ARGS__, __FILE__, __LINE__)
|
||||
|
||||
#endif
|
||||
|
||||
#define BLAH_ASSERT(condition, message) \
|
||||
do { if (!(condition)) { BLAH_ERROR(message); } } while(0)
|
||||
|
||||
// maximum length of a print/warn/error message
|
||||
#ifndef BLAH_MESSAGE
|
||||
#define BLAH_MESSAGE 1024
|
||||
#endif
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
namespace Log
|
||||
{
|
||||
void print(const char* info, ...);
|
||||
void warn(const char* info, ...);
|
||||
void error(const char* info, ...);
|
||||
}
|
||||
}
|
44
include/blah/core/time.h
Normal file
44
include/blah/core/time.h
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
struct Time
|
||||
{
|
||||
// uptime, in milliseconds
|
||||
static uint64_t milliseconds;
|
||||
|
||||
// uptime, in seconds
|
||||
static float elapsed;
|
||||
|
||||
// previous frame uptime, in seconds
|
||||
static float previous_elapsed;
|
||||
|
||||
// delta time from last frame
|
||||
static float delta;
|
||||
|
||||
// time the application should pause for
|
||||
static float pause_timer;
|
||||
|
||||
// pauses the entire application for the given time
|
||||
static void pause_for(float time);
|
||||
|
||||
// returns true on the given time interval
|
||||
static bool on_interval(float time, float delta, float interval, float offset);
|
||||
|
||||
// returns true on the given time interval
|
||||
static bool on_interval(float delta, float interval, float offset);
|
||||
|
||||
// returns true on the given time interval
|
||||
static bool on_interval(float interval, float offset = 0);
|
||||
|
||||
// returns true when the given timestamp is passed
|
||||
static bool on_time(float time, float timestamp);
|
||||
|
||||
// returns true between time intervals
|
||||
static bool between_interval(float time, float interval, float offset);
|
||||
|
||||
// returns true between time intervals
|
||||
static bool between_interval(float interval, float offset = 0);
|
||||
};
|
||||
}
|
237
include/blah/drawing/batch.h
Normal file
237
include/blah/drawing/batch.h
Normal file
@ -0,0 +1,237 @@
|
||||
#pragma once
|
||||
#include <blah/containers/str.h>
|
||||
#include <blah/math/vec2.h>
|
||||
#include <blah/math/rect.h>
|
||||
#include <blah/math/mat3x2.h>
|
||||
#include <blah/math/mat4x4.h>
|
||||
#include <blah/math/color.h>
|
||||
#include <blah/drawing/subtexture.h>
|
||||
#include <blah/drawing/spritefont.h>
|
||||
#include <blah/containers/vector.h>
|
||||
#include <blah/graphics/blend.h>
|
||||
#include <blah/graphics/sampler.h>
|
||||
#include <blah/graphics/renderpass.h>
|
||||
#include <blah/core/app.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
enum class ColorMode
|
||||
{
|
||||
Normal,
|
||||
Wash
|
||||
};
|
||||
|
||||
enum class TextAlign : char
|
||||
{
|
||||
Center = 0,
|
||||
Left = 1 << 1,
|
||||
Right = 1 << 2,
|
||||
Top = 1 << 3,
|
||||
Bottom = 1 << 4,
|
||||
|
||||
TopLeft = Top | Left,
|
||||
TopRight = Top | Right,
|
||||
BottomLeft = Bottom | Left,
|
||||
BottomRight = Bottom | Right
|
||||
};
|
||||
|
||||
inline TextAlign operator|(TextAlign lhs, TextAlign rhs) { return static_cast<TextAlign>(static_cast<char>(lhs) | static_cast<char>(rhs)); }
|
||||
inline TextAlign operator&(TextAlign lhs, TextAlign rhs) { return static_cast<TextAlign>(static_cast<char>(lhs) & static_cast<char>(rhs)); }
|
||||
|
||||
// A simple 2D sprite batcher, used for drawing shapes and textures
|
||||
class Batch
|
||||
{
|
||||
public:
|
||||
|
||||
// The name of the Matrix Uniform in the Shader
|
||||
const char* matrix_uniform;
|
||||
|
||||
// Default Sampler, set on clear
|
||||
TextureSampler default_sampler;
|
||||
|
||||
Batch();
|
||||
Batch(const Batch& other) = delete;
|
||||
Batch& operator=(const Batch& other) = delete;
|
||||
~Batch();
|
||||
|
||||
// Pushes a new matrix onto the stack, and uses it for transforming all drawing.
|
||||
// `absolute` means the matrix provided will not be transformed by the current stack.
|
||||
void push_matrix(const Mat3x2& matrix, bool absolute = false);
|
||||
|
||||
// Pops the matrix from the stack
|
||||
Mat3x2 pop_matrix();
|
||||
|
||||
// Gets the current matrix from the top of the stackKO
|
||||
Mat3x2 peek_matrix() const;
|
||||
|
||||
// Pushes a Scissor rectangle. Note this is not transformed by the matrix stack
|
||||
// or other scissors. Each push is screen-space.
|
||||
void push_scissor(const Rect& scissor);
|
||||
|
||||
// Pops a Scissor rectangle from the stack
|
||||
Rect pop_scissor();
|
||||
|
||||
// Gets the current Scissor rectangle from the top of the stack
|
||||
Rect peek_scissor() const;
|
||||
|
||||
// Pushes a blend mode
|
||||
void push_blend(const BlendMode& blend);
|
||||
|
||||
// Pops a blend mode
|
||||
BlendMode pop_blend();
|
||||
|
||||
// Gets the current BlendMode from the top of the stack
|
||||
BlendMode peek_blend() const;
|
||||
|
||||
// Pushes a Material to use for all drawing. Note that the state of the Material
|
||||
// is not copied - it will be drawn with the values of the Material at render.
|
||||
void push_material(const MaterialRef& material);
|
||||
|
||||
// Pops a Material
|
||||
MaterialRef pop_material();
|
||||
|
||||
// Gets the current Material from the top of the stack
|
||||
MaterialRef peek_material() const;
|
||||
|
||||
// Pushes a render layer. Lower values are rendered first. This is not super optimized
|
||||
// and should generally be avoided.
|
||||
void push_layer(int layer);
|
||||
|
||||
// Pops a Layer
|
||||
int pop_layer();
|
||||
|
||||
// Gets the current Layer from the top of the stack
|
||||
int peek_layer() const;
|
||||
|
||||
// Pushes a Color Mode for drawing Textures
|
||||
void push_color_mode(ColorMode mode);
|
||||
|
||||
// Pops a Color MOde
|
||||
ColorMode pop_color_mode();
|
||||
|
||||
// Gets the current ColorMode from the top of the stack
|
||||
ColorMode peek_color_mode() const;
|
||||
|
||||
// Sets the current texture used for drawing. Note that certain functions will override
|
||||
// this (ex the `str` and `tex` methods)
|
||||
void set_texture(const TextureRef& texture);
|
||||
|
||||
// Sets the current texture sampler for drawing.
|
||||
void set_sampler(const TextureSampler& sampler);
|
||||
|
||||
// Draws the batch to the given target
|
||||
void render(const FrameBufferRef& target = App::backbuffer);
|
||||
|
||||
// Draws the batch to the given target, with the provided matrix
|
||||
void render(const FrameBufferRef& target, const Mat4x4& matrix);
|
||||
|
||||
// Clears the batch
|
||||
void clear();
|
||||
|
||||
// Clears and disposes all resources that the batch is using
|
||||
void dispose();
|
||||
|
||||
void line(const Vec2& from, const Vec2& to, float t, Color color);
|
||||
void line(const Vec2& from, const Vec2& to, float t, Color fromColor, Color toColor);
|
||||
|
||||
void bezier_line(const Vec2& from, const Vec2& b, const Vec2& to, int steps, float t, Color color);
|
||||
void bezier_line(const Vec2& from, const Vec2& b, const Vec2& c, const Vec2& to, int steps, float t, Color color);
|
||||
|
||||
void tri(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, Color color);
|
||||
void tri(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, Color col0, Color col1, Color col2);
|
||||
void tri(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec2& tex0, const Vec2& tex1, const Vec2& tex2, Color color);
|
||||
void 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 tri_line(const Vec2& a, const Vec2& b, const Vec2& c, float t, Color color);
|
||||
|
||||
void rect(const Rect& rect, Color color);
|
||||
void rect_line(const Rect& rect, float t, Color color);
|
||||
void rect_rounded(const Rect& rect, float radius, int steps, Color color);
|
||||
void 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 rect_rounded_line(const Rect& rect, float radius, int steps, float t, Color color);
|
||||
void rect_rounded_line(const Rect& rect, 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 semi_circle(Vec2 center, float start_radians, float end_radians, float radius, int steps, Color centerColor, Color edgeColor);
|
||||
void semi_circle(Vec2 center, float start_radians, float end_radians, float radius, int steps, Color color);
|
||||
void semi_circle_line(Vec2 center, float start_radians, float end_radians, float radius, int steps, float t, Color color);
|
||||
|
||||
void circle(const Vec2 center, float radius, int steps, Color color);
|
||||
void circle(const Vec2 center, float radius, int steps, Color center_color, Color outer_color);
|
||||
void circle_line(const Vec2 center, float raidus, float t, int steps, Color color);
|
||||
|
||||
void quad(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec2& pos3, Color color);
|
||||
void quad(const Vec2& pos0, const Vec2& pos1, const Vec2& pos2, const Vec2& pos3, Color col0, Color col1, Color col2, Color col3);
|
||||
void 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 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 quad_line(const Vec2& a, const Vec2& b, const Vec2& c, const Vec2& d, float t, Color color);
|
||||
|
||||
void arrow_head(const Vec2& point_pos, float radians, float side_len, Color color);
|
||||
void arrow_head(const Vec2& point_pos, const Vec2& from_pos, float side_len, Color color);
|
||||
|
||||
void tex(const TextureRef& texture, const Vec2& position = Vec2::zero, Color color = Color::white);
|
||||
void tex(const TextureRef& texture, const Vec2& position, const Vec2& origin, const Vec2& scale, float rotation, Color color);
|
||||
void tex(const TextureRef& texture, const Rect& clip, const Vec2& position, const Vec2& origin, const Vec2& scale, float rotation, Color color);
|
||||
|
||||
void tex(const Subtexture& subtexture, const Vec2& position = Vec2::zero, Color color = Color::white);
|
||||
void tex(const Subtexture& subtexture, const Vec2& pos, const Vec2& origin, const Vec2& scale, float rotation, Color color);
|
||||
void tex(const Subtexture& subtexture, const Rect& clip, const Vec2& pos, const Vec2& origin, const Vec2& scale, float rotation, Color color);
|
||||
|
||||
void str(const SpriteFont& font, const String& text, const Vec2& pos, Color color);
|
||||
void str(const SpriteFont& font, const String& text, const Vec2& pos, TextAlign align, float size, Color color);
|
||||
|
||||
private:
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
Vec2 pos;
|
||||
Vec2 tex;
|
||||
Color col;
|
||||
|
||||
uint8_t mult;
|
||||
uint8_t wash;
|
||||
uint8_t fill;
|
||||
uint8_t pad;
|
||||
};
|
||||
|
||||
struct DrawBatch
|
||||
{
|
||||
int layer;
|
||||
int offset;
|
||||
int elements;
|
||||
MaterialRef material;
|
||||
BlendMode blend;
|
||||
TextureRef texture;
|
||||
TextureSampler sampler;
|
||||
bool flip_vertically;
|
||||
Rect scissor;
|
||||
|
||||
DrawBatch() :
|
||||
layer(0),
|
||||
offset(0),
|
||||
elements(0),
|
||||
blend(BlendMode::Normal),
|
||||
flip_vertically(false),
|
||||
scissor(0, 0, -1, -1) {}
|
||||
};
|
||||
|
||||
static ShaderRef m_default_shader;
|
||||
MaterialRef m_default_material;
|
||||
MeshRef m_mesh;
|
||||
Mat3x2 m_matrix;
|
||||
ColorMode m_color_mode;
|
||||
uint8_t m_tex_mult;
|
||||
uint8_t m_tex_wash;
|
||||
DrawBatch m_batch;
|
||||
Vector<Vertex> m_vertices;
|
||||
Vector<uint32_t> m_indices;
|
||||
Vector<Mat3x2> m_matrix_stack;
|
||||
Vector<Rect> m_scissor_stack;
|
||||
Vector<BlendMode> m_blend_stack;
|
||||
Vector<MaterialRef> m_material_stack;
|
||||
Vector<ColorMode> m_color_mode_stack;
|
||||
Vector<int> m_layer_stack;
|
||||
Vector<DrawBatch> m_batches;
|
||||
|
||||
void render_single_batch(RenderPass& pass, const DrawBatch& b, const Mat4x4& matrix);
|
||||
};
|
||||
}
|
76
include/blah/drawing/spritefont.h
Normal file
76
include/blah/drawing/spritefont.h
Normal file
@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
#include <inttypes.h>
|
||||
#include <blah/containers/str.h>
|
||||
#include <blah/containers/vector.h>
|
||||
#include <blah/drawing/subtexture.h>
|
||||
#include <blah/math/vec2.h>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
class Font;
|
||||
|
||||
class SpriteFont
|
||||
{
|
||||
public:
|
||||
struct Character
|
||||
{
|
||||
Subtexture subtexture;
|
||||
float advance = 0;
|
||||
Vec2 offset;
|
||||
};
|
||||
private:
|
||||
// charset & kerning maps
|
||||
std::unordered_map<uint32_t, Character> m_characters;
|
||||
std::unordered_map<uint64_t, float> m_kerning;
|
||||
|
||||
// built texture
|
||||
Vector<TextureRef> m_atlas;
|
||||
|
||||
public:
|
||||
static const uint32_t* ASCII;
|
||||
|
||||
String name;
|
||||
float size;
|
||||
float ascent;
|
||||
float descent;
|
||||
float line_gap;
|
||||
|
||||
// Note:
|
||||
// charset is a list of range pairs, until a 0 terminator (ex. 32,128,0)
|
||||
|
||||
SpriteFont();
|
||||
SpriteFont(const char* file, float size);
|
||||
SpriteFont(const char* file, float size, const uint32_t* charset);
|
||||
SpriteFont(const Font& font, float size);
|
||||
SpriteFont(const Font& font, float size, const uint32_t* charset);
|
||||
SpriteFont(const SpriteFont&) = delete;
|
||||
SpriteFont(SpriteFont&& src) noexcept;
|
||||
~SpriteFont();
|
||||
|
||||
void dispose();
|
||||
|
||||
SpriteFont& operator=(const SpriteFont&) = delete;
|
||||
SpriteFont& operator=(SpriteFont&& src) noexcept;
|
||||
|
||||
float height() const { return ascent - descent; }
|
||||
float line_height() const { return ascent - descent + line_gap; }
|
||||
|
||||
const Vector<TextureRef>& textures() { return m_atlas; }
|
||||
|
||||
float width_of(const String& text) const;
|
||||
float width_of_line(const String& text, int start = 0) const;
|
||||
float height_of(const String& text) const;
|
||||
|
||||
void build(const char* file, float size, const uint32_t* charset);
|
||||
void build(const Font& font, float size, const uint32_t* charset);
|
||||
|
||||
float get_kerning(uint32_t codepoint0, uint32_t codepoint1) const;
|
||||
void set_kerning(uint32_t codepoint0, uint32_t codepoint1, float kerning);
|
||||
|
||||
Character& get_character(uint32_t codepoint) { return m_characters[codepoint]; }
|
||||
const Character& get_character(uint32_t codepoint) const;
|
||||
Character& operator[](uint32_t codepoint) { return m_characters[codepoint]; }
|
||||
const Character& operator[](uint32_t codepoint) const;
|
||||
};
|
||||
}
|
48
include/blah/drawing/subtexture.h
Normal file
48
include/blah/drawing/subtexture.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include <blah/graphics/texture.h>
|
||||
#include <blah/math/rect.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
// Subtexture is a view into a texture, and can be used to
|
||||
// easily represent sprites in a larger texture atlas.
|
||||
struct Subtexture
|
||||
{
|
||||
// Reference to our Texture
|
||||
TextureRef texture;
|
||||
|
||||
// Source rectangle, in pixels
|
||||
Rect source;
|
||||
|
||||
// Frame rectangle, in pixels. This describes padding around the image.
|
||||
// This is useful for drawing images that have been trimmed. Ex. if the source
|
||||
// is 32,32, but the original image was 64,64, the frame could be -16,-16,64,64
|
||||
Rect frame;
|
||||
|
||||
// `draw_coords` are automatically assigned through `update` method
|
||||
Vec2 draw_coords[4];
|
||||
|
||||
// `tex_coords` are automatically assigned through the `update` method
|
||||
Vec2 tex_coords[4];
|
||||
|
||||
Subtexture();
|
||||
Subtexture(const TextureRef& texture);
|
||||
Subtexture(const TextureRef& texture, Rect source);
|
||||
Subtexture(const TextureRef& texture, Rect source, Rect frame);
|
||||
|
||||
// Returns the width of the image
|
||||
float width() const { return frame.w; }
|
||||
|
||||
// Returns the height of the image
|
||||
float height() const { return frame.h; }
|
||||
|
||||
// updates the `draw_coords` and `tex_coords`
|
||||
void update();
|
||||
|
||||
// returns resulting source and frame rectangles based on the provided clip rectangle
|
||||
void crop_info(const Rect& clip, Rect* dest_source, Rect* dest_frame) const;
|
||||
|
||||
// returns a subtexture cropped to the provided rectangle
|
||||
Subtexture crop(const Rect& clip) const;
|
||||
};
|
||||
}
|
104
include/blah/graphics/blend.h
Normal file
104
include/blah/graphics/blend.h
Normal file
@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
enum class BlendOp
|
||||
{
|
||||
Add,
|
||||
Subtract,
|
||||
ReverseSubtract,
|
||||
Min,
|
||||
Max
|
||||
};
|
||||
|
||||
enum class BlendFactor
|
||||
{
|
||||
Zero,
|
||||
One,
|
||||
SrcColor,
|
||||
OneMinusSrcColor,
|
||||
DstColor,
|
||||
OneMinusDstColor,
|
||||
SrcAlpha,
|
||||
OneMinusSrcAlpha,
|
||||
DstAlpha,
|
||||
OneMinusDstAlpha,
|
||||
ConstantColor,
|
||||
OneMinusConstantColor,
|
||||
ConstantAlpha,
|
||||
OneMinusConstantAlpha,
|
||||
SrcAlphaSaturate,
|
||||
Src1Color,
|
||||
OneMinusSrc1Color,
|
||||
Src1Alpha,
|
||||
OneMinusSrc1Alpha
|
||||
};
|
||||
|
||||
enum class BlendMask
|
||||
{
|
||||
None = 0,
|
||||
Red = 1,
|
||||
Green = 2,
|
||||
Blue = 4,
|
||||
Alpha = 8,
|
||||
RGB = Red | Green | Blue,
|
||||
RGBA = Red | Green | Blue | Alpha,
|
||||
};
|
||||
|
||||
struct BlendMode
|
||||
{
|
||||
// Normal, pre-multiplied, Blend Mode
|
||||
static const BlendMode Normal;
|
||||
|
||||
// Subtractive Blend Mode
|
||||
static const BlendMode Subtract;
|
||||
|
||||
BlendOp color_op;
|
||||
BlendFactor color_src;
|
||||
BlendFactor color_dst;
|
||||
BlendOp alpha_op;
|
||||
BlendFactor alpha_src;
|
||||
BlendFactor alpha_dst;
|
||||
BlendMask mask;
|
||||
uint32_t rgba;
|
||||
|
||||
BlendMode() = default;
|
||||
|
||||
BlendMode(BlendOp op, BlendFactor src, BlendFactor dst) :
|
||||
color_op(op),
|
||||
color_src(src),
|
||||
color_dst(dst),
|
||||
alpha_op(op),
|
||||
alpha_src(src),
|
||||
alpha_dst(dst),
|
||||
mask(BlendMask::RGBA),
|
||||
rgba(0xffffffff) {}
|
||||
|
||||
BlendMode(
|
||||
BlendOp color_op, BlendFactor color_src, BlendFactor color_dst,
|
||||
BlendOp alpha_op, BlendFactor alpha_src, BlendFactor alpha_dst,
|
||||
BlendMask blend_mask, uint32_t blend_rgba) :
|
||||
color_op(color_op),
|
||||
color_src(color_src),
|
||||
color_dst(color_dst),
|
||||
alpha_op(alpha_op),
|
||||
alpha_src(alpha_src),
|
||||
alpha_dst(alpha_dst),
|
||||
mask(blend_mask),
|
||||
rgba(blend_rgba) {}
|
||||
|
||||
bool operator==(const BlendMode& rhs) const
|
||||
{
|
||||
return
|
||||
color_op == rhs.color_op && color_src == rhs.color_src && color_dst == rhs.color_dst &&
|
||||
alpha_op == rhs.alpha_op && alpha_src == rhs.alpha_src && alpha_dst == rhs.alpha_dst &&
|
||||
mask == rhs.mask && rgba == rhs.rgba;
|
||||
}
|
||||
|
||||
bool operator!=(const BlendMode& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
};
|
||||
}
|
62
include/blah/graphics/framebuffer.h
Normal file
62
include/blah/graphics/framebuffer.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
#include <blah/graphics/texture.h>
|
||||
#include <blah/containers/stackvector.h>
|
||||
#include <blah/math/color.h>
|
||||
#include <memory>
|
||||
|
||||
// 4 color attachments + 1 depth/stencil
|
||||
#define BLAH_ATTACHMENTS 5
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
typedef StackVector<TextureRef, BLAH_ATTACHMENTS> Attachments;
|
||||
|
||||
class FrameBuffer;
|
||||
typedef std::shared_ptr<FrameBuffer> FrameBufferRef;
|
||||
|
||||
class FrameBuffer
|
||||
{
|
||||
protected:
|
||||
FrameBuffer() = default;
|
||||
|
||||
public:
|
||||
// Copy / Moves not allowed
|
||||
FrameBuffer(const FrameBuffer&) = delete;
|
||||
FrameBuffer(FrameBuffer&&) = delete;
|
||||
FrameBuffer& operator=(const FrameBuffer&) = delete;
|
||||
FrameBuffer& operator=(FrameBuffer&&) = delete;
|
||||
|
||||
// Default Destructor
|
||||
virtual ~FrameBuffer() = default;
|
||||
|
||||
// Creates a new FrameBuffer with a single Color attachment
|
||||
// If the FrameBuffer creation fails, it will return an invalid FrameBufferRef.
|
||||
static FrameBufferRef create(int width, int height);
|
||||
|
||||
// Creates a new FrameBuffer with the given Texture Attachments. You must provide at least one Attachment.
|
||||
// If the FrameBuffer creation fails, it will return an invalid FrameBufferRef.
|
||||
static FrameBufferRef create(int width, int height, const TextureFormat* attachments, int attachmentCount);
|
||||
|
||||
// Gets the list of Attachments from the FrameBuffer
|
||||
virtual Attachments& attachments() = 0;
|
||||
|
||||
// Gets the list of Attachments from the FrameBuffer
|
||||
virtual const Attachments& attachments() const = 0;
|
||||
|
||||
// Gets the Attachment at a given index from the FrameBuffer
|
||||
virtual TextureRef& attachment(int index) = 0;
|
||||
|
||||
// Gets the Attachment at a given index from the FrameBuffer
|
||||
virtual const TextureRef& attachment(int index) const = 0;
|
||||
|
||||
// Gets the width of the FrameBuffer
|
||||
virtual int width() const = 0;
|
||||
|
||||
// Gets the height of the FrameBuffer
|
||||
virtual int height() const = 0;
|
||||
|
||||
// Clears the FrameBuffer
|
||||
virtual void clear(Color color) = 0;
|
||||
};
|
||||
|
||||
}
|
82
include/blah/graphics/material.h
Normal file
82
include/blah/graphics/material.h
Normal file
@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
#include <blah/graphics/texture.h>
|
||||
#include <blah/graphics/shader.h>
|
||||
#include <blah/graphics/sampler.h>
|
||||
#include <blah/containers/vector.h>
|
||||
#include <memory>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
class Material;
|
||||
typedef std::shared_ptr<Material> MaterialRef;
|
||||
|
||||
class Material final
|
||||
{
|
||||
private:
|
||||
Material(const ShaderRef& shader);
|
||||
|
||||
public:
|
||||
// Copy / Moves not allowed
|
||||
Material(const Material&) = delete;
|
||||
Material(Material&&) = delete;
|
||||
Material& operator=(const Material&) = delete;
|
||||
Material& operator=(Material&&) = delete;
|
||||
|
||||
// Default destructor
|
||||
~Material() = default;
|
||||
|
||||
// Creates a new Material from the given Shader.
|
||||
// If the Shader is invalid, it will return an invalid MaterialRef.
|
||||
static MaterialRef create(const ShaderRef& shader);
|
||||
|
||||
// Returns the Shader assigned to the Material.
|
||||
const ShaderRef shader() const;
|
||||
|
||||
// Sets the texture
|
||||
void set_texture(const char* name, const TextureRef& texture, int array_index = 0);
|
||||
|
||||
// Sets the texture
|
||||
void set_texture(int slot, const TextureRef& texture, int array_index = 0);
|
||||
|
||||
// Gets the texture, or an empty reference if invalid
|
||||
TextureRef get_texture(const char* name, int array_index = 0) const;
|
||||
|
||||
// Gets the texture, or an empty reference if invalid
|
||||
TextureRef get_texture(int slot, int array_index = 0) const;
|
||||
|
||||
// Sets the sampler
|
||||
void set_sampler(const char* name, const TextureSampler& sampler, int array_index = 0);
|
||||
|
||||
// Sets the sampler
|
||||
void set_sampler(int slot, const TextureSampler& sampler, int array_index = 0);
|
||||
|
||||
// Gets the sampler
|
||||
TextureSampler get_sampler(const char* name, int array_index = 0) const;
|
||||
|
||||
// Gets the sampler
|
||||
TextureSampler get_sampler(int slot, int array_index = 0) const;
|
||||
|
||||
// Sets the value. `length` is the total number of floats to set
|
||||
// For example if the uniform is a float2[4], a total of 8 float values
|
||||
// can be set.
|
||||
void set_value(const char* name, const float* value, int64_t length);
|
||||
|
||||
// Gets a pointer to the values of the given Uniform, or nullptr if it doesn't exist.
|
||||
const float* get_value(const char* name, int64_t* length = nullptr) const;
|
||||
|
||||
// Returns the internal Texture buffer
|
||||
const Vector<TextureRef>& textures() const;
|
||||
|
||||
// Returns the internal Sampler buffer
|
||||
const Vector<TextureSampler>& samplers() const;
|
||||
|
||||
// Returns the interal float buffer of all the values
|
||||
const float* data() const;
|
||||
|
||||
private:
|
||||
ShaderRef m_shader;
|
||||
Vector<TextureRef> m_textures;
|
||||
Vector<TextureSampler> m_samplers;
|
||||
Vector<float> m_data;
|
||||
};
|
||||
}
|
93
include/blah/graphics/mesh.h
Normal file
93
include/blah/graphics/mesh.h
Normal file
@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
#include <inttypes.h>
|
||||
#include <memory>
|
||||
#include <blah/containers/stackvector.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
enum class VertexType
|
||||
{
|
||||
None,
|
||||
Float,
|
||||
Float2,
|
||||
Float3,
|
||||
Float4,
|
||||
Byte4,
|
||||
UByte4,
|
||||
Short2,
|
||||
UShort2,
|
||||
Short4,
|
||||
UShort4
|
||||
};
|
||||
|
||||
struct VertexAttribute
|
||||
{
|
||||
// Location / Attribute Index
|
||||
int index = 0;
|
||||
|
||||
// Vertex Type
|
||||
VertexType type = VertexType::None;
|
||||
|
||||
// Whether the Vertex should be normalized (doesn't apply to Floats)
|
||||
bool normalized = false;
|
||||
};
|
||||
|
||||
struct VertexFormat
|
||||
{
|
||||
// List of Attributes
|
||||
StackVector<VertexAttribute, 16> attributes;
|
||||
|
||||
// Total size in bytes of each Vertex element
|
||||
int stride = 0;
|
||||
|
||||
VertexFormat() = default;
|
||||
VertexFormat(std::initializer_list<VertexAttribute> attributes, int stride = 0);
|
||||
};
|
||||
|
||||
enum class IndexFormat
|
||||
{
|
||||
UInt16,
|
||||
UInt32
|
||||
};
|
||||
|
||||
class Mesh;
|
||||
typedef std::shared_ptr<Mesh> MeshRef;
|
||||
|
||||
class Mesh
|
||||
{
|
||||
protected:
|
||||
Mesh() = default;
|
||||
|
||||
public:
|
||||
// Copy / Moves not allowed
|
||||
Mesh(const Mesh&) = delete;
|
||||
Mesh(Mesh&&) = delete;
|
||||
Mesh& operator=(const Mesh&) = delete;
|
||||
Mesh& operator=(Mesh&&) = delete;
|
||||
|
||||
// Default Destructor
|
||||
virtual ~Mesh() = default;
|
||||
|
||||
// Creates a new Mesh.
|
||||
// If the Mesh creation fails, it will return an invalid Mesh.
|
||||
static MeshRef create();
|
||||
|
||||
// Uploads the given index buffer to the Mesh
|
||||
virtual void index_data(IndexFormat format, const void* indices, int64_t count) = 0;
|
||||
|
||||
// Uploads the given vertex buffer to the Mesh
|
||||
virtual void vertex_data(const VertexFormat& format, const void* vertices, int64_t count) = 0;
|
||||
|
||||
// Uploads the given instance buffer to the Mesh
|
||||
virtual void instance_data(const VertexFormat& format, const void* instances, int64_t count) = 0;
|
||||
|
||||
// Gets the index count of the Mesh
|
||||
virtual int64_t index_count() const = 0;
|
||||
|
||||
// Gets the vertex count of the Mesh
|
||||
virtual int64_t vertex_count() const = 0;
|
||||
|
||||
// Gets the instance count of the Mesh
|
||||
virtual int64_t instance_count() const = 0;
|
||||
};
|
||||
}
|
81
include/blah/graphics/renderpass.h
Normal file
81
include/blah/graphics/renderpass.h
Normal file
@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
#include <inttypes.h>
|
||||
#include <blah/math/rect.h>
|
||||
#include <blah/containers/str.h>
|
||||
#include <blah/graphics/texture.h>
|
||||
#include <blah/graphics/framebuffer.h>
|
||||
#include <blah/graphics/mesh.h>
|
||||
#include <blah/graphics/shader.h>
|
||||
#include <blah/graphics/material.h>
|
||||
#include <blah/graphics/blend.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
enum class Compare
|
||||
{
|
||||
None,
|
||||
Always,
|
||||
Never,
|
||||
Less,
|
||||
Equal,
|
||||
LessOrEqual,
|
||||
Greater,
|
||||
NotEqual,
|
||||
GreatorOrEqual
|
||||
};
|
||||
|
||||
enum class Cull
|
||||
{
|
||||
None = 0,
|
||||
Front = 1,
|
||||
Back = 2,
|
||||
};
|
||||
|
||||
struct RenderPass
|
||||
{
|
||||
// Framebuffer to draw to
|
||||
FrameBufferRef target;
|
||||
|
||||
// Mesh to draw with
|
||||
MeshRef mesh;
|
||||
|
||||
// Material to draw with
|
||||
MaterialRef material;
|
||||
|
||||
// Whether the RenderPass should use a specific viewport
|
||||
bool has_viewport;
|
||||
|
||||
// Whether the RenderPass should use a scissor rectangle
|
||||
bool has_scissor;
|
||||
|
||||
// The viewport (only used if hasViewport is true)
|
||||
Rect viewport;
|
||||
|
||||
// The scissor rectangle (only used if hasScissor is true)
|
||||
Rect scissor;
|
||||
|
||||
// First index in the Mesh to draw from
|
||||
int64_t index_start;
|
||||
|
||||
// Total amount of indices to draw from the Mesh
|
||||
int64_t index_count;
|
||||
|
||||
// Total amount of instances to draw from the Mesh
|
||||
int64_t instance_count;
|
||||
|
||||
// Depth Compare Function
|
||||
Compare depth;
|
||||
|
||||
// Cull Mode
|
||||
Cull cull;
|
||||
|
||||
// Blend Mode
|
||||
BlendMode blend;
|
||||
|
||||
// Initializes a default RenderPass
|
||||
RenderPass();
|
||||
|
||||
// Performs the render
|
||||
void perform();
|
||||
};
|
||||
}
|
53
include/blah/graphics/sampler.h
Normal file
53
include/blah/graphics/sampler.h
Normal file
@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
enum class TextureFilter
|
||||
{
|
||||
None,
|
||||
Linear,
|
||||
Nearest
|
||||
};
|
||||
|
||||
enum class TextureWrap
|
||||
{
|
||||
None,
|
||||
Clamp,
|
||||
Repeat
|
||||
};
|
||||
|
||||
struct TextureSampler
|
||||
{
|
||||
TextureFilter filter;
|
||||
TextureWrap wrap_x;
|
||||
TextureWrap wrap_y;
|
||||
|
||||
TextureSampler() :
|
||||
filter(TextureFilter::Linear),
|
||||
wrap_x(TextureWrap::Repeat),
|
||||
wrap_y(TextureWrap::Repeat) {}
|
||||
|
||||
TextureSampler(TextureFilter filter) :
|
||||
filter(filter),
|
||||
wrap_x(TextureWrap::Repeat),
|
||||
wrap_y(TextureWrap::Repeat) {}
|
||||
|
||||
TextureSampler(TextureFilter filter, TextureWrap wrap_x, TextureWrap wrap_y) :
|
||||
filter(filter),
|
||||
wrap_x(wrap_x),
|
||||
wrap_y(wrap_y) {}
|
||||
|
||||
bool operator==(const TextureSampler& rhs) const
|
||||
{
|
||||
return
|
||||
filter == rhs.filter &&
|
||||
wrap_x == rhs.wrap_x &&
|
||||
wrap_y == rhs.wrap_y;
|
||||
}
|
||||
|
||||
bool operator!=(const TextureSampler& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
};
|
||||
}
|
101
include/blah/graphics/shader.h
Normal file
101
include/blah/graphics/shader.h
Normal file
@ -0,0 +1,101 @@
|
||||
#pragma once
|
||||
#include <blah/containers/stackvector.h>
|
||||
#include <blah/containers/str.h>
|
||||
#include <memory>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
// Supported Uniform Types
|
||||
enum class UniformType
|
||||
{
|
||||
None,
|
||||
Float,
|
||||
Float2,
|
||||
Float3,
|
||||
Float4,
|
||||
Mat3x2,
|
||||
Mat4x4,
|
||||
Texture2D,
|
||||
Sampler2D
|
||||
};
|
||||
|
||||
// Supported Shader Types
|
||||
enum class ShaderType
|
||||
{
|
||||
None = 0,
|
||||
Vertex = 1 << 0,
|
||||
Fragment = 1 << 1
|
||||
};
|
||||
|
||||
// Uniform Info, provided by the Shader
|
||||
struct UniformInfo
|
||||
{
|
||||
// Name of the Uniform
|
||||
String name;
|
||||
|
||||
// The Value type of the Uniform
|
||||
UniformType type;
|
||||
|
||||
// The Shader type the Uniform is a part of
|
||||
ShaderType shader;
|
||||
|
||||
// Some rendering APIs have uniform buffers. The `buffer_index`
|
||||
// specifies which buffer the uniform belongs to
|
||||
int buffer_index;
|
||||
|
||||
// Array length of the Uniform (ex. a vec2[4] would be 4)
|
||||
int array_length;
|
||||
};
|
||||
|
||||
// Data to be passed to the shader to construct it
|
||||
struct ShaderData
|
||||
{
|
||||
struct HLSL_Attribute
|
||||
{
|
||||
// Semantic Name
|
||||
const char* semantic_name = nullptr;
|
||||
|
||||
// (optional) Semantic Index
|
||||
int semantic_index = 0;
|
||||
};
|
||||
|
||||
// Vertex Shader Program data
|
||||
String vertex;
|
||||
|
||||
// Fragment Shader Program data
|
||||
String fragment;
|
||||
|
||||
// HLSL Attributes - required for D3D11
|
||||
StackVector<HLSL_Attribute, 16> hlsl_attributes;
|
||||
};
|
||||
|
||||
class Shader;
|
||||
typedef std::shared_ptr<Shader> ShaderRef;
|
||||
|
||||
class Shader
|
||||
{
|
||||
protected:
|
||||
Shader() = default;
|
||||
|
||||
public:
|
||||
// Copy / Moves not allowed
|
||||
Shader(const Shader&) = delete;
|
||||
Shader(Shader&&) = delete;
|
||||
Shader& operator=(const Shader&) = delete;
|
||||
Shader& operator=(Shader&&) = delete;
|
||||
|
||||
// Default Destructor
|
||||
virtual ~Shader() = default;
|
||||
|
||||
// Creates a Shader with the given Shader Data.
|
||||
// If the Shader creation fails, it will return an invalid ShaderRef.
|
||||
static ShaderRef create(const ShaderData& data);
|
||||
|
||||
// Gets a list of Shader Uniforms from Shader
|
||||
virtual Vector<UniformInfo>& uniforms() = 0;
|
||||
|
||||
// Gets a list of Shader Uniforms from Shader
|
||||
virtual const Vector<UniformInfo>& uniforms() const = 0;
|
||||
};
|
||||
|
||||
}
|
78
include/blah/graphics/texture.h
Normal file
78
include/blah/graphics/texture.h
Normal file
@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
enum class TextureFormat
|
||||
{
|
||||
None,
|
||||
R,
|
||||
RG,
|
||||
RGBA,
|
||||
DepthStencil,
|
||||
Count
|
||||
};
|
||||
|
||||
class Image;
|
||||
class Stream;
|
||||
class Texture;
|
||||
typedef std::shared_ptr<Texture> TextureRef;
|
||||
|
||||
class Texture
|
||||
{
|
||||
protected:
|
||||
Texture() = default;
|
||||
|
||||
public:
|
||||
// Copy / Moves not allowed
|
||||
Texture(const Texture&) = delete;
|
||||
Texture(Texture&&) = delete;
|
||||
Texture& operator=(const Texture&) = delete;
|
||||
Texture& operator=(Texture&&) = delete;
|
||||
|
||||
// Default Destructor
|
||||
virtual ~Texture() = default;
|
||||
|
||||
// Creates a new Texture.
|
||||
// If the Texture creation fails, it will return an invalid TextureRef.
|
||||
static TextureRef create(const Image& image);
|
||||
|
||||
// Creates a new Texture.
|
||||
// If the Texture creation fails, it will return an invalid TextureRef.
|
||||
static TextureRef create(int width, int height, unsigned char* rgba);
|
||||
|
||||
// Creates a new Texture.
|
||||
// If the Texture creation fails, it will return an invalid TextureRef.
|
||||
static TextureRef create(int width, int height, TextureFormat format);
|
||||
|
||||
// Creates a new Texture from a Stream.
|
||||
// If the Texture creation fails, it will return an invalid TextureRef.
|
||||
static TextureRef create(Stream& stream);
|
||||
|
||||
// Creates a new Texture from a File.
|
||||
// If the Texture creation fails, it will return an invalid TextureRef.
|
||||
static TextureRef create(const char* file);
|
||||
|
||||
// gets the width of the texture
|
||||
virtual int width() const = 0;
|
||||
|
||||
// gets the height of the texture
|
||||
virtual int height() const = 0;
|
||||
|
||||
// Gets the format of the Texture
|
||||
virtual TextureFormat format() const = 0;
|
||||
|
||||
// Sets the data of the Texture.
|
||||
// Note that the pixel buffer should be in the same format as the Texture. There is no row padding.
|
||||
// If the pixel buffer isn't the same size as the texture, it will set the minimum available amount of data.
|
||||
virtual void set_data(unsigned char* data) = 0;
|
||||
|
||||
// Gets the data of the Texture.
|
||||
// Note that the pixel buffer will be written to in the same format as the Texture,
|
||||
// and you should allocate enough space for the full texture. There is no row padding.
|
||||
virtual void get_data(unsigned char* data) = 0;
|
||||
|
||||
// Returns true if the Texture is part of a FrameBuffer
|
||||
virtual bool is_framebuffer() const = 0;
|
||||
};
|
||||
}
|
153
include/blah/images/aseprite.h
Normal file
153
include/blah/images/aseprite.h
Normal file
@ -0,0 +1,153 @@
|
||||
#pragma once
|
||||
#include <blah/math/color.h>
|
||||
#include <blah/images/image.h>
|
||||
#include <blah/containers/str.h>
|
||||
#include <blah/streams/stream.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
// A simple Aseprite file parser.
|
||||
// This implementation does not support Aseprite blendmodes,
|
||||
// besides the default blend mode.
|
||||
class Aseprite
|
||||
{
|
||||
public:
|
||||
|
||||
enum class Modes
|
||||
{
|
||||
Indexed = 1,
|
||||
Grayscale = 2,
|
||||
RGBA = 4
|
||||
};
|
||||
|
||||
enum class Chunks
|
||||
{
|
||||
OldPaletteA = 0x0004,
|
||||
OldPaletteB = 0x0011,
|
||||
Layer = 0x2004,
|
||||
Cel = 0x2005,
|
||||
CelExtra = 0x2006,
|
||||
Mask = 0x2016,
|
||||
Path = 0x2017,
|
||||
FrameTags = 0x2018,
|
||||
Palette = 0x2019,
|
||||
UserData = 0x2020,
|
||||
Slice = 0x2022
|
||||
};
|
||||
|
||||
enum class LoopDirections
|
||||
{
|
||||
Forward = 0,
|
||||
Reverse = 1,
|
||||
PingPong = 2
|
||||
};
|
||||
|
||||
enum class LayerFlags
|
||||
{
|
||||
Visible = 1,
|
||||
Editable = 2,
|
||||
LockMovement = 4,
|
||||
Background = 8,
|
||||
PreferLinkedCels = 16,
|
||||
Collapsed = 32,
|
||||
Reference = 64
|
||||
};
|
||||
|
||||
enum class LayerTypes
|
||||
{
|
||||
Normal = 0,
|
||||
Group = 1
|
||||
};
|
||||
|
||||
struct UserData
|
||||
{
|
||||
String text;
|
||||
Color color;
|
||||
};
|
||||
|
||||
struct Layer;
|
||||
|
||||
struct Cel
|
||||
{
|
||||
int layer_index = 0;
|
||||
int linked_frame_index = 0;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
unsigned char alpha = 0;
|
||||
Image image;
|
||||
UserData userdata;
|
||||
};
|
||||
|
||||
struct Frame
|
||||
{
|
||||
int duration = 0;
|
||||
Image image;
|
||||
Vector<Cel> cels;
|
||||
};
|
||||
|
||||
struct Layer
|
||||
{
|
||||
LayerFlags flag = (LayerFlags)0;
|
||||
LayerTypes type = LayerTypes::Normal;
|
||||
String name;
|
||||
int child_level = 0;
|
||||
int blendmode = 0;
|
||||
unsigned char alpha = 0;
|
||||
bool visible = true;
|
||||
UserData userdata;
|
||||
};
|
||||
|
||||
struct Tag
|
||||
{
|
||||
String name;
|
||||
LoopDirections loops = LoopDirections::Forward;
|
||||
int from = 0;
|
||||
int to = 0;
|
||||
Color color;
|
||||
UserData userdata;
|
||||
};
|
||||
|
||||
struct Slice
|
||||
{
|
||||
int frame = 0;
|
||||
String name;
|
||||
Point origin;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
bool has_pivot = false;
|
||||
Point pivot;
|
||||
UserData userdata;
|
||||
};
|
||||
|
||||
Modes mode = Modes::RGBA;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
Vector<Layer> layers;
|
||||
Vector<Frame> frames;
|
||||
Vector<Tag> tags;
|
||||
Vector<Slice> slices;
|
||||
Vector<Color> palette;
|
||||
|
||||
Aseprite();
|
||||
Aseprite(const char* path);
|
||||
Aseprite(Stream& stream);
|
||||
Aseprite(const Aseprite& src);
|
||||
Aseprite(Aseprite&& src) noexcept;
|
||||
Aseprite& operator=(const Aseprite& src);
|
||||
Aseprite& operator=(Aseprite&& src) noexcept;
|
||||
~Aseprite();
|
||||
|
||||
private:
|
||||
UserData* m_last_userdata = nullptr;
|
||||
|
||||
void parse(Stream& stream);
|
||||
void parse_layer(Stream& stream, int frame);
|
||||
void parse_cel(Stream& stream, int frame, size_t maxPosition);
|
||||
void parse_palette(Stream& stream, int frame);
|
||||
void parse_user_data(Stream& stream, int frame);
|
||||
void parse_tag(Stream& stream, int frame);
|
||||
void parse_slice(Stream& stream, int frame);
|
||||
void render_cel(Cel* cel, Frame* frame);
|
||||
};
|
||||
}
|
62
include/blah/images/font.h
Normal file
62
include/blah/images/font.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
#include <blah/streams/stream.h>
|
||||
#include <blah/images/image.h>
|
||||
#include <blah/containers/str.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
typedef uint32_t Codepoint;
|
||||
|
||||
class Font
|
||||
{
|
||||
public:
|
||||
struct Char
|
||||
{
|
||||
int glyph = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
float advance = 0;
|
||||
float offset_x = 0;
|
||||
float offset_y = 0;
|
||||
float scale = 0;
|
||||
bool has_glyph = false;
|
||||
};
|
||||
|
||||
Font();
|
||||
Font(Stream& stream);
|
||||
Font(const char* path);
|
||||
Font(const Font&) = delete;
|
||||
Font& operator=(const Font&) = delete;
|
||||
Font(Font&& src) noexcept;
|
||||
Font& operator=(Font&& src) noexcept;
|
||||
~Font();
|
||||
|
||||
void dispose();
|
||||
|
||||
const char* family_name() const;
|
||||
const char* style_name() const;
|
||||
int ascent() const;
|
||||
int descent() const;
|
||||
int line_gap() const;
|
||||
int height() const;
|
||||
int line_height() const;
|
||||
|
||||
int get_glyph(Codepoint codepoint) const;
|
||||
float get_scale(float size) const;
|
||||
float get_kerning(int glyph1, int glyph2, float scale) const;
|
||||
Char get_character(int glyph, float scale) const;
|
||||
bool get_image(const Char& ch, Color* pixels) const;
|
||||
bool is_valid() const;
|
||||
|
||||
private:
|
||||
void load(Stream& stream);
|
||||
void* m_font;
|
||||
unsigned char* m_data;
|
||||
String m_family_name;
|
||||
String m_style_name;
|
||||
int m_ascent;
|
||||
int m_descent;
|
||||
int m_line_gap;
|
||||
bool m_valid;
|
||||
};
|
||||
}
|
42
include/blah/images/image.h
Normal file
42
include/blah/images/image.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include <blah/math/color.h>
|
||||
#include <blah/math/rectI.h>
|
||||
#include <blah/math/point.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
class Stream;
|
||||
|
||||
class Image
|
||||
{
|
||||
public:
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
Color* pixels = nullptr;
|
||||
|
||||
Image();
|
||||
Image(Stream& stream);
|
||||
Image(const char* file);
|
||||
Image(int width, int height);
|
||||
Image(const Image& src);
|
||||
Image& operator=(const Image& src);
|
||||
Image(Image&& src) noexcept;
|
||||
Image& operator=(Image&& src) noexcept;
|
||||
~Image();
|
||||
|
||||
void from_stream(Stream& stream);
|
||||
void dispose();
|
||||
|
||||
void premultiply();
|
||||
void set_pixels(const RectI& rect, Color* data);
|
||||
bool save_png(const char* file) const;
|
||||
bool save_png(Stream& stream) const;
|
||||
bool save_jpg(const char* file, int quality) const;
|
||||
bool save_jpg(Stream& stream, int quality) const;
|
||||
void get_pixels(Color* dest, const Point& destPos, const Point& destSize, RectI sourceRect);
|
||||
Image get_sub_image(const RectI& sourceRect);
|
||||
|
||||
private:
|
||||
bool m_stbi_ownership;
|
||||
};
|
||||
}
|
75
include/blah/images/packer.h
Normal file
75
include/blah/images/packer.h
Normal file
@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#include <blah/images/image.h>
|
||||
#include <blah/math/color.h>
|
||||
#include <blah/math/rectI.h>
|
||||
#include <blah/math/point.h>
|
||||
#include <blah/containers/str.h>
|
||||
#include <blah/containers/vector.h>
|
||||
#include <blah/streams/bufferstream.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
// Texture Packer, which takes source images and combines
|
||||
// them into a single large texture.
|
||||
class Packer
|
||||
{
|
||||
public:
|
||||
class Entry
|
||||
{
|
||||
friend class Packer;
|
||||
private:
|
||||
int64_t memory_index;
|
||||
public:
|
||||
uint64_t id;
|
||||
int page;
|
||||
bool empty;
|
||||
RectI frame;
|
||||
RectI packed;
|
||||
|
||||
Entry(uint64_t id, const RectI& frame)
|
||||
: memory_index(0), id(id), page(0), empty(true), frame(frame), packed(0, 0, 0, 0) {}
|
||||
};
|
||||
|
||||
int max_size;
|
||||
bool power_of_two;
|
||||
int spacing;
|
||||
int padding;
|
||||
|
||||
Vector<Image> pages;
|
||||
Vector<Entry> entries;
|
||||
|
||||
Packer();
|
||||
Packer(int max_size, int spacing, bool power_of_two);
|
||||
Packer(const Packer&) = delete;
|
||||
Packer& operator=(const Packer&) = delete;
|
||||
Packer(Packer&& src) noexcept;
|
||||
Packer& operator=(Packer&& src) noexcept;
|
||||
~Packer();
|
||||
|
||||
void add(uint64_t id, int width, int height, const Color* pixels);
|
||||
void add(uint64_t id, const Image& bitmap);
|
||||
void add(uint64_t id, const String& path);
|
||||
|
||||
void pack();
|
||||
void clear();
|
||||
void dispose();
|
||||
|
||||
private:
|
||||
struct Node
|
||||
{
|
||||
bool used;
|
||||
RectI rect;
|
||||
Node* right;
|
||||
Node* down;
|
||||
|
||||
Node();
|
||||
Node* Find(int w, int h);
|
||||
Node* Reset(const RectI& rect);
|
||||
};
|
||||
|
||||
bool m_dirty;
|
||||
BufferStream m_buffer;
|
||||
|
||||
void add_entry(uint64_t id, int w, int h, const Color* pixels);
|
||||
};
|
||||
}
|
467
include/blah/input/input.h
Normal file
467
include/blah/input/input.h
Normal file
@ -0,0 +1,467 @@
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <blah/math/vec2.h>
|
||||
|
||||
// These are generally copied from the SDL2 Scancode Keys
|
||||
#define BLAH_KEY_DEFINITIONS \
|
||||
DEFINE_KEY(Unknown, 0) \
|
||||
DEFINE_KEY(A, 4) \
|
||||
DEFINE_KEY(B, 5) \
|
||||
DEFINE_KEY(C, 6) \
|
||||
DEFINE_KEY(D, 7) \
|
||||
DEFINE_KEY(E, 8) \
|
||||
DEFINE_KEY(F, 9) \
|
||||
DEFINE_KEY(G, 10) \
|
||||
DEFINE_KEY(H, 11) \
|
||||
DEFINE_KEY(I, 12) \
|
||||
DEFINE_KEY(J, 13) \
|
||||
DEFINE_KEY(K, 14) \
|
||||
DEFINE_KEY(L, 15) \
|
||||
DEFINE_KEY(M, 16) \
|
||||
DEFINE_KEY(N, 17) \
|
||||
DEFINE_KEY(O, 18) \
|
||||
DEFINE_KEY(P, 19) \
|
||||
DEFINE_KEY(Q, 20) \
|
||||
DEFINE_KEY(R, 21) \
|
||||
DEFINE_KEY(S, 22) \
|
||||
DEFINE_KEY(T, 23) \
|
||||
DEFINE_KEY(U, 24) \
|
||||
DEFINE_KEY(V, 25) \
|
||||
DEFINE_KEY(W, 26) \
|
||||
DEFINE_KEY(X, 27) \
|
||||
DEFINE_KEY(Y, 28) \
|
||||
DEFINE_KEY(Z, 29) \
|
||||
DEFINE_KEY(D1, 30) \
|
||||
DEFINE_KEY(D2, 31) \
|
||||
DEFINE_KEY(D3, 32) \
|
||||
DEFINE_KEY(D4, 33) \
|
||||
DEFINE_KEY(D5, 34) \
|
||||
DEFINE_KEY(D6, 35) \
|
||||
DEFINE_KEY(D7, 36) \
|
||||
DEFINE_KEY(D8, 37) \
|
||||
DEFINE_KEY(D9, 38) \
|
||||
DEFINE_KEY(D0, 39) \
|
||||
DEFINE_KEY(Enter, 40) \
|
||||
DEFINE_KEY(Escape, 41) \
|
||||
DEFINE_KEY(Backspace, 42) \
|
||||
DEFINE_KEY(Tab, 43) \
|
||||
DEFINE_KEY(Space, 44) \
|
||||
DEFINE_KEY(Minus, 45) \
|
||||
DEFINE_KEY(Equals, 46) \
|
||||
DEFINE_KEY(LeftBracket, 47) \
|
||||
DEFINE_KEY(RightBracket, 48) \
|
||||
DEFINE_KEY(BackSlash, 49) \
|
||||
DEFINE_KEY(NonUSHash, 50) \
|
||||
DEFINE_KEY(Semicolon, 51) \
|
||||
DEFINE_KEY(Apostrophe, 52) \
|
||||
DEFINE_KEY(Grave, 53) \
|
||||
DEFINE_KEY(Comma, 54) \
|
||||
DEFINE_KEY(Period, 55) \
|
||||
DEFINE_KEY(Slash, 56) \
|
||||
DEFINE_KEY(Capslock, 57) \
|
||||
DEFINE_KEY(F1, 58) \
|
||||
DEFINE_KEY(F2, 59) \
|
||||
DEFINE_KEY(F3, 60) \
|
||||
DEFINE_KEY(F4, 61) \
|
||||
DEFINE_KEY(F5, 62) \
|
||||
DEFINE_KEY(F6, 63) \
|
||||
DEFINE_KEY(F7, 64) \
|
||||
DEFINE_KEY(F8, 65) \
|
||||
DEFINE_KEY(F9, 66) \
|
||||
DEFINE_KEY(F10, 67) \
|
||||
DEFINE_KEY(F11, 68) \
|
||||
DEFINE_KEY(F12, 69) \
|
||||
DEFINE_KEY(PrintScreen, 70) \
|
||||
DEFINE_KEY(ScrollLock, 71) \
|
||||
DEFINE_KEY(Pause, 72) \
|
||||
DEFINE_KEY(Insert, 73) \
|
||||
DEFINE_KEY(Home, 74) \
|
||||
DEFINE_KEY(PageUp, 75) \
|
||||
DEFINE_KEY(Delete, 76) \
|
||||
DEFINE_KEY(End, 77) \
|
||||
DEFINE_KEY(PageDown, 78) \
|
||||
DEFINE_KEY(Right, 79) \
|
||||
DEFINE_KEY(Left, 80) \
|
||||
DEFINE_KEY(Down, 81) \
|
||||
DEFINE_KEY(Up, 82) \
|
||||
DEFINE_KEY(NumlockClear, 83) \
|
||||
DEFINE_KEY(KP_Divide, 84) \
|
||||
DEFINE_KEY(KP_Multiply, 85) \
|
||||
DEFINE_KEY(KP_Minus, 86) \
|
||||
DEFINE_KEY(KP_Plus, 87) \
|
||||
DEFINE_KEY(KP_Enter, 88) \
|
||||
DEFINE_KEY(KP_1, 89) \
|
||||
DEFINE_KEY(KP_2, 90) \
|
||||
DEFINE_KEY(KP_3, 91) \
|
||||
DEFINE_KEY(KP_4, 92) \
|
||||
DEFINE_KEY(KP_5, 93) \
|
||||
DEFINE_KEY(KP_6, 94) \
|
||||
DEFINE_KEY(KP_7, 95) \
|
||||
DEFINE_KEY(KP_8, 96) \
|
||||
DEFINE_KEY(KP_9, 97) \
|
||||
DEFINE_KEY(KP_0, 98) \
|
||||
DEFINE_KEY(KP_Period, 99) \
|
||||
DEFINE_KEY(NonUSBackSlash, 100) \
|
||||
DEFINE_KEY(Application, 101) \
|
||||
DEFINE_KEY(Power, 102) \
|
||||
DEFINE_KEY(KP_Equals, 103) \
|
||||
DEFINE_KEY(F13, 104) \
|
||||
DEFINE_KEY(F14, 105) \
|
||||
DEFINE_KEY(F15, 106) \
|
||||
DEFINE_KEY(F16, 107) \
|
||||
DEFINE_KEY(F17, 108) \
|
||||
DEFINE_KEY(F18, 109) \
|
||||
DEFINE_KEY(F19, 110) \
|
||||
DEFINE_KEY(F20, 111) \
|
||||
DEFINE_KEY(F21, 112) \
|
||||
DEFINE_KEY(F22, 113) \
|
||||
DEFINE_KEY(F23, 114) \
|
||||
DEFINE_KEY(F24, 115) \
|
||||
DEFINE_KEY(Execute, 116) \
|
||||
DEFINE_KEY(Help, 117) \
|
||||
DEFINE_KEY(Menu, 118) \
|
||||
DEFINE_KEY(Select, 119) \
|
||||
DEFINE_KEY(Stop, 120) \
|
||||
DEFINE_KEY(Again, 121) \
|
||||
DEFINE_KEY(Undo, 122) \
|
||||
DEFINE_KEY(Cut, 123) \
|
||||
DEFINE_KEY(Copy, 124) \
|
||||
DEFINE_KEY(Paste, 125) \
|
||||
DEFINE_KEY(Find, 126) \
|
||||
DEFINE_KEY(Mute, 127) \
|
||||
DEFINE_KEY(VolumeUp, 128) \
|
||||
DEFINE_KEY(VolumeDown, 129) \
|
||||
DEFINE_KEY(KP_Comma, 133) \
|
||||
DEFINE_KEY(KP_EqualsAs400, 134) \
|
||||
DEFINE_KEY(International1, 135) \
|
||||
DEFINE_KEY(International2, 136) \
|
||||
DEFINE_KEY(International3, 137) \
|
||||
DEFINE_KEY(International4, 138) \
|
||||
DEFINE_KEY(International5, 139) \
|
||||
DEFINE_KEY(International6, 140) \
|
||||
DEFINE_KEY(International7, 141) \
|
||||
DEFINE_KEY(International8, 142) \
|
||||
DEFINE_KEY(International9, 143) \
|
||||
DEFINE_KEY(Language1, 144) \
|
||||
DEFINE_KEY(Language2, 145) \
|
||||
DEFINE_KEY(Language3, 146) \
|
||||
DEFINE_KEY(Language4, 147) \
|
||||
DEFINE_KEY(Language5, 148) \
|
||||
DEFINE_KEY(Language6, 149) \
|
||||
DEFINE_KEY(Language7, 150) \
|
||||
DEFINE_KEY(Language8, 151) \
|
||||
DEFINE_KEY(Language9, 152) \
|
||||
DEFINE_KEY(AltErase, 153) \
|
||||
DEFINE_KEY(SysReq, 154) \
|
||||
DEFINE_KEY(Cancel, 155) \
|
||||
DEFINE_KEY(clear, 156) \
|
||||
DEFINE_KEY(Prior, 157) \
|
||||
DEFINE_KEY(Return2, 158) \
|
||||
DEFINE_KEY(Separator, 159) \
|
||||
DEFINE_KEY(Out, 160) \
|
||||
DEFINE_KEY(Oper, 161) \
|
||||
DEFINE_KEY(ClearAgain, 162) \
|
||||
DEFINE_KEY(CRSEL, 163) \
|
||||
DEFINE_KEY(EXSEL, 164) \
|
||||
DEFINE_KEY(KP_00, 176) \
|
||||
DEFINE_KEY(KP_000, 177) \
|
||||
DEFINE_KEY(ThousandsSeparator, 178) \
|
||||
DEFINE_KEY(DecimalSeparator, 179) \
|
||||
DEFINE_KEY(CurrencyUnit, 180) \
|
||||
DEFINE_KEY(CurrencySubUnit, 181) \
|
||||
DEFINE_KEY(KP_LeftParen, 182) \
|
||||
DEFINE_KEY(KP_RightParent, 183) \
|
||||
DEFINE_KEY(KP_LeftBrace, 184) \
|
||||
DEFINE_KEY(KP_RightBrace, 185) \
|
||||
DEFINE_KEY(KP_Tab, 186) \
|
||||
DEFINE_KEY(KP_BackSpace, 187) \
|
||||
DEFINE_KEY(KP_A, 188) \
|
||||
DEFINE_KEY(KP_B, 189) \
|
||||
DEFINE_KEY(KP_C, 190) \
|
||||
DEFINE_KEY(KP_D, 191) \
|
||||
DEFINE_KEY(KP_E, 192) \
|
||||
DEFINE_KEY(KP_F, 193) \
|
||||
DEFINE_KEY(KP_XOR, 194) \
|
||||
DEFINE_KEY(KP_Power, 195) \
|
||||
DEFINE_KEY(KP_Percent, 196) \
|
||||
DEFINE_KEY(KP_Less, 197) \
|
||||
DEFINE_KEY(KP_Greater, 198) \
|
||||
DEFINE_KEY(KP_Ampersand, 199) \
|
||||
DEFINE_KEY(KP_DoubleAmpersand, 200) \
|
||||
DEFINE_KEY(KP_VerticalBar, 201) \
|
||||
DEFINE_KEY(KP_DoubleVerticalBar, 202) \
|
||||
DEFINE_KEY(KP_Colon, 203) \
|
||||
DEFINE_KEY(KP_Hash, 204) \
|
||||
DEFINE_KEY(KP_Space, 205) \
|
||||
DEFINE_KEY(KP_At, 206) \
|
||||
DEFINE_KEY(KP_EXCLAM, 207) \
|
||||
DEFINE_KEY(KP_MemStore, 208) \
|
||||
DEFINE_KEY(KP_MemRecall, 209) \
|
||||
DEFINE_KEY(KP_MemClear, 210) \
|
||||
DEFINE_KEY(KP_MemAdd, 211) \
|
||||
DEFINE_KEY(KP_MemSubstract, 212) \
|
||||
DEFINE_KEY(KP_MemMultiply, 213) \
|
||||
DEFINE_KEY(KP_MemDivide, 214) \
|
||||
DEFINE_KEY(KP_PlusMinus, 215) \
|
||||
DEFINE_KEY(KP_Clear, 216) \
|
||||
DEFINE_KEY(KP_ClearEntry, 217) \
|
||||
DEFINE_KEY(KP_Binary, 218) \
|
||||
DEFINE_KEY(KP_Octal, 219) \
|
||||
DEFINE_KEY(KP_Decimal, 220) \
|
||||
DEFINE_KEY(KP_Hexadecimal, 221) \
|
||||
DEFINE_KEY(LeftControl, 224) \
|
||||
DEFINE_KEY(LeftShift, 225) \
|
||||
DEFINE_KEY(LeftAlt, 226) \
|
||||
DEFINE_KEY(LeftGui, 227) \
|
||||
DEFINE_KEY(RightControl, 228) \
|
||||
DEFINE_KEY(RightShift, 229) \
|
||||
DEFINE_KEY(RightAlt, 230) \
|
||||
DEFINE_KEY(RightGui, 231)
|
||||
|
||||
#define BLAH_BUTTON_DEFINITIONS \
|
||||
DEFINE_BTN(None, -1) \
|
||||
DEFINE_BTN(A, 0) \
|
||||
DEFINE_BTN(B, 1) \
|
||||
DEFINE_BTN(X, 2) \
|
||||
DEFINE_BTN(Y, 3) \
|
||||
DEFINE_BTN(Back, 4) \
|
||||
DEFINE_BTN(Select, 5) \
|
||||
DEFINE_BTN(Start, 6) \
|
||||
DEFINE_BTN(LeftStick, 7) \
|
||||
DEFINE_BTN(RightStick, 8) \
|
||||
DEFINE_BTN(LeftShoulder, 9) \
|
||||
DEFINE_BTN(RightShoulder, 10) \
|
||||
DEFINE_BTN(Up, 11) \
|
||||
DEFINE_BTN(Down, 12) \
|
||||
DEFINE_BTN(Left, 13) \
|
||||
DEFINE_BTN(Right, 14)
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
namespace Input
|
||||
{
|
||||
// maximum number of controllers the input can handle
|
||||
constexpr int max_controllers = 8;
|
||||
|
||||
// maximum number of buttons the input will track
|
||||
constexpr int max_controller_buttons = 64;
|
||||
|
||||
// maximum number of controller axis the input will track
|
||||
constexpr int max_controller_axis = 16;
|
||||
|
||||
// maximum number of mouse buttons the input will track
|
||||
constexpr int max_mouse_buttons = 16;
|
||||
|
||||
// maximum number of keys the input will track
|
||||
constexpr int max_keyboard_keys = 512;
|
||||
|
||||
// maximum length of text input that can be received per-frame
|
||||
constexpr int max_text_input = 256;
|
||||
|
||||
// maximum number of nodes within a virtual input device
|
||||
constexpr int max_virtual_nodes = 32;
|
||||
}
|
||||
|
||||
struct ControllerState
|
||||
{
|
||||
// The name of the gamepad, or NULL if not connected
|
||||
const char* name;
|
||||
|
||||
// Whether this gamepad is connected
|
||||
bool is_connected;
|
||||
|
||||
// Whether this gamepad is a standard Game Controller
|
||||
bool is_gamepad;
|
||||
|
||||
// The total button count for this controller
|
||||
int button_count;
|
||||
|
||||
// The total axis count for this controller
|
||||
int axis_count;
|
||||
|
||||
// An array holding the pressed state of each button
|
||||
bool pressed[Input::max_controller_buttons];
|
||||
|
||||
// An array holding the down state of each button
|
||||
bool down[Input::max_controller_buttons];
|
||||
|
||||
// An array holding the released state of each button
|
||||
bool released[Input::max_controller_buttons];
|
||||
|
||||
// An array holding the value state of each axis
|
||||
float axis[Input::max_controller_axis];
|
||||
|
||||
// Timestamp, in milliseconds, since each button was last pressed
|
||||
uint64_t button_timestamp[Input::max_controller_buttons];
|
||||
|
||||
// Timestamp, in milliseconds, since each axis last had a value set
|
||||
uint64_t axis_timestamp[Input::max_controller_axis];
|
||||
|
||||
// The USB Vendor ID
|
||||
uint16_t vendor;
|
||||
|
||||
// The USB Product ID
|
||||
uint16_t product;
|
||||
|
||||
// the Product Version
|
||||
uint16_t version;
|
||||
};
|
||||
|
||||
struct KeyboardState
|
||||
{
|
||||
bool pressed[Input::max_keyboard_keys];
|
||||
bool down[Input::max_keyboard_keys];
|
||||
bool released[Input::max_keyboard_keys];
|
||||
uint64_t timestamp[Input::max_keyboard_keys];
|
||||
char text[Input::max_text_input];
|
||||
};
|
||||
|
||||
struct MouseState
|
||||
{
|
||||
bool pressed[Input::max_mouse_buttons];
|
||||
bool down[Input::max_mouse_buttons];
|
||||
bool released[Input::max_mouse_buttons];
|
||||
uint64_t timestamp[Input::max_mouse_buttons];
|
||||
Vec2 screen_position;
|
||||
Vec2 draw_position;
|
||||
Vec2 position;
|
||||
Point wheel;
|
||||
};
|
||||
|
||||
// An Input State, which stores the state for gamepads, keyboard, and mouse
|
||||
struct InputState
|
||||
{
|
||||
// All the Gamepads. Note that not all gamepads are necessarily connected,
|
||||
// and each one must be checked before use.
|
||||
ControllerState controllers[Input::max_controllers];
|
||||
|
||||
// The current Keyboard state
|
||||
KeyboardState keyboard;
|
||||
|
||||
// The current Mouse state
|
||||
MouseState mouse;
|
||||
|
||||
};
|
||||
|
||||
// Keyboard Keys
|
||||
enum class Key
|
||||
{
|
||||
#define DEFINE_KEY(name, value) name = value,
|
||||
BLAH_KEY_DEFINITIONS
|
||||
#undef DEFINE_KEY
|
||||
};
|
||||
|
||||
// Game Controller Buttons
|
||||
enum class Button
|
||||
{
|
||||
#define DEFINE_BTN(name, value) name = value,
|
||||
BLAH_BUTTON_DEFINITIONS
|
||||
#undef DEFINE_BTN
|
||||
};
|
||||
|
||||
// Game Controller Axes
|
||||
enum class Axis
|
||||
{
|
||||
None = -1,
|
||||
LeftX = 0,
|
||||
LeftY = 1,
|
||||
RightX = 2,
|
||||
RightY = 3,
|
||||
LeftTrigger = 4,
|
||||
RightTrigger = 5
|
||||
};
|
||||
|
||||
// Mouse Buttons
|
||||
enum class MouseButton
|
||||
{
|
||||
None = -1,
|
||||
Left = 0,
|
||||
Middle = 1,
|
||||
Right = 2,
|
||||
};
|
||||
|
||||
namespace Input
|
||||
{
|
||||
// Returns the Input State of the current frame.
|
||||
// This pointer is only valid for the current frame and should not be stored.
|
||||
const InputState* state();
|
||||
|
||||
// Returns the Input State of the previous frame.
|
||||
// This pointer is only valid for the current frame and should not be stored.
|
||||
const InputState* last_state();
|
||||
|
||||
// Gets the Mouse Position
|
||||
Vec2 mouse();
|
||||
|
||||
// Gets the Draw Mouse Position (Mouse Position / Window Size * Draw Size)
|
||||
Vec2 mouse_draw();
|
||||
|
||||
// Gets the Mouse Position in Screen Coordinates
|
||||
Vec2 mouse_screen();
|
||||
|
||||
// Checks if the given Mouse Button is pressed
|
||||
bool pressed(MouseButton button);
|
||||
|
||||
// Checks if the given Mouse Button is down
|
||||
bool down(MouseButton button);
|
||||
|
||||
// Checks if the given Mouse Button is released
|
||||
bool released(MouseButton button);
|
||||
|
||||
// Gets the Mouse Wheel
|
||||
Point mouse_wheel();
|
||||
|
||||
// Checks if the keyboard key was pressed this frame
|
||||
bool pressed(Key key);
|
||||
|
||||
// Checks if the keyboard key was held this frame
|
||||
bool down(Key key);
|
||||
|
||||
// Checks if the keyboard key was released this frame
|
||||
bool released(Key key);
|
||||
|
||||
// Checks if the Left or Right Ctrl Key is down
|
||||
bool ctrl();
|
||||
|
||||
// Checks if the Left or Right Shift Key is down
|
||||
bool shift();
|
||||
|
||||
// Checks if the Left or Right Alt Key is down
|
||||
bool alt();
|
||||
|
||||
// Get the current Text Input
|
||||
const char* text();
|
||||
|
||||
// Gets the controller info for the current controller index.
|
||||
// If the controller is not connected or the index it out of range, this will set an unconnected controller.
|
||||
const ControllerState* controller(int controller_index);
|
||||
|
||||
// Checks if the button on the controller was pressed this frame.
|
||||
// If the controller is not connected, or the index is out of range, this will return false.
|
||||
bool pressed(int controller_index, Button button);
|
||||
|
||||
// Checks if the button on the controller was held this frame.
|
||||
// If the controller is not connected, or the index is out of range, this will return false.
|
||||
bool down(int controller_index, Button button);
|
||||
|
||||
// Checks if the button on the controller was released this frame.
|
||||
// If the controller is not connected, or the index is out of range, this will return false.
|
||||
bool released(int controller_index, Button button);
|
||||
|
||||
// returns the value of the given axis
|
||||
float axis_check(int controller_index, Axis axis);
|
||||
|
||||
// checks the given virtual axis, described by 2 keys. `fallback` is returned if both keys are held
|
||||
int axis_check(int fallback, Key negative, Key positive);
|
||||
|
||||
// checks the given virtual axis, described by 2 buttons. `fallback` is returned if both buttons are held
|
||||
int axis_check(int fallback, int controller_index, Button negative, Button positive);
|
||||
|
||||
// returns a string name of the given key
|
||||
const char* name_of(Key key);
|
||||
|
||||
// returns a string name of the given button
|
||||
const char* name_of(Button button);
|
||||
}
|
||||
}
|
86
include/blah/input/virtual_axis.h
Normal file
86
include/blah/input/virtual_axis.h
Normal file
@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
#include <blah/input/input.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
// A virtual controller axis, which can be used to map multiple
|
||||
// inputs to an axis. Note that you must call `update` every frame!
|
||||
class VirtualAxis
|
||||
{
|
||||
private:
|
||||
struct KeysNode
|
||||
{
|
||||
Key positive = Key::Unknown;
|
||||
Key negative = Key::Unknown;
|
||||
|
||||
int value = 0;
|
||||
|
||||
void init(Key negative, Key positive);
|
||||
void update();
|
||||
};
|
||||
|
||||
struct ButtonsNode
|
||||
{
|
||||
int gamepad_id = 0;
|
||||
Button positive = Button::None;
|
||||
Button negative = Button::None;
|
||||
|
||||
int value = 0;
|
||||
|
||||
void init(int gamepad_id, Button negative, Button positive);
|
||||
void update();
|
||||
};
|
||||
|
||||
struct AxisNode
|
||||
{
|
||||
int gamepad_id = 0;
|
||||
Axis axis = Axis::None;
|
||||
float deadzone = 0;
|
||||
|
||||
float value = 0;
|
||||
|
||||
void init(int gamepad_id, Axis axis, float deadzone);
|
||||
void update();
|
||||
};
|
||||
|
||||
KeysNode m_keys[Input::max_virtual_nodes];
|
||||
ButtonsNode m_buttons[Input::max_virtual_nodes];
|
||||
AxisNode m_axes[Input::max_virtual_nodes];
|
||||
int m_keys_len = 0;
|
||||
int m_buttons_len = 0;
|
||||
int m_axes_len = 0;
|
||||
|
||||
float m_press_buffer = 0;
|
||||
float m_release_buffer = 0;
|
||||
float m_repeat_delay = 0;
|
||||
float m_repeat_interval = 0;
|
||||
|
||||
float m_value = 0;
|
||||
int m_value_i = 0;
|
||||
float m_last_value = 0;
|
||||
int m_last_value_i = 0;
|
||||
bool m_pressed = false;
|
||||
bool m_released = false;
|
||||
float m_last_press_time = -1;
|
||||
float m_last_release_time = -1;
|
||||
float m_repeat_press_time = -1;
|
||||
|
||||
public:
|
||||
VirtualAxis& add_keys(Key negative, Key positive);
|
||||
VirtualAxis& add_buttons(int gamepad_id, Button negative, Button positive);
|
||||
VirtualAxis& add_axis(int gamepad_id, Axis axis, float deadzone);
|
||||
VirtualAxis& repeat(float m_repeat_delay, float m_repeat_interval);
|
||||
VirtualAxis& press_buffer(float duration);
|
||||
VirtualAxis& release_buffer(float duration);
|
||||
|
||||
void update();
|
||||
float value() const { return m_value; }
|
||||
int value_i() const { return m_value_i; }
|
||||
float last_value() const { return m_last_value; }
|
||||
int last_value_i() const { return m_last_value_i; }
|
||||
bool pressed() const { return m_pressed; }
|
||||
bool released() const { return m_released; }
|
||||
void clear_press_buffer() { m_last_press_time = -1; m_pressed = false; }
|
||||
void clear_release_buffer() { m_last_release_time = -1; m_released = false; }
|
||||
};
|
||||
}
|
83
include/blah/input/virtual_button.h
Normal file
83
include/blah/input/virtual_button.h
Normal file
@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
#include <blah/input/input.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
class VirtualButton
|
||||
{
|
||||
private:
|
||||
struct KeyNode
|
||||
{
|
||||
Key key = Key::Unknown;
|
||||
|
||||
bool down = false;
|
||||
bool pressed = false;
|
||||
bool released = false;
|
||||
|
||||
void init(Key key);
|
||||
void update();
|
||||
};
|
||||
|
||||
struct ButtonNode
|
||||
{
|
||||
int gamepad_id = 0;
|
||||
Button button = Button::None;
|
||||
|
||||
bool down = false;
|
||||
bool pressed = false;
|
||||
bool released = false;
|
||||
|
||||
void init(int gamepad_id, Button button);
|
||||
void update();
|
||||
};
|
||||
|
||||
struct AxisNode
|
||||
{
|
||||
int gamepad_id = 0;
|
||||
Axis axis = Axis::None;
|
||||
float threshold = 0;
|
||||
bool greater_than = false;
|
||||
|
||||
bool down = false;
|
||||
bool pressed = false;
|
||||
bool released = false;
|
||||
|
||||
void init(int gamepad_id, Axis axis, float threshold, bool greater_than);
|
||||
void update();
|
||||
};
|
||||
|
||||
KeyNode m_keys[Input::max_virtual_nodes];
|
||||
ButtonNode m_buttons[Input::max_virtual_nodes];
|
||||
AxisNode m_axes[Input::max_virtual_nodes];
|
||||
int m_keys_len = 0;
|
||||
int m_buttons_len = 0;
|
||||
int m_axes_len = 0;
|
||||
|
||||
float m_press_buffer = 0;
|
||||
float m_release_buffer = 0;
|
||||
float m_repeat_delay = 0;
|
||||
float m_repeat_interval = 0;
|
||||
|
||||
bool m_down = false;
|
||||
bool m_pressed = false;
|
||||
bool m_released = false;
|
||||
float m_last_press_time = -1;
|
||||
float m_last_release_time = -1;
|
||||
float m_repeat_press_time = -1;
|
||||
|
||||
public:
|
||||
VirtualButton& add_key(Key key);
|
||||
VirtualButton& add_button(int gamepad_id, Button button);
|
||||
VirtualButton& add_axis(int gamepad_id, Axis axis, float threshold, bool greater_than);
|
||||
VirtualButton& repeat(float m_repeat_delay, float m_repeat_interval);
|
||||
VirtualButton& press_buffer(float duration);
|
||||
VirtualButton& release_buffer(float duration);
|
||||
|
||||
void update();
|
||||
bool down() const { return m_down; }
|
||||
bool pressed() const { return m_pressed; }
|
||||
bool released() const { return m_released; }
|
||||
void clear_press_buffer() { m_last_press_time = -1; m_pressed = false; }
|
||||
void clear_release_buffer() { m_last_release_time = -1; m_released = false; }
|
||||
};
|
||||
}
|
97
include/blah/input/virtual_stick.h
Normal file
97
include/blah/input/virtual_stick.h
Normal file
@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
#include <blah/input/input.h>
|
||||
#include <blah/math/vec2.h>
|
||||
#include <blah/math/point.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
// A virtual controller stick, which can be used to map multiple
|
||||
// inputs to a stick. Note that you must call `update` every frame!
|
||||
class VirtualStick
|
||||
{
|
||||
private:
|
||||
struct KeysNode
|
||||
{
|
||||
Key left;
|
||||
Key right;
|
||||
Key up;
|
||||
Key down;
|
||||
|
||||
Point value;
|
||||
|
||||
void init(Key left, Key right, Key up, Key down);
|
||||
void update();
|
||||
};
|
||||
|
||||
struct ButtonsNode
|
||||
{
|
||||
int gamepad_id;
|
||||
Button left;
|
||||
Button right;
|
||||
Button up;
|
||||
Button down;
|
||||
|
||||
Point value;
|
||||
|
||||
void init(int gamepad_id, Button left, Button right, Button up, Button down);
|
||||
void update();
|
||||
};
|
||||
|
||||
struct AxesNode
|
||||
{
|
||||
int gamepad_id;
|
||||
Axis horizontal;
|
||||
Axis vertical;
|
||||
float deadzone;
|
||||
|
||||
Vec2 value;
|
||||
|
||||
void init(int gamepad_id, Axis horizontal, Axis vertical, float deadzone);
|
||||
void update();
|
||||
};
|
||||
|
||||
KeysNode m_keys[Input::max_virtual_nodes];
|
||||
ButtonsNode m_buttons[Input::max_virtual_nodes];
|
||||
AxesNode m_axes[Input::max_virtual_nodes];
|
||||
int m_keys_len = 0;
|
||||
int m_buttons_len = 0;
|
||||
int m_axes_len = 0;
|
||||
|
||||
float m_press_buffer = 0;
|
||||
float m_release_buffer = 0;
|
||||
float m_repeat_delay = 0;
|
||||
float m_repeat_interval = 0;
|
||||
|
||||
Vec2 m_value = Vec2();
|
||||
Point m_value_i = Point();
|
||||
Vec2 m_last_value = Vec2();
|
||||
Point m_last_value_i = Point();
|
||||
bool m_pressed = false;
|
||||
bool m_released = false;
|
||||
|
||||
float m_i_deadzone;
|
||||
float m_last_press_time = -1;
|
||||
float m_last_release_time = -1;
|
||||
float m_repeat_press_time = -1;
|
||||
|
||||
public:
|
||||
VirtualStick();
|
||||
VirtualStick(float iDeadzone);
|
||||
VirtualStick& add_keys(Key left, Key right, Key up, Key down);
|
||||
VirtualStick& add_buttons(int gamepad_id, Button left, Button right, Button up, Button down);
|
||||
VirtualStick& add_axes(int gamepad_id, Axis horizontal, Axis vertical, float deadzone);
|
||||
VirtualStick& repeat(float m_repeat_delay, float m_repeat_interval);
|
||||
VirtualStick& press_buffer(float duration);
|
||||
VirtualStick& release_buffer(float duration);
|
||||
|
||||
void update();
|
||||
const Vec2& value() const { return m_value; }
|
||||
const Point& value_i() const { return m_value_i; }
|
||||
const Vec2& last_value() const { return m_last_value; }
|
||||
const Point& last_value_i() const { return m_last_value_i; }
|
||||
bool pressed() const { return m_pressed; }
|
||||
bool released() const { return m_released; }
|
||||
void clear_press_buffer() { m_last_press_time = 0; }
|
||||
void clear_release_buffer() { m_last_release_time = 0; }
|
||||
};
|
||||
}
|
79
include/blah/math/calc.h
Normal file
79
include/blah/math/calc.h
Normal file
@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
namespace Calc
|
||||
{
|
||||
constexpr float PI = 3.141592653f;
|
||||
constexpr float TAU = PI * 2.0f;
|
||||
constexpr float RIGHT = 0;
|
||||
constexpr float LEFT = PI;
|
||||
constexpr float UP = PI / -2;
|
||||
constexpr float DOWN = PI / 2;
|
||||
|
||||
float rand_float(float min, float maxExc);
|
||||
|
||||
float rand_float(float maxExc);
|
||||
|
||||
int rand_int(int min, int maxExc);
|
||||
|
||||
int rand_int(int maxExc);
|
||||
|
||||
int rand_int();
|
||||
|
||||
float approach(float t, float target, float maxDelta);
|
||||
|
||||
float clamp(float t, float min, float max);
|
||||
|
||||
int clamp_int(int t, int min, int max);
|
||||
|
||||
float map(float t, float old_min, float old_max, float new_min, float new_max);
|
||||
|
||||
float clamped_map(float t, float old_min, float old_max, float new_min, float new_max);
|
||||
|
||||
int sign(int x);
|
||||
|
||||
float sign(float x);
|
||||
|
||||
int abs(int x);
|
||||
|
||||
float abs(float x);
|
||||
|
||||
template<class T, class U>
|
||||
T min(T a, U b) { return (T)(a < b ? a : b); }
|
||||
|
||||
template<class T, class U>
|
||||
T max(T a, U b) { return (T)(a > b ? a : b); }
|
||||
|
||||
float round(float x);
|
||||
|
||||
float floor(float x);
|
||||
|
||||
float ceiling(float x);
|
||||
|
||||
float mod(float x, float m);
|
||||
|
||||
float sin(float x);
|
||||
|
||||
float cos(float x);
|
||||
|
||||
float atan2(float y, float x);
|
||||
|
||||
float pow(float x, float n);
|
||||
|
||||
float sqrt(float x);
|
||||
|
||||
float snap(float val, float interval);
|
||||
|
||||
float angle_diff(float radians_a, float radians_b);
|
||||
|
||||
float angle_lerp(float radians_a, float radians_b, float p);
|
||||
|
||||
float lerp(float a, float b, float t);
|
||||
|
||||
bool is_big_endian();
|
||||
|
||||
bool is_little_endian();
|
||||
};
|
||||
}
|
22
include/blah/math/circle.h
Normal file
22
include/blah/math/circle.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include <blah/math/vec2.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
struct Circle
|
||||
{
|
||||
Vec2 center;
|
||||
float radius;
|
||||
|
||||
Circle()
|
||||
: center(), radius(0) {}
|
||||
|
||||
Circle(Vec2 center, float radius)
|
||||
: center(center), radius(radius) {}
|
||||
|
||||
Circle(float x, float y, float radius)
|
||||
: center(x, y), radius(radius) {}
|
||||
|
||||
void project(const Vec2& axis, float* min, float* max) const;
|
||||
};
|
||||
}
|
64
include/blah/math/color.h
Normal file
64
include/blah/math/color.h
Normal file
@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
struct Vec4;
|
||||
|
||||
struct Color
|
||||
{
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t a;
|
||||
|
||||
Color();
|
||||
Color(int rgb);
|
||||
Color(int rgb, float alpha);
|
||||
Color(uint8_t r, uint8_t g, uint8_t b);
|
||||
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
|
||||
// Parses a Hex string in the format of "#00000000" or "0x00000000" or "00000000"
|
||||
Color(const char* hexCstr);
|
||||
|
||||
// Premultiplies the Color
|
||||
void premultiply();
|
||||
|
||||
// Sets a Hex string to the given buffer, in the format of RRGGBBAA
|
||||
// The buffer must be at least 8 bytes long
|
||||
void to_hex_rgba(char* buffer) const;
|
||||
|
||||
// Sets a Hex string to the given buffer, in the format of RRGGBB
|
||||
// The buffer must be at least 6 bytes long
|
||||
void to_hex_rgb(char* buffer) const;
|
||||
|
||||
uint32_t to_rgba() const;
|
||||
|
||||
Vec4 to_vec4() const;
|
||||
|
||||
// Returns a RGBA Color representation of the integer value
|
||||
static Color from_rgba(uint32_t value);
|
||||
|
||||
// Returns a RGB Color representation of the integer value, with Alpha = 255
|
||||
static Color from_rgb(uint32_t value);
|
||||
|
||||
static Color lerp(Color a, Color b, float amount);
|
||||
|
||||
// Mutliplties the Color
|
||||
Color operator*(float multiply) const;
|
||||
|
||||
// assignment from int
|
||||
Color& operator= (const int rgb);
|
||||
|
||||
static const Color transparent;
|
||||
static const Color white;
|
||||
static const Color black;
|
||||
static const Color red;
|
||||
static const Color green;
|
||||
static const Color blue;
|
||||
static const Color yellow;
|
||||
static const Color orange;
|
||||
static const Color purple;
|
||||
static const Color teal;
|
||||
};
|
||||
}
|
336
include/blah/math/ease.h
Normal file
336
include/blah/math/ease.h
Normal file
@ -0,0 +1,336 @@
|
||||
#pragma once
|
||||
#include <blah/math/calc.h>
|
||||
#include <blah/core/log.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
using Easer = float (*)(float);
|
||||
|
||||
enum class Easers
|
||||
{
|
||||
QuadIn, QuadOut, QuadInOut,
|
||||
CubeIn, CubeOut, CubeInOut,
|
||||
QuartIn, QuartOut, QuartInOut,
|
||||
QuintIn, QuintOut, QuintInOut,
|
||||
SineIn, SineOut, SineInOut,
|
||||
CircIn, CircOut, CircInOut,
|
||||
ExpIn, ExpOut, ExpInOut,
|
||||
ElasticIn, ElasticOut, ElasticInOut,
|
||||
BackIn, BackOut, BackInOut,
|
||||
BounceIn, BounceOut, BounceInOut,
|
||||
_Count
|
||||
};
|
||||
|
||||
namespace Ease
|
||||
{
|
||||
/*
|
||||
Adapted from functions here: https://github.com/warrenm/AHEasing/blob/master/AHEasing/easing.c
|
||||
For previews go here: https://easings.net/
|
||||
*/
|
||||
|
||||
inline float linear(float t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
inline float quad_in(float t)
|
||||
{
|
||||
return t * t;
|
||||
}
|
||||
|
||||
inline float quad_out(float t)
|
||||
{
|
||||
return -(t * (t - 2));
|
||||
}
|
||||
|
||||
inline float quad_in_out(float t)
|
||||
{
|
||||
if (t < 0.5f)
|
||||
return 2 * t * t;
|
||||
else
|
||||
{
|
||||
return (-2 * t * t) + (4 * t) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline float cube_in(float t)
|
||||
{
|
||||
return t * t * t;
|
||||
}
|
||||
|
||||
inline float cube_out(float t)
|
||||
{
|
||||
float f = (t - 1);
|
||||
return f * f * f + 1;
|
||||
}
|
||||
|
||||
inline float cube_in_out(float t)
|
||||
{
|
||||
if (t < 0.5f)
|
||||
return 4 * t * t * t;
|
||||
else
|
||||
{
|
||||
float f = ((2 * t) - 2);
|
||||
return 0.5f * f * f * f + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline float quart_in(float t)
|
||||
{
|
||||
return t * t * t * t;
|
||||
}
|
||||
|
||||
inline float quart_out(float t)
|
||||
{
|
||||
float f = (t - 1);
|
||||
return f * f * f * (1 - t) + 1;
|
||||
}
|
||||
|
||||
inline float quart_in_out(float t)
|
||||
{
|
||||
if (t < 0.5f)
|
||||
return 8 * t * t * t * t;
|
||||
else
|
||||
{
|
||||
float f = (t - 1);
|
||||
return -8 * f * f * f * f + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline float quint_in(float t)
|
||||
{
|
||||
return t * t * t * t * t;
|
||||
}
|
||||
|
||||
inline float quint_out(float t)
|
||||
{
|
||||
float f = (t - 1);
|
||||
return f * f * f * f * f + 1;
|
||||
}
|
||||
|
||||
inline float quint_in_out(float t)
|
||||
{
|
||||
if (t < 0.5f)
|
||||
return 16 * t * t * t * t * t;
|
||||
else
|
||||
{
|
||||
float f = ((2 * t) - 2);
|
||||
return 0.5f * f * f * f * f * f + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline float sine_in(float t)
|
||||
{
|
||||
return Calc::sin((t - 1) * Calc::PI * 0.5f) + 1;
|
||||
}
|
||||
|
||||
inline float sine_out(float t)
|
||||
{
|
||||
return Calc::sin(t * (Calc::PI * 0.5f));
|
||||
}
|
||||
|
||||
inline float sine_in_out(float t)
|
||||
{
|
||||
return 0.5f * (1 - Calc::cos(t * Calc::PI));
|
||||
}
|
||||
|
||||
inline float circ_in(float t)
|
||||
{
|
||||
return 1 - Calc::sqrt(1 - (t * t));
|
||||
}
|
||||
|
||||
inline float circ_out(float t)
|
||||
{
|
||||
return Calc::sqrt((2 - t) * t);
|
||||
}
|
||||
|
||||
inline float circ_in_out(float t)
|
||||
{
|
||||
if (t < 0.5f)
|
||||
return 0.5f * (1 - Calc::sqrt(1 - 4 * (t * t)));
|
||||
else
|
||||
return 0.5f * (Calc::sqrt(-((2 * t) - 3) * ((2 * t) - 1)) + 1);
|
||||
}
|
||||
|
||||
inline float exp_in(float t)
|
||||
{
|
||||
return (t == 0) ? 0 : Calc::pow(2, 10 * (t - 1));
|
||||
}
|
||||
|
||||
inline float exp_out(float t)
|
||||
{
|
||||
return (t == 1) ? 1 : 1 - Calc::pow(2, -10 * t);
|
||||
}
|
||||
|
||||
inline float exp_in_out(float t)
|
||||
{
|
||||
if (t == 0 || t == 1)
|
||||
return t;
|
||||
|
||||
if (t < 0.5f)
|
||||
return 0.5f * Calc::pow(2, (20 * t) - 10);
|
||||
else
|
||||
return -0.5f * Calc::pow(2, (-20 * t) + 10) + 1;
|
||||
}
|
||||
|
||||
inline float elastic_in(float t)
|
||||
{
|
||||
return Calc::sin(13 * (Calc::PI * 0.5f) * t) * Calc::pow(2, 10 * (t - 1));
|
||||
}
|
||||
|
||||
inline float elastic_out(float t)
|
||||
{
|
||||
return Calc::sin(-13 * (Calc::PI * 0.5f) * (t + 1)) * Calc::pow(2, -10 * t) + 1;
|
||||
}
|
||||
|
||||
inline float elastic_in_out(float t)
|
||||
{
|
||||
if (t < 0.5f)
|
||||
return 0.5f * Calc::sin(13 * (Calc::PI * 0.5f) * (2 * t)) * Calc::pow(2, 10 * ((2 * t) - 1));
|
||||
else
|
||||
return 0.5f * (Calc::sin(-13 * (Calc::PI * 0.5f) * ((2 * t - 1) + 1)) * Calc::pow(2, -10 * (2 * t - 1)) + 2);
|
||||
}
|
||||
|
||||
inline float back_in(float t)
|
||||
{
|
||||
return t * t * t - t * Calc::sin(t * Calc::PI);
|
||||
}
|
||||
|
||||
inline float back_out(float t)
|
||||
{
|
||||
float f = (1 - t);
|
||||
return 1 - (f * f * f - f * Calc::sin(f * Calc::PI));
|
||||
}
|
||||
|
||||
inline float back_in_out(float t)
|
||||
{
|
||||
if (t < 0.5f)
|
||||
{
|
||||
float f = 2 * t;
|
||||
return 0.5f * (f * f * f - f * Calc::sin(f * Calc::PI));
|
||||
}
|
||||
else
|
||||
{
|
||||
float f = (1 - (2 * t - 1));
|
||||
return 0.5f * (1 - (f * f * f - f * Calc::sin(f * Calc::PI))) + 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
inline float bounce_out(float t)
|
||||
{
|
||||
if (t < 4 / 11.0f)
|
||||
return (121 * t * t) / 16.0f;
|
||||
else if (t < 8 / 11.0f)
|
||||
return (363 / 40.0f * t * t) - (99 / 10.0f * t) + 17 / 5.0f;
|
||||
else if (t < 9 / 10.0f)
|
||||
return (4356 / 361.0f * t * t) - (35442 / 1805.0f * t) + 16061 / 1805.0f;
|
||||
else
|
||||
return (54 / 5.0f * t * t) - (513 / 25.0f * t) + 268 / 25.0f;
|
||||
}
|
||||
|
||||
inline float bounce_in(float t)
|
||||
{
|
||||
return 1 - bounce_out(1 - t);
|
||||
}
|
||||
|
||||
inline float bounce_in_out(float t)
|
||||
{
|
||||
if (t < 0.5f)
|
||||
return 0.5f * bounce_in(t * 2);
|
||||
else
|
||||
return 0.5f * bounce_out(t * 2 - 1) + 0.5f;
|
||||
}
|
||||
|
||||
inline Easer get(Easers e)
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case Easers::CubeIn: return &cube_in;
|
||||
case Easers::CubeOut: return &cube_out;
|
||||
case Easers::CubeInOut: return &cube_in_out;
|
||||
|
||||
case Easers::QuadIn: return &quad_in;
|
||||
case Easers::QuadOut: return &quad_out;
|
||||
case Easers::QuadInOut: return &quad_in_out;
|
||||
|
||||
case Easers::QuartIn: return &quart_in;
|
||||
case Easers::QuartOut: return &quart_out;
|
||||
case Easers::QuartInOut: return &quart_in_out;
|
||||
|
||||
case Easers::QuintIn: return &quint_in;
|
||||
case Easers::QuintOut: return &quint_out;
|
||||
case Easers::QuintInOut: return &quint_in_out;
|
||||
|
||||
case Easers::SineIn: return &sine_in;
|
||||
case Easers::SineOut: return &sine_out;
|
||||
case Easers::SineInOut: return &sine_in_out;
|
||||
|
||||
case Easers::CircIn: return &circ_in;
|
||||
case Easers::CircOut: return &circ_out;
|
||||
case Easers::CircInOut: return &circ_in_out;
|
||||
|
||||
case Easers::ExpIn: return &exp_in;
|
||||
case Easers::ExpOut: return &exp_out;
|
||||
case Easers::ExpInOut: return &exp_in_out;
|
||||
|
||||
case Easers::ElasticIn: return &elastic_in;
|
||||
case Easers::ElasticOut: return &elastic_out;
|
||||
case Easers::ElasticInOut: return &elastic_in_out;
|
||||
|
||||
case Easers::BackIn: return &back_in;
|
||||
case Easers::BackOut: return &back_out;
|
||||
case Easers::BackInOut: return &back_in_out;
|
||||
|
||||
case Easers::BounceIn: return &bounce_in;
|
||||
case Easers::BounceOut: return &bounce_out;
|
||||
case Easers::BounceInOut: return &bounce_in_out;
|
||||
case Easers::_Count:
|
||||
break;
|
||||
}
|
||||
|
||||
BLAH_ERROR("Invalid Easer Type");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline const char* name(Easers e)
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case Easers::CubeIn: return "CubeIn";
|
||||
case Easers::CubeOut: return "CubeOut";
|
||||
case Easers::CubeInOut: return "CubeInOut";
|
||||
case Easers::QuadIn: return "QuadIn";
|
||||
case Easers::QuadOut: return "QuadOut";
|
||||
case Easers::QuadInOut: return "QuadInOut";
|
||||
case Easers::QuartIn: return "QuartIn";
|
||||
case Easers::QuartOut: return "QuartOut";
|
||||
case Easers::QuartInOut: return "QuartInOut";
|
||||
case Easers::QuintIn: return "QuintIn";
|
||||
case Easers::QuintOut: return "QuintOut";
|
||||
case Easers::QuintInOut: return "QuintInOut";
|
||||
case Easers::SineIn: return "SineIn";
|
||||
case Easers::SineOut: return "SineOut";
|
||||
case Easers::SineInOut: return "SineInOut";
|
||||
case Easers::CircIn: return "CircIn";
|
||||
case Easers::CircOut: return "CircOut";
|
||||
case Easers::CircInOut: return "CircInOut";
|
||||
case Easers::ExpIn: return "ExpIn";
|
||||
case Easers::ExpOut: return "ExpOut";
|
||||
case Easers::ExpInOut: return "ExpInOut";
|
||||
case Easers::ElasticIn: return "ElasticIn";
|
||||
case Easers::ElasticOut: return "ElasticOut";
|
||||
case Easers::ElasticInOut: return "ElasticInOut";
|
||||
case Easers::BackIn: return "BackIn";
|
||||
case Easers::BackOut: return "BackOut";
|
||||
case Easers::BackInOut: return "BackInOut";
|
||||
case Easers::BounceIn: return "BounceIn";
|
||||
case Easers::BounceOut: return "BounceOut";
|
||||
case Easers::BounceInOut: return "BounceInOut";
|
||||
case Easers::_Count:
|
||||
break;
|
||||
}
|
||||
|
||||
return "<Invalid>";
|
||||
}
|
||||
}
|
||||
}
|
30
include/blah/math/line.h
Normal file
30
include/blah/math/line.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include <blah/math/vec2.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
struct Rect;
|
||||
|
||||
struct Line
|
||||
{
|
||||
Vec2 a;
|
||||
Vec2 b;
|
||||
|
||||
Line() {}
|
||||
Line(float x0, float y0, float x1, float y1);
|
||||
Line(const Vec2& start, const Vec2& end);
|
||||
|
||||
Rect bounds() const;
|
||||
|
||||
Vec2 closest_point(const Vec2& pt) const;
|
||||
bool intersects(const Rect& rect) const;
|
||||
bool intersects(const Rect& rect, Vec2* out_intersection_point) const;
|
||||
bool intersects(const Line& line) const;
|
||||
bool intersects(const Line& line, Vec2* out_intersection_point) const;
|
||||
|
||||
void project(const Vec2& axis, float* min, float* max) const;
|
||||
|
||||
Line operator +(const Vec2& rhs) const;
|
||||
Line operator -(const Vec2& rhs) const;
|
||||
};
|
||||
}
|
47
include/blah/math/mat3x2.h
Normal file
47
include/blah/math/mat3x2.h
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
struct Vec2;
|
||||
|
||||
struct Mat3x2
|
||||
{
|
||||
float m11;
|
||||
float m12;
|
||||
float m21;
|
||||
float m22;
|
||||
float m31;
|
||||
float m32;
|
||||
|
||||
Mat3x2();
|
||||
Mat3x2(float m11, float m12, float m21, float m22, float m31, float m32);
|
||||
|
||||
Mat3x2 invert() const;
|
||||
float scaling_factor() const;
|
||||
|
||||
Mat3x2 operator *(const Mat3x2& rhs) const;
|
||||
Mat3x2 operator +(const Mat3x2& rhs) const;
|
||||
Mat3x2 operator -(const Mat3x2& rhs) const;
|
||||
Mat3x2& operator *=(const Mat3x2& rhs);
|
||||
bool operator==(const Mat3x2& rhs);
|
||||
bool operator!=(const Mat3x2& rhs);
|
||||
|
||||
static const Mat3x2 identity;
|
||||
|
||||
static Mat3x2 create_translation(const Vec2& position);
|
||||
static Mat3x2 create_translation(float x, float y);
|
||||
static Mat3x2 create_scale(float scale);
|
||||
static Mat3x2 create_scale(Vec2 scale);
|
||||
static Mat3x2 create_scale(float x, float y);
|
||||
static Mat3x2 create_scale(float scale, Vec2 centerPoint);
|
||||
static Mat3x2 create_scale(Vec2 scale, Vec2 centerPoint);
|
||||
static Mat3x2 create_scale(float scaleX, float scaleY, Vec2 centerPoint);
|
||||
static Mat3x2 create_rotation(float radians);
|
||||
static Mat3x2 create_transform(const Vec2& position, const Vec2& origin, const Vec2& scale, float rotation);
|
||||
|
||||
static Mat3x2 add(const Mat3x2& a, const Mat3x2& b);
|
||||
static Mat3x2 subtract(const Mat3x2& a, const Mat3x2& b);
|
||||
static Mat3x2 multiply(const Mat3x2& a, const Mat3x2& b);
|
||||
|
||||
};
|
||||
}
|
44
include/blah/math/mat4x4.h
Normal file
44
include/blah/math/mat4x4.h
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
struct 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;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
static const Mat4x4 identity;
|
||||
|
||||
static Mat4x4 create_ortho(float width, float height, float z_near_plane, float z_far_plane);
|
||||
static Mat4x4 create_ortho_offcenter(float left, float right, float bottom, float top, float z_near_plane, float z_far_plane);
|
||||
static Mat4x4 create_translation(float x, float y, float z);
|
||||
static Mat4x4 create_scale(float x, float y, float z);
|
||||
|
||||
Mat4x4 operator* (const Mat4x4& rhs);
|
||||
};
|
||||
}
|
41
include/blah/math/point.h
Normal file
41
include/blah/math/point.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
struct Point
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
|
||||
Point();
|
||||
Point(int px, int py);
|
||||
|
||||
Point operator +(const Point rhs) const;
|
||||
Point operator -(const Point rhs) const;
|
||||
Point operator /(const int rhs) const;
|
||||
Point operator *(const int rhs) const;
|
||||
Point operator -() const;
|
||||
|
||||
Point& operator +=(const Point& rhs);
|
||||
Point& operator -=(const Point& rhs);
|
||||
Point& operator /=(const Point& rhs);
|
||||
Point& operator *=(const Point& rhs);
|
||||
Point& operator /=(int rhs);
|
||||
Point& operator *=(int rhs);
|
||||
|
||||
bool operator ==(const Point& rhs);
|
||||
bool operator !=(const Point& rhs);
|
||||
|
||||
float length() const;
|
||||
int length_squared() const;
|
||||
|
||||
static const Point unitX;
|
||||
static const Point unitY;
|
||||
static const Point right;
|
||||
static const Point up;
|
||||
static const Point down;
|
||||
static const Point left;
|
||||
static const Point zero;
|
||||
static const Point one;
|
||||
};
|
||||
}
|
19
include/blah/math/quad.h
Normal file
19
include/blah/math/quad.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <blah/math/vec2.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
struct Quad
|
||||
{
|
||||
Vec2 a;
|
||||
Vec2 b;
|
||||
Vec2 c;
|
||||
Vec2 d;
|
||||
|
||||
Quad() {}
|
||||
Quad(const Vec2& a, const Vec2& b, const Vec2& c, const Vec2& d)
|
||||
: a(a), b(b), c(c), d(d) {}
|
||||
|
||||
void project(const Vec2& axis, float* min, float* max) const;
|
||||
};
|
||||
}
|
87
include/blah/math/rect.h
Normal file
87
include/blah/math/rect.h
Normal file
@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
#include <blah/math/point.h>
|
||||
#include <blah/math/vec2.h>
|
||||
#include <blah/math/rectI.h>
|
||||
#include <blah/math/line.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
struct Mat3x2;
|
||||
|
||||
struct Rect
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float w;
|
||||
float h;
|
||||
|
||||
Rect();
|
||||
Rect(float rx, float ry, float rw, float rh);
|
||||
Rect(Vec2 pos, Vec2 size);
|
||||
Rect(RectI r);
|
||||
|
||||
Rect scale(float s);
|
||||
Rect scale(float sx, float sy);
|
||||
|
||||
float left() const;
|
||||
float right() const;
|
||||
float top() const;
|
||||
float bottom() const;
|
||||
|
||||
Vec2 center() const;
|
||||
float center_x() const;
|
||||
float center_y() const;
|
||||
|
||||
Vec2 top_left() const;
|
||||
Vec2 top_right() const;
|
||||
Vec2 bottom_right() const;
|
||||
Vec2 bottom_left() const;
|
||||
|
||||
Vec2 center_left() const;
|
||||
Vec2 center_right() const;
|
||||
Vec2 middle_top() const;
|
||||
Vec2 middle_bottom() const;
|
||||
|
||||
Line left_line() const;
|
||||
Line right_line() const;
|
||||
Line top_line() const;
|
||||
Line bottom_line() const;
|
||||
|
||||
bool contains(const Point& pt) const;
|
||||
bool contains(const Vec2& pt) const;
|
||||
|
||||
bool overlaps(const Rect& rect) const;
|
||||
Rect overlap_rect(const Rect& other) const;
|
||||
|
||||
bool intersects(const Line& line) const;
|
||||
bool intersects(const Line& line, Vec2* out_intersection_point) const;
|
||||
bool intersects(const Vec2& line_from, const Vec2& line_to) const;
|
||||
bool intersects(const Vec2& line_from, const Vec2& line_to, Vec2* out_intersection_point) const;
|
||||
|
||||
Vec2 intersection_point(const Line& line) const;
|
||||
Vec2 intersection_point(const Vec2& line_from, const Vec2& line_to) const;
|
||||
|
||||
Rect inflate(float amount) const;
|
||||
|
||||
/*
|
||||
Rect Sectors:
|
||||
0101 0100 0110
|
||||
0001 0000 0010
|
||||
1001 1000 1010
|
||||
0000 = inside rectangle, all others refer to sectors relative to the rectangle
|
||||
*/
|
||||
char get_sector(const Vec2& pt) const;
|
||||
|
||||
bool operator==(const Rect& rhs) const { return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h; }
|
||||
bool operator!=(const Rect& rhs) const { return !(*this == rhs); }
|
||||
|
||||
Rect operator+(const Vec2& rhs) const;
|
||||
Rect operator-(const Vec2& rhs) const;
|
||||
Rect& operator+=(const Vec2& rhs);
|
||||
Rect& operator-=(const Vec2& rhs);
|
||||
|
||||
static Rect transform(const Rect& vec, const Mat3x2& matrix);
|
||||
static Rect transform(float x, float y, float w, float h, const Mat3x2& matrix);
|
||||
static Rect from_points(Vec2& from, Vec2& to);
|
||||
};
|
||||
}
|
64
include/blah/math/rectI.h
Normal file
64
include/blah/math/rectI.h
Normal file
@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
struct Point;
|
||||
struct Rect;
|
||||
struct Vec2;
|
||||
|
||||
struct RectI
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
RectI();
|
||||
RectI(int rx, int ry, int rw, int rh);
|
||||
RectI(Point pos, Point size);
|
||||
|
||||
int left() const { return x; }
|
||||
int right() const { return x + w; }
|
||||
int top() const { return y; }
|
||||
int bottom() const { return y + h; }
|
||||
int centerX() const { return x + w / 2; }
|
||||
int centerY() const { return y + h / 2; }
|
||||
|
||||
Point center() const;
|
||||
Point top_left() const;
|
||||
Point top_right() const;
|
||||
Point bottom_left() const;
|
||||
Point bottom_right() const;
|
||||
|
||||
bool overlaps(const RectI& other) const
|
||||
{
|
||||
return x < other.x + other.w
|
||||
&& other.x < x + w
|
||||
&& y < other.y + other.h
|
||||
&& other.y < y + h;
|
||||
}
|
||||
|
||||
bool contains(const Point& pt) const;
|
||||
bool contains(const Vec2& pt) const;
|
||||
|
||||
/*
|
||||
Rect Sectors:
|
||||
0101 0100 0110
|
||||
0001 0000 0010
|
||||
1001 1000 1010
|
||||
0000 = inside rectangle, all others refer to sectors relative to the rectangle
|
||||
*/
|
||||
char get_sector(const Point& pt) const;
|
||||
char get_sector(const Vec2& pt) const;
|
||||
|
||||
bool operator==(const RectI& rhs) const { return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h; }
|
||||
bool operator!=(const RectI& rhs) const { return !(*this == rhs); }
|
||||
|
||||
RectI operator+(const Point& rhs) const;
|
||||
RectI operator-(const Point& rhs) const;
|
||||
RectI& operator+=(const Point& rhs);
|
||||
RectI& operator-=(const Point& rhs);
|
||||
|
||||
RectI operator*(const int& rhs) const { return RectI(x * rhs, y * rhs, w * rhs, h * rhs); }
|
||||
};
|
||||
}
|
16
include/blah/math/stopwatch.h
Normal file
16
include/blah/math/stopwatch.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
class Stopwatch
|
||||
{
|
||||
public:
|
||||
Stopwatch();
|
||||
void reset();
|
||||
uint64_t microseconds();
|
||||
uint64_t milliseconds();
|
||||
private:
|
||||
uint64_t start_time;
|
||||
};
|
||||
}
|
72
include/blah/math/vec2.h
Normal file
72
include/blah/math/vec2.h
Normal file
@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#include <blah/math/point.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
|
||||
struct Mat3x2;
|
||||
|
||||
struct Vec2
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
|
||||
Vec2();
|
||||
Vec2(float vx, float vy);
|
||||
Vec2(int vx, float vy);
|
||||
Vec2(float vx, int vy);
|
||||
Vec2(int vx, int vy);
|
||||
Vec2(Point p);
|
||||
|
||||
Vec2 operator +(const Vec2 rhs) const;
|
||||
Vec2 operator -(const Vec2 rhs) const;
|
||||
Vec2 operator /(const float rhs) const;
|
||||
Vec2 operator *(const float rhs) const;
|
||||
Vec2 operator -() const;
|
||||
|
||||
Vec2& operator +=(const Vec2& rhs);
|
||||
Vec2& operator -=(const Vec2& rhs);
|
||||
Vec2& operator /=(const Vec2& rhs);
|
||||
Vec2& operator *=(const Vec2& rhs);
|
||||
Vec2& operator /=(float rhs);
|
||||
Vec2& operator *=(float rhs);
|
||||
|
||||
bool operator ==(const Vec2& rhs);
|
||||
bool operator !=(const Vec2& rhs);
|
||||
|
||||
Vec2 normal() const;
|
||||
Vec2 turn_right() const;
|
||||
Vec2 turn_left() const;
|
||||
float length() const;
|
||||
float length_squared() const;
|
||||
Vec2 perpendicular() const;
|
||||
float angle() const;
|
||||
|
||||
static float dot(Vec2 a, Vec2 b);
|
||||
static float dot(float x, float y, Vec2 b);
|
||||
static float dot(float x1, float y1, float x2, float y2);
|
||||
|
||||
static Vec2 transform(const Vec2& vec, const Mat3x2& matrix);
|
||||
static Vec2 transform(float x, float y, const Mat3x2& matrix);
|
||||
static Vec2 from_angle(float radians, float length);
|
||||
static Vec2 from_angle(float radians);
|
||||
static Vec2 lerp(Vec2 start, Vec2 end, float t);
|
||||
static Vec2 bezier_lerp(Vec2 start, Vec2 b, Vec2 end, float t);
|
||||
static Vec2 bezier_lerp(Vec2 start, Vec2 b, Vec2 c, Vec2 end, float t);
|
||||
static Vec2 reflect(const Vec2& vector, const Vec2& normal);
|
||||
|
||||
static const Vec2 unit_x;
|
||||
static const Vec2 unit_y;
|
||||
static const Vec2 right;
|
||||
static const Vec2 up;
|
||||
static const Vec2 down;
|
||||
static const Vec2 left;
|
||||
static const Vec2 zero;
|
||||
static const Vec2 one;
|
||||
static const Vec2 up_right;
|
||||
static const Vec2 up_left;
|
||||
static const Vec2 down_right;
|
||||
static const Vec2 down_left;
|
||||
};
|
||||
|
||||
}
|
15
include/blah/math/vec4.h
Normal file
15
include/blah/math/vec4.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
struct Vec4
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
|
||||
Vec4() : x(0), y(0), z(0), w(0) {}
|
||||
Vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
|
||||
};
|
||||
}
|
37
include/blah/streams/bufferstream.h
Normal file
37
include/blah/streams/bufferstream.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
#include <blah/streams/stream.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
class BufferStream : public Stream
|
||||
{
|
||||
public:
|
||||
BufferStream();
|
||||
BufferStream(int capacity);
|
||||
BufferStream(BufferStream&& bs) noexcept;
|
||||
BufferStream& operator=(BufferStream&& bs) noexcept;
|
||||
~BufferStream();
|
||||
|
||||
virtual int64_t length() const override { return m_length; }
|
||||
virtual int64_t position() const override { return m_position; }
|
||||
virtual int64_t seek(int64_t seekTo) override { return m_position = (seekTo < 0 ? 0 : (seekTo > m_length ? m_length : seekTo)); }
|
||||
virtual bool is_open() const override { return m_buffer != nullptr; }
|
||||
virtual bool is_readable() const override { return true; }
|
||||
virtual bool is_writable() const override { return true; }
|
||||
virtual void close() override;
|
||||
void clear() { m_length = m_position = 0; }
|
||||
|
||||
char* data() { return m_buffer; }
|
||||
const char* data() const { return m_buffer; }
|
||||
|
||||
protected:
|
||||
virtual int64_t read_into(void* ptr, int64_t length) override;
|
||||
virtual int64_t write_from(const void* ptr, int64_t length) override;
|
||||
|
||||
private:
|
||||
char* m_buffer;
|
||||
int64_t m_capacity;
|
||||
int64_t m_length;
|
||||
int64_t m_position;
|
||||
};
|
||||
}
|
39
include/blah/streams/endian.h
Normal file
39
include/blah/streams/endian.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
enum class Endian
|
||||
{
|
||||
Little,
|
||||
Big
|
||||
};
|
||||
|
||||
template<class T>
|
||||
inline void swap_endian(T* value)
|
||||
{
|
||||
for (int i = 0; i < sizeof(T) / 2; i++)
|
||||
{
|
||||
char* _ptr = (char*)&value;
|
||||
char _temp = *(_ptr + i);
|
||||
*(_ptr + i) = *(_ptr + sizeof(T) - i - 1);
|
||||
*(_ptr + sizeof(T) - i - 1) = _temp;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool is_big_endian()
|
||||
{
|
||||
return (*((short*)"AB") == 0x4243);
|
||||
}
|
||||
|
||||
inline bool is_little_endian()
|
||||
{
|
||||
return (*((short*)"AB") != 0x4243);
|
||||
}
|
||||
|
||||
inline bool is_endian(const Endian& endian)
|
||||
{
|
||||
return
|
||||
(endian == Endian::Little && is_little_endian()) ||
|
||||
(endian == Endian::Big && is_big_endian());
|
||||
}
|
||||
}
|
32
include/blah/streams/filestream.h
Normal file
32
include/blah/streams/filestream.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include <blah/streams/stream.h>
|
||||
#include <blah/core/filesystem.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
class FileStream : public Stream
|
||||
{
|
||||
public:
|
||||
FileStream();
|
||||
FileStream(const char* path, FileMode mode = FileMode::ReadWrite);
|
||||
FileStream(FileStream&& fs) noexcept;
|
||||
FileStream& operator=(FileStream&& fs) noexcept;
|
||||
~FileStream();
|
||||
|
||||
virtual int64_t length() const override;
|
||||
virtual int64_t position() const override;
|
||||
virtual int64_t seek(int64_t seekTo) override;
|
||||
virtual bool is_open() const override { return m_handle != nullptr; }
|
||||
virtual bool is_readable() const override { return m_handle != nullptr && (m_mode == FileMode::ReadWrite || m_mode == FileMode::Read); }
|
||||
virtual bool is_writable() const override { return m_handle != nullptr && (m_mode == FileMode::ReadWrite || m_mode == FileMode::Write); }
|
||||
virtual void close() override;
|
||||
|
||||
protected:
|
||||
virtual int64_t read_into(void* ptr, int64_t length) override;
|
||||
virtual int64_t write_from(const void* ptr, int64_t length) override;
|
||||
|
||||
private:
|
||||
FileMode m_mode;
|
||||
void* m_handle;
|
||||
};
|
||||
}
|
35
include/blah/streams/memorystream.h
Normal file
35
include/blah/streams/memorystream.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include <blah/streams/stream.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
class MemoryStream : public Stream
|
||||
{
|
||||
public:
|
||||
MemoryStream();
|
||||
MemoryStream(char* data, int64_t length);
|
||||
MemoryStream(MemoryStream&& ms) noexcept;
|
||||
MemoryStream& operator=(MemoryStream&& ms) noexcept;
|
||||
~MemoryStream() { m_data = nullptr; m_length = m_position = 0; }
|
||||
|
||||
virtual int64_t length() const override { return m_length; }
|
||||
virtual int64_t position() const override { return m_position; }
|
||||
virtual int64_t seek(int64_t seekTo) override { return m_position = (seekTo < 0 ? 0 : (seekTo > m_length ? m_length : seekTo)); }
|
||||
virtual bool is_open() const override { return m_data != nullptr; }
|
||||
virtual bool is_readable() const override { return true; }
|
||||
virtual bool is_writable() const override { return true; }
|
||||
virtual void close() override { m_data = nullptr; m_length = m_position = 0; }
|
||||
|
||||
char* data() { return m_data; }
|
||||
const char* data() const { return m_data; }
|
||||
|
||||
protected:
|
||||
virtual int64_t read_into(void* ptr, int64_t length) override;
|
||||
virtual int64_t write_from(const void* ptr, int64_t length) override;
|
||||
|
||||
private:
|
||||
char* m_data;
|
||||
int64_t m_length;
|
||||
int64_t m_position;
|
||||
};
|
||||
}
|
141
include/blah/streams/stream.h
Normal file
141
include/blah/streams/stream.h
Normal file
@ -0,0 +1,141 @@
|
||||
#pragma once
|
||||
#include <inttypes.h>
|
||||
#include <blah/containers/str.h>
|
||||
#include <blah/streams/endian.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
class Stream
|
||||
{
|
||||
public:
|
||||
Stream() = default;
|
||||
Stream(const Stream&) = delete;
|
||||
Stream& operator=(const Stream&) = delete;
|
||||
|
||||
virtual ~Stream() = default;
|
||||
|
||||
// returns the length of the stream
|
||||
virtual int64_t length() const = 0;
|
||||
|
||||
// returns the position of the stream
|
||||
virtual int64_t position() const = 0;
|
||||
|
||||
// seeks the position of the stream
|
||||
virtual int64_t seek(int64_t seek_to) = 0;
|
||||
|
||||
// returns true of the stream is open
|
||||
virtual bool is_open() const = 0;
|
||||
|
||||
// returns true of the stream is readable
|
||||
virtual bool is_readable() const = 0;
|
||||
|
||||
// returns true of the stream is writable
|
||||
virtual bool is_writable() const = 0;
|
||||
|
||||
// closes the stream
|
||||
virtual void close() = 0;
|
||||
|
||||
// pipes the contents of this tream to another stream
|
||||
int64_t pipe(Stream& to, int64_t length);
|
||||
|
||||
// reads the amount of bytes into the given buffer, and returns the amount read
|
||||
int64_t read(void* buffer, int64_t length) { return read_into(buffer, length); }
|
||||
|
||||
// reads a string. if length < 0, assumes null-terminated
|
||||
String read_string(int length = -1)
|
||||
{
|
||||
String result;
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
char next;
|
||||
while (read(&next, 1) && next != '\0')
|
||||
result.append(next);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.set_length(length);
|
||||
read_into(result.cstr(), length);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String read_line()
|
||||
{
|
||||
String result;
|
||||
|
||||
char next;
|
||||
while (read(&next, 1) && next != '\n' && next != '\0')
|
||||
result.append(next);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// reads a number
|
||||
template<class T>
|
||||
T read()
|
||||
{
|
||||
return read<T>(Endian::Little);
|
||||
}
|
||||
|
||||
// reads a number
|
||||
template<class T>
|
||||
T read(Endian endian)
|
||||
{
|
||||
T result;
|
||||
read(&result, sizeof(T));
|
||||
if (!Blah::is_endian(endian))
|
||||
Blah::swap_endian(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// writes the amount of bytes to the stream from the given buffer, and returns the amount written
|
||||
int64_t write(const void* buffer, int64_t length)
|
||||
{
|
||||
return write_from(buffer, length);
|
||||
}
|
||||
|
||||
// writes a null-terminated string, and returns the amount written
|
||||
int64_t write_cstr(const Str& string)
|
||||
{
|
||||
return write(string.cstr(), string.length() + 1);
|
||||
}
|
||||
|
||||
// writes a null-terminated string, and returns the amount written
|
||||
int64_t write_cstr(const char* cstr)
|
||||
{
|
||||
return write(cstr, strlen(cstr) + 1);
|
||||
}
|
||||
|
||||
// writes a number
|
||||
template<class T>
|
||||
int64_t write(const T& value)
|
||||
{
|
||||
return write<T>(value, Endian::Little);
|
||||
}
|
||||
|
||||
// writes a number
|
||||
template<class T>
|
||||
int64_t write(const T& value, Endian endian)
|
||||
{
|
||||
T writing = value;
|
||||
|
||||
if (!Blah::is_endian(endian))
|
||||
Blah::swap_endian(&writing);
|
||||
|
||||
return write(&writing, sizeof(T));
|
||||
}
|
||||
|
||||
protected:
|
||||
// reads from the stream into the given buffer, and returns the number of bytes read
|
||||
virtual int64_t read_into(void* buffer, int64_t length) = 0;
|
||||
|
||||
// writes from the stream from the given buffer, and returns the number of bytes written
|
||||
virtual int64_t write_from(const void* buffer, int64_t length) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#undef BLAH_SWAP_ENDIAN
|
||||
#undef BLAH_BIG_ENDIAN
|
Reference in New Issue
Block a user