2018-09-26 17:39:17 +00:00
|
|
|
#include <stdarg.h>
|
2019-06-02 07:20:10 +00:00
|
|
|
#include <stddef.h>
|
2020-05-19 19:49:40 +00:00
|
|
|
#include <stdint.h>
|
2016-09-30 06:18:51 +00:00
|
|
|
|
2017-01-26 10:20:30 +00:00
|
|
|
#pragma once
|
2016-10-04 22:05:34 +00:00
|
|
|
|
2019-05-20 09:47:33 +00:00
|
|
|
#define LOVR_VERSION_MAJOR 0
|
2021-04-11 14:57:11 +00:00
|
|
|
#define LOVR_VERSION_MINOR 15
|
2019-05-20 09:47:33 +00:00
|
|
|
#define LOVR_VERSION_PATCH 0
|
2021-04-11 14:57:11 +00:00
|
|
|
#define LOVR_VERSION_ALIAS "Government Goop"
|
2019-05-20 09:47:33 +00:00
|
|
|
|
2021-03-08 05:03:35 +00:00
|
|
|
#ifdef _MSC_VER
|
2020-10-26 08:24:44 +00:00
|
|
|
#define LOVR_THREAD_LOCAL __declspec(thread)
|
2019-01-04 10:18:21 +00:00
|
|
|
#else
|
2019-05-20 11:05:39 +00:00
|
|
|
#define LOVR_THREAD_LOCAL __thread
|
2019-01-18 16:44:03 +00:00
|
|
|
#endif
|
2018-12-13 03:35:18 +00:00
|
|
|
|
2019-06-21 04:43:40 +00:00
|
|
|
#ifndef M_PI
|
|
|
|
#define M_PI 3.14159265358979
|
|
|
|
#endif
|
|
|
|
|
2018-09-27 18:45:43 +00:00
|
|
|
#define MAX(a, b) (a > b ? a : b)
|
|
|
|
#define MIN(a, b) (a < b ? a : b)
|
|
|
|
#define CLAMP(x, min, max) MAX(min, MIN(max, x))
|
2020-10-26 08:03:19 +00:00
|
|
|
#define ALIGN(p, n) (((uintptr_t) (p) + (n - 1)) & ~(n - 1))
|
2022-03-22 00:00:30 +00:00
|
|
|
#define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
|
2019-05-20 11:15:24 +00:00
|
|
|
#define CHECK_SIZEOF(T) int(*_o)[sizeof(T)]=1
|
2018-11-25 02:04:27 +00:00
|
|
|
|
2019-04-05 12:08:03 +00:00
|
|
|
typedef struct Color { float r, g, b, a; } Color;
|
2017-08-02 08:25:56 +00:00
|
|
|
|
lovr.log;
lovr.log is a new callback that is invoked whenever LÖVR wants to
send the project a message. For example, this could be a performance
warning from the graphics module, an error message from one of the
headset backends, or an API deprecation notice.
The callback's signature is (message, level, tag). The message is a
string containing the message to log, level is a string that is currently
one of "debug", "info", "warn", "error", and tag is an optional string
that is used to indicate the source of the message for grouping purposes.
The default implementation of the callback just prints the message,
but the callback can be overridden to do things like filter messages,
write them to a file, or even render them in VR. Projects can also
invoke the callback directly to log their own messages.
2020-07-06 22:20:55 +00:00
|
|
|
// Error handling
|
2019-06-02 07:20:10 +00:00
|
|
|
typedef void errorFn(void*, const char*, va_list);
|
lovr.log;
lovr.log is a new callback that is invoked whenever LÖVR wants to
send the project a message. For example, this could be a performance
warning from the graphics module, an error message from one of the
headset backends, or an API deprecation notice.
The callback's signature is (message, level, tag). The message is a
string containing the message to log, level is a string that is currently
one of "debug", "info", "warn", "error", and tag is an optional string
that is used to indicate the source of the message for grouping purposes.
The default implementation of the callback just prints the message,
but the callback can be overridden to do things like filter messages,
write them to a file, or even render them in VR. Projects can also
invoke the callback directly to log their own messages.
2020-07-06 22:20:55 +00:00
|
|
|
void lovrSetErrorCallback(errorFn* callback, void* userdata);
|
2022-03-25 19:10:45 +00:00
|
|
|
_Noreturn void lovrThrow(const char* format, ...);
|
2019-04-05 09:50:11 +00:00
|
|
|
#define lovrAssert(c, ...) if (!(c)) { lovrThrow(__VA_ARGS__); }
|
2020-05-19 19:49:40 +00:00
|
|
|
|
2021-06-05 17:12:00 +00:00
|
|
|
#ifdef LOVR_UNCHECKED
|
|
|
|
#define lovrCheck(c, ...) ((void) 0)
|
|
|
|
#else
|
|
|
|
#define lovrCheck lovrAssert
|
|
|
|
#endif
|
|
|
|
|
lovr.log;
lovr.log is a new callback that is invoked whenever LÖVR wants to
send the project a message. For example, this could be a performance
warning from the graphics module, an error message from one of the
headset backends, or an API deprecation notice.
The callback's signature is (message, level, tag). The message is a
string containing the message to log, level is a string that is currently
one of "debug", "info", "warn", "error", and tag is an optional string
that is used to indicate the source of the message for grouping purposes.
The default implementation of the callback just prints the message,
but the callback can be overridden to do things like filter messages,
write them to a file, or even render them in VR. Projects can also
invoke the callback directly to log their own messages.
2020-07-06 22:20:55 +00:00
|
|
|
// Logging
|
|
|
|
typedef void logFn(void*, int, const char*, const char*, va_list);
|
|
|
|
enum { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR };
|
|
|
|
void lovrSetLogCallback(logFn* callback, void* userdata);
|
|
|
|
void lovrLog(int level, const char* tag, const char* format, ...);
|
|
|
|
|
|
|
|
// Hash function (FNV1a)
|
2020-12-25 19:29:22 +00:00
|
|
|
static inline uint64_t hash64(const void* data, size_t length) {
|
2020-05-19 19:49:40 +00:00
|
|
|
const uint8_t* bytes = (const uint8_t*) data;
|
|
|
|
uint64_t hash = 0xcbf29ce484222325;
|
|
|
|
for (size_t i = 0; i < length; i++) {
|
|
|
|
hash = (hash ^ bytes[i]) * 0x100000001b3;
|
|
|
|
}
|
|
|
|
return hash;
|
|
|
|
}
|
2021-02-09 00:23:18 +00:00
|
|
|
|
|
|
|
// Refcounting
|
2021-02-11 23:37:55 +00:00
|
|
|
void lovrRetain(void* ref);
|
|
|
|
void lovrRelease(void* ref, void (*destructor)(void*));
|
2021-02-09 01:25:05 +00:00
|
|
|
|
|
|
|
// Dynamic Array
|
|
|
|
typedef void* arr_allocator(void* data, size_t size);
|
|
|
|
#define arr_t(T) struct { T* data; arr_allocator* alloc; size_t length, capacity; }
|
|
|
|
#define arr_init(a, allocator) (a)->data = NULL, (a)->length = 0, (a)->capacity = 0, (a)->alloc = allocator
|
2021-02-09 15:15:43 +00:00
|
|
|
#define arr_free(a) if ((a)->data) (a)->alloc((a)->data, 0)
|
2021-02-09 01:25:05 +00:00
|
|
|
#define arr_reserve(a, n) _arr_reserve((void**) &((a)->data), n, &(a)->capacity, sizeof(*(a)->data), (a)->alloc)
|
|
|
|
#define arr_expand(a, n) arr_reserve(a, (a)->length + n)
|
|
|
|
#define arr_push(a, x) arr_reserve(a, (a)->length + 1), (a)->data[(a)->length++] = x
|
|
|
|
#define arr_pop(a) (a)->data[--(a)->length]
|
|
|
|
#define arr_append(a, p, n) arr_reserve(a, (a)->length + n), memcpy((a)->data + (a)->length, p, n * sizeof(*(p))), (a)->length += n
|
2021-02-12 15:16:36 +00:00
|
|
|
#define arr_splice(a, i, n) memmove((a)->data + (i), (a)->data + ((i) + n), ((a)->length - (i) - (n)) * sizeof(*(a)->data)), (a)->length -= n
|
2021-02-09 01:25:05 +00:00
|
|
|
#define arr_clear(a) (a)->length = 0
|
|
|
|
|
2022-03-14 19:27:58 +00:00
|
|
|
void* arr_alloc(void* data, size_t size);
|
|
|
|
|
2021-02-09 01:25:05 +00:00
|
|
|
static inline void _arr_reserve(void** data, size_t n, size_t* capacity, size_t stride, arr_allocator* allocator) {
|
|
|
|
if (*capacity >= n) return;
|
|
|
|
if (*capacity == 0) *capacity = 1;
|
|
|
|
while (*capacity < n) *capacity *= 2;
|
|
|
|
*data = allocator(*data, *capacity * stride);
|
|
|
|
lovrAssert(*data, "Out of memory");
|
|
|
|
}
|
2021-02-09 03:55:51 +00:00
|
|
|
|
|
|
|
// UTF-8
|
|
|
|
size_t utf8_decode(const char *s, const char *e, unsigned *pch);
|
|
|
|
void utf8_encode(uint32_t codepoint, char str[4]);
|