Cleaned slate.

This commit is contained in:
2022-10-18 10:00:31 -07:00
parent 94914e2ebc
commit a9462a42cc
288 changed files with 1 additions and 132589 deletions

View File

@ -1,44 +0,0 @@
# Copyright (c) 2021 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Dawn Libraries
target_link_libraries(${PROJECT_NAME}
PUBLIC
${LIBS_PLATFORM}
glad
cglm
stb
)
target_include_directories(${PROJECT_NAME}
PRIVATE
${LIBS_PLATFORM}
)
# Source H files
target_include_directories(${PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)
# Add in each part of the engine.
add_subdirectory(display)
add_subdirectory(engine)
add_subdirectory(epoch)
add_subdirectory(file)
add_subdirectory(input)
add_subdirectory(locale)
add_subdirectory(physics)
add_subdirectory(poker)
add_subdirectory(save)
add_subdirectory(scene)
add_subdirectory(util)
# add_subdirectory(vn)
# Add client and game
if(TARGET_TYPE STREQUAL game)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/games/${TARGET_GAME})
add_subdirectory(client)
endif()

View File

@ -1,30 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#define ASSERT_TRUE(x) assert(x)
#define ASSERT_FALSE(x) ASSERT_TRUE((x) == false)
#define ASSERT_NOT_NULL(x) ASSERT_FALSE(x == NULL)
#define ASSERT_IF(x, y) (x ? y : false)
#define ASSERT_EQUAL(x, y) ASSERT_TRUE(x == y)
#define ASSERT_NOT_EQUAL(x, y) ASSERT_TRUE(x != y)
#define ASSERT_LESS_THAN(x, y) ASSERT_TRUE(x < y)
#define ASSERT_LESS_THAN_EQUAL_TO(x, y) ASSERT_TRUE(x <= y)
#define ASSERT_GREATER_THAN(x, y) ASSERT_TRUE(x > y)
#define ASSERT_GREATER_THAN_EQUAL_TO(x, y) ASSERT_TRUE(x >= y)
#define ASSERT_FLAG_OFF(flags, flag) ASSERT_FALSE(flags & flag)
#define ASSERT_FLAG_ON(flags, flag) ASSERT_TRUE(flags & flag)
#define ASSERT_STRING_EQUALS(a, b) ASSERT_EQUAL(strcmp(a, b), 0)

View File

@ -1,6 +0,0 @@
# Copyright (c) 2021 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
add_subdirectory(glfwclient)

View File

@ -1,16 +0,0 @@
# Copyright (c) 2021 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Libraries
target_link_libraries(${PROJECT_NAME}
PUBLIC
glfw
glad
)
target_sources(${PROJECT_NAME}
PRIVATE
glfwclient.c
)

View File

@ -1,158 +0,0 @@
// Copyright (c) 2021 Dominic Msters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "glfwclient.h"
static game_t *GAME_STATE;
static GLFWwindow *window = NULL;
int32_t main() {
double time, newTime;
game_t *game;
input_t *input;
float fDelta;
// Attempt to init GLFW
if(!glfwInit()) return 1;
// Setup window hints
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, false);
// Create Window
window = glfwCreateWindow(
WINDOW_WIDTH_DEFAULT, WINDOW_HEIGHT_DEFAULT, "", NULL, NULL
);
if(!window) {
glfwTerminate();
return 1;
}
// Load GLAD
glfwMakeContextCurrent(window);
glfwSwapInterval(0);
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
// Setup window listeners
glfwSetWindowSizeCallback(window, &glfwOnResize);
glfwSetKeyCallback(window, &glfwOnKey);
glfwSetErrorCallback(&glfwOnError);
glfwSetCursorPosCallback(window, &glfwOnCursor);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
// Prepare the game
game = malloc(sizeof(game_t));
ASSERT_NOT_NULL(game);
GAME_STATE = game;
input = &game->engine.input;
printf("Game is %zu bytes.\n", sizeof(game_t));
// Init the render resolution
renderSetResolution(&game->engine.render,
WINDOW_WIDTH_DEFAULT, WINDOW_HEIGHT_DEFAULT
);
// Init the game
if(gameInit(game)) {
// Bind initial keys
inputBind(input, INPUT_NULL, glfwGetInputSourceForKey(GLFW_KEY_ESCAPE));
inputBind(input, INPUT_UP, glfwGetInputSourceForKey(GLFW_KEY_UP));
inputBind(input, INPUT_DOWN, glfwGetInputSourceForKey(GLFW_KEY_DOWN));
inputBind(input, INPUT_LEFT, glfwGetInputSourceForKey(GLFW_KEY_LEFT));
inputBind(input, INPUT_RIGHT, glfwGetInputSourceForKey(GLFW_KEY_RIGHT));
inputBind(input, INPUT_UP, glfwGetInputSourceForKey(GLFW_KEY_W));
inputBind(input, INPUT_DOWN, glfwGetInputSourceForKey(GLFW_KEY_S));
inputBind(input, INPUT_LEFT, glfwGetInputSourceForKey(GLFW_KEY_A));
inputBind(input, INPUT_RIGHT, glfwGetInputSourceForKey(GLFW_KEY_D));
inputBind(input, INPUT_ACCEPT, glfwGetInputSourceForKey(GLFW_KEY_E));
inputBind(input, INPUT_ACCEPT, glfwGetInputSourceForKey(GLFW_KEY_ENTER));
inputBind(input, INPUT_ACCEPT, glfwGetInputSourceForKey(GLFW_KEY_SPACE));
// Bind the fake inputs
inputBind(input, INPUT_MOUSE_X, GLFW_PLATFORM_INPUT_MOUSE_X);
inputBind(input, INPUT_MOUSE_Y, GLFW_PLATFORM_INPUT_MOUSE_Y);
// Set up some GLFW stuff
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
glfwSetWindowTitle(window, game->engine.name);
// Begin time.
time = 0;
// Main Render Loop
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
// Determine the delta.
newTime = glfwGetTime();
fDelta = (float)(newTime - time);
time = newTime;
// Tick the engine.
if(!gameUpdate(game, fDelta)) break;
glfwSwapBuffers(window);
sleep(0);//Fixes some weird high CPU bug, not actually necessary.
}
// Game has finished running, cleanup.
gameDispose(game);
}
free(game);
// Terminate the GLFW context.
glfwSetWindowSizeCallback(window, NULL);
glfwTerminate();
return 0;
}
void glfwOnResize(GLFWwindow *window, int32_t width, int32_t height) {
ASSERT_NOT_NULL(window);
ASSERT_GREATER_THAN(width, 0);
ASSERT_GREATER_THAN(height, 0);
renderSetResolution(&GAME_STATE->engine.render, (float)width, (float)height);
}
void glfwOnKey(GLFWwindow *window,
int32_t key, int32_t scancode, int32_t action, int32_t mods
) {
input_t *input;
ASSERT_NOT_NULL(window);
input = &GAME_STATE->engine.input;
if(action == GLFW_PRESS) {
inputStateSet(input, glfwGetInputSourceForKey(key), 1.0f);
} else if(action == GLFW_RELEASE) {
inputStateSet(input, glfwGetInputSourceForKey(key), 0.0f);
}
}
void glfwOnError(int error, const char* description) {
fputs(description, stderr);
}
void glfwOnCursor(GLFWwindow *window, double x, double y) {
input_t *input;
ASSERT_NOT_NULL(window);
input = &GAME_STATE->engine.input;
inputStateSet(input, GLFW_PLATFORM_INPUT_MOUSE_X, (float)x);
inputStateSet(input, GLFW_PLATFORM_INPUT_MOUSE_Y, (float)y);
}
inputsource_t glfwGetInputSourceForKey(int32_t key) {
return (inputsource_t)((
key <= GLFW_KEY_GRAVE_ACCENT ? key - GLFW_KEY_SPACE :
key <= GLFW_KEY_MENU ? key - GLFW_KEY_ESCAPE + GLFW_KEY_GRAVE_ACCENT :
key
) % INPUT_SOURCE_COUNT);
}
void glfwClientSetTitle(char *name) {
ASSERT_NOT_NULL(window);
glfwSetWindowTitle(window, name);
}

View File

@ -1,59 +0,0 @@
// Copyright (c) 2021 Dominic Msters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <libs.h>
#include "display/render.h"
#include "assert/assert.h"
#include "input/input.h"
#include "game/game.h"
#define WINDOW_WIDTH_DEFAULT 1280
#define WINDOW_HEIGHT_DEFAULT WINDOW_WIDTH_DEFAULT/16*9
#define GLFW_PLATFORM_INPUT_MOUSE_X (inputsource_t)0xFF
#define GLFW_PLATFORM_INPUT_MOUSE_Y (inputsource_t)0xFE
/**
* Entry of the program
* @return 0 if success, anything else for failure.
*/
int32_t main();
/**
* Resize callbacks.
*
* @param window Window that was resized.
* @param width New window width.
* @param height New window height.
*/
void glfwOnResize(GLFWwindow *window, int32_t width, int32_t height);
/**
* Keyboard Input callbacks.
*
* @param window Window that was resized.
*/
void glfwOnKey(GLFWwindow *window,
int32_t key, int32_t scancode, int32_t action, int32_t mods
);
void glfwOnError(int error, const char* description);
void glfwOnCursor(GLFWwindow *window, double x, double y);
/**
* Get the game engine specific input source for a given GLFW Key code.
*
* @param key Key to get the input source for.
* @return The input source.
*/
inputsource_t glfwGetInputSourceForKey(int32_t key);
/** GLFW Client Methods */
void glfwClientSetTitle(char *name);

View File

@ -1,26 +0,0 @@
# Copyright (c) 2021 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${PROJECT_NAME}
PRIVATE
bitmapfont.c
camera.c
font.c
framebuffer.c
matrix.c
render.c
renderlist.c
shaderprogram.c
spritebatch.c
texture.c
tileset.c
)
# Subdirs
add_subdirectory(animation)
add_subdirectory(primitive)
add_subdirectory(shaders)
# add_subdirectory(ui)

View File

@ -1,13 +0,0 @@
# Copyright (c) 2021 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${PROJECT_NAME}
PRIVATE
animation.c
easing.c
queue.c
timeline.c
)

View File

@ -1,20 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "animation.h"
float animForwardAndBackward(float t) {
return (t < 0.5 ? t : 1 - t);
}
float animForwardAndBackwardScaled(float t) {
return animForwardAndBackward(t) * 2.0f;
}
float animTimeScaleFromFrameTime(int32_t frames, float time) {
return 1.0f / (float)frames / time;
}

View File

@ -1,38 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../../libs.h"
/**
* Animation tool for converting 0-1 space into a 0-0.5 back to zero space. This
* is intended to make a "Forward then backwards" effect for animation. This
* method will not scale t.
* @param t Time in space to back and fourth on between 0 and 1.
* @returns Forward and backwards time. 0 to 0.5 are as such, 0.5 to 1 are from
* 0.5 to 0.
*/
float animForwardAndBackward(float t);
/**
* Animation tool for converting 0-1 space into a 0-1-0 space. Scaled version of
* animForwardAndBackward().
* @param t Time in space to back and fourth on between 0 and 1.
* @returns Forward and backwards time.
*/
float animForwardAndBackwardScaled(float t);
/**
* Returns the time scale (speed to multiply time range by) for a given frame
* time and frame count. E.g. 3 frames at 0.5 time each would have a time scale
* of 1.5.
*
* @param frames Frames to get the scale of.
* @param time Time to get the scale of.
* @return The time scale.
*/
float animTimeScaleFromFrameTime(int32_t frames, float time);

View File

@ -1,60 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "easing.h"
float easeLinear(float t) {
return t;
}
float easeInQuad(float t) {
return t * t;
}
float easeOutQuad(float t) {
return t * (2 - t);
}
float easeInOutQuad(float t) {
return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
}
float easeInCubic(float t) {
return t * t * t;
}
float easeOutCubic(float t) {
return (t - 1) * (t - 1) * (t - 1) + 1;
}
float easeInOutCubic(float t) {
return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
}
float easeInQuart(float t) {
return t * t * t * t;
}
float easeOutQuart(float t) {
return 1 - (t-1)*(t-1)*(t-1)*(t-1);
}
float easeInOutQuart(float t) {
return t < .5 ? 8*t*t*t*t : 1-8*(t-1)*(t-1)*(t-1)*(t-1);
}
float easeInQuint(float t) {
return t*t*t*t*t;
}
float easeOutQuint(float t) {
return 1 + (t-1)*(t-1)*(t-1)*(t-1)*(t-1);
}
float easeInOutQuint(float t) {
return t<.5 ? 16*t*t*t*t*t : 1+16*(t-1)*(t-1)*(t-1)*(t-1)*(t-1);
}

View File

@ -1,32 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
typedef float easefunction_t(float t);
/**
* Returns the ease time for a given real time duration span.
* @param start At what point in time the animation started
* @param current The current point in time the animation is at.
* @param duration The total duration on the animation.
* @returns The easing time (0-1 time) that the animation is at.
*/
#define easeTimeToEase(start, current, duration) ((current-start)/duration)
float easeLinear(float t);
float easeInQuad(float t);
float easeOutQuad(float t);
float easeInOutQuad(float t);
float easeInCubic(float t);
float easeOutCubic(float t);
float easeInOutCubic(float t);
float easeInQuart(float t);
float easeOutQuart(float t);
float easeInOutQuart(float t);
float easeInQuint(float t);
float easeOutQuint(float t);
float easeInOutQuint(float t);

View File

@ -1,125 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "queue.h"
void queueInit(queue_t *queue) {
ASSERT_NOT_NULL(queue);
queue->timeline = 0;
queue->count = 0;
queue->current = ANIMATION_QUEUE_START;
}
queueaction_t * queueNext(queue_t *queue) {
queueaction_t *action;
ASSERT_NOT_NULL(queue);
// Is there a currently running action? If so, end it.
if(queue->current != ANIMATION_QUEUE_START) {
action = queue->items + queue->current;
if(action->onEnd != NULL) action->onEnd(queue, action, queue->current);
}
// Prepare to go to next action if there is a next action.
queue->current++;
queue->actionStarted = queue->timeline;
if(queue->current >= queue->count) return NULL;
// Go to next action, start it.
action = queue->items + queue->current;
if(action->onStart != NULL) action->onStart(queue, action, queue->current);
return action;
}
queueaction_t * queueAdd(queue_t *queue) {
queueaction_t *action;
ASSERT_NOT_NULL(queue);
ASSERT_LESS_THAN(queue->count, ANIMATION_QUEUE_ITEM_MAX);
action = queue->items + queue->count;
action->index = queue->count;
action->data = NULL;
action->onStart = NULL;
action->onUpdate = NULL;
action->onEnd = NULL;
queue->count++;
return action;
}
void queueUpdate(queue_t *queue, float delta) {
queueaction_t *action;
ASSERT_NOT_NULL(queue);
ASSERT_GREATER_THAN(delta, 0);
queue->timeline += delta;
if(queue->current >= queue->count) return;
action = queue->items + queue->current;
if(action->onUpdate != NULL) {
action->onUpdate(queue, action, queue->current);
}
}
void queueDispose(queue_t *queue) {
queueaction_t *action;
ASSERT_NOT_NULL(queue);
if(queue->current >= queue->count) return;
action = queue->items + queue->current;
if(action->onEnd != NULL) action->onEnd(queue, action, queue->current);
}
void queueRestack(queue_t *queue) {
uint8_t i;
ASSERT_NOT_NULL(queue);
// Rewind the array.
if(queue->current == 0) return;
arrayRewind(sizeof(queueaction_t), queue->items, ANIMATION_QUEUE_START,
queue->current, queue->count
);
// Now rewind the stack
queue->count -= queue->current;
queue->current = 0;
// Now fix indexes
for(i = 0; i < queue->count; i++) {
queue->items[i].index = i;
}
}
void _queueDelayUpdate(queue_t *queue, queueaction_t *action, uint8_t i) {
float n;
ASSERT_NOT_NULL(queue);
ASSERT_NOT_NULL(action);
ASSERT_GREATER_THAN_EQUAL_TO(i, 0);
n = queue->timeline - queue->actionStarted;
if(n < queue->delays[i]) return;
queueNext(queue);
}
queueaction_t * queueDelay(queue_t *queue, float delay) {
queueaction_t *action;
ASSERT_NOT_NULL(queue);
ASSERT_GREATER_THAN(delay, 0);
action = queueAdd(queue);
queue->delays[action->index] = delay;
action->onUpdate = &_queueDelayUpdate;
return action;
}

View File

@ -1,113 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../../libs.h"
#include "../../util/array.h"
#define ANIMATION_QUEUE_ITEM_MAX 128
#define ANIMATION_QUEUE_START 0xFF
typedef struct _queueaction_t queueaction_t;
typedef struct _queue_t queue_t;
/**
* Callback for queue events.
* @param conversation Conversation this text is attached to.
* @param text Text item that is being used in the callback
* @param i Index of the item in the queue.
*/
typedef void queuecallback_t(queue_t *queue, queueaction_t *action, uint8_t i);
typedef struct _queueaction_t {
/** Index that the action is within the queue */
uint8_t index;
/** Pointer to any custom user data */
void *data;
/** Callback to fire the moment the action is active in the queue */
queuecallback_t *onStart;
/** Callback to fire when this action has ended */
queuecallback_t *onEnd;
/** Callback to fire every update of this queue while action is active. */
queuecallback_t *onUpdate;
} queueaction_t;
typedef struct _queue_t {
/** Array of items within the queue. */
queueaction_t items[ANIMATION_QUEUE_ITEM_MAX];
uint8_t count;
/** Current index within the array of actions that is currently processing */
uint8_t current;
/** Internal timeline tracking */
float timeline;
/** Time that the current aciton started */
float actionStarted;
/** Delay Queue Item Storage */
float delays[ANIMATION_QUEUE_ITEM_MAX];
} queue_t;
/**
* Initialize the queue set.
* @param queue Queue to initialize.
*/
void queueInit(queue_t *queue);
/**
* Goes to the next action, or start the queue if this is the first action.
* @param queue Queue to skip to the next action.
* @returns Action that was just started.
*/
queueaction_t * queueNext(queue_t *queue);
/**
* Add a queue action to the queue.
* @param convo Queue to add to.
* @return Pointer to the queue action that was added.
*/
queueaction_t * queueAdd(queue_t *queue);
/**
* Updates the queue logic.
* @param convo Queue to update.
* @param delta Time delta to tick the queue by.
*/
void queueUpdate(queue_t *queue, float delta);
/**
* Dispose the queue when finished.
* @param queue Queue to dispose.
*/
void queueDispose(queue_t *queue);
/**
* Restacks the queue. The restack process essentially rewinds the queue so that
* the current items move back to position 0, and allows you to add more items
* to the queue again. Because the memory does shift, and the indexes do change
* a lot of your pointers will break, make sure you re-reference all your
* pointers.
*
* @param queue Queue to restack.
*/
void queueRestack(queue_t *queue);
/** Callbacks for Queue Delay Action */
void _queueDelayUpdate(queue_t *queue, queueaction_t *action, uint8_t i);
/**
* Adds a delay action to a queue.
* @param queue Queue to add to.
* @param delay Delay time (in seconds) to have.
* @return Pointer to the action added to the queue.
*/
queueaction_t * queueDelay(queue_t *queue, float delay);

View File

@ -1,184 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "timeline.h"
void _timelineActionDeltaUpdateStart(
timeline_t *timeline, timelineaction_t *action, uint8_t i
) {
ASSERT_NOT_NULL(timeline);
ASSERT_NOT_NULL(action);
ASSERT_GREATER_THAN_EQUAL_TO(i, 0);
ASSERT_LESS_THAN(i, TIMELINE_ACTION_COUNT_MAX);
if(action->data == NULL) return;
*((float *)action->data) = timeline->initials[i];
}
void _timelineActionDeltaUpdateDuration(
timeline_t *timeline, timelineaction_t *action, uint8_t i
) {
float n;
ASSERT_NOT_NULL(timeline);
ASSERT_NOT_NULL(action);
ASSERT_GREATER_THAN_EQUAL_TO(i, 0);
ASSERT_LESS_THAN(i, TIMELINE_ACTION_COUNT_MAX);
if(action->data == NULL) return;
n = timeline->easings[i](
timelineActionGetTimeRaw(timeline, action)
);
*((float *)action->data) = timeline->initials[i] + (timeline->deltas[i] * n);
}
void _timelineActionDeltaUpdateEnd(
timeline_t *timeline, timelineaction_t *action, uint8_t i
) {
ASSERT_NOT_NULL(timeline);
ASSERT_NOT_NULL(action);
ASSERT_GREATER_THAN_EQUAL_TO(i, 0);
ASSERT_LESS_THAN(i, TIMELINE_ACTION_COUNT_MAX);
if(action->data == NULL) return;
*((float *)action->data) = timeline->initials[i] + timeline->deltas[i];
}
void timelineInit(timeline_t *timeline) {
ASSERT_NOT_NULL(timeline);
timeline->current = 0;
timeline->diff = 0;
timeline->previous = 0;
timeline->user = 0;
timeline->actionCount = 0;
}
void timelineUpdate(timeline_t *timeline, float delta) {
uint8_t i;
timelineaction_t *action;
float full;
ASSERT_NOT_NULL(timeline);
ASSERT_GREATER_THAN(delta, 0);
timeline->diff = delta;
timeline->previous = timeline->current;
timeline->current = timeline->current + delta;
// Find all actions that would have started or ended in this timespan.
for(i = 0; i < timeline->actionCount; i++) {
action = timeline->actions +i;
// Has the action started yet?
if(action->start > timeline->current) continue;
// Did we start this frame?
if(action->start > timeline->previous && action->onStart != NULL) {
action->onStart(timeline, action, i);
}
// Durations of 0 only fire starts, never ends or durations.
if(action->duration == 0) continue;
// Is the end still in the future? Durations in negatives go forever
full = action->start+action->duration;
if(action->duration < 0 || full > timeline->current) {
if(action->onDuration != NULL) action->onDuration(timeline, action, i);
} else if(full > timeline->previous) {// Did we end this frame?
if(action->onEnd != NULL) action->onEnd(timeline, action, i);
if(action->loop) action->start = timeline->current;
}
}
}
bool timelineIsFinished(timeline_t *timeline) {
uint8_t i;
timelineaction_t *action;
ASSERT_NOT_NULL(timeline);
for(i = 0; i < timeline->actionCount; i++) {
action = timeline->actions +i;
if(action->start > timeline->current) return false;
if(action->duration < 0) return false;
if(action->duration == 0) continue;
if(action->start+action->duration > timeline->current) return false;
}
return true;
}
timelineaction_t * timelineAddAction(timeline_t *timeline, float start,
float duration
) {
timelineaction_t *action;
ASSERT_NOT_NULL(timeline);
ASSERT_LESS_THAN(timeline->actionCount, TIMELINE_ACTION_COUNT_MAX);
ASSERT_GREATER_THAN_EQUAL_TO(start, 0);
ASSERT_IF(duration < 0, ASSERT_EQUAL(duration, -1));
action = timeline->actions + (timeline->actionCount++);
action->loop = false;
action->start = start, action->duration = duration;
action->onStart = action->onEnd = action->onDuration = NULL;
return action;
}
timelineaction_t * timelineAddDeltaAction(timeline_t *timeline,
float start, float duration, float initial, float delta,
easefunction_t *easing, float *destination
) {
timelineaction_t *action;
ASSERT_NOT_NULL(timeline);
timeline->initials[timeline->actionCount] = initial;
timeline->deltas[timeline->actionCount] = delta;
timeline->easings[timeline->actionCount] = (
easing == NULL ? &easeLinear : easing
);
action = timelineAddAction(timeline, start, duration);
action->data = destination;
action->onStart = &_timelineActionDeltaUpdateStart;
action->onDuration = &_timelineActionDeltaUpdateDuration;
action->onEnd = &_timelineActionDeltaUpdateEnd;
return action;
}
timelineaction_t * timelineAddDeltaActionTo(timeline_t *timeline,
float start, float duration, float initial, float end,
easefunction_t *easing, float *destination
) {
ASSERT_NOT_NULL(timeline);
return timelineAddDeltaAction(
timeline, start, duration, initial, end-initial, easing, destination
);
}
float timelineActionGetTimeRaw(timeline_t *timeline, timelineaction_t *action) {
ASSERT_NOT_NULL(timeline);
ASSERT_NOT_NULL(action);
return (timeline->current - action->start) / action->duration;
}
float timelineActionGetTime(timeline_t *tl, timelineaction_t *at) {
ASSERT_NOT_NULL(tl);
ASSERT_NOT_NULL(at);
return mathClamp(timelineActionGetTimeRaw(tl, at), 0, 1);
}
void timelineClear(timeline_t *timeline) {
ASSERT_NOT_NULL(timeline);
timeline->actionCount = 0;
}

View File

@ -1,188 +0,0 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "../../libs.h"
#include "../../assert/assert.h"
#include "../../util/math.h"
#include "easing.h"
/** Maximum number of actions a timeline can support, smaller than 0xFF */
#define TIMELINE_ACTION_COUNT_MAX 128
/** Type forwarders */
typedef struct _timeline_t timeline_t;
typedef struct _timelineaction_t timelineaction_t;
/**
* Callback for when a timeline event occurs
* @param timeline The timeline that fired this callback.
* @param action The action that this callback is attached to.
* @param i The index that this action is within the timeline.
*/
typedef void timelinecallback_t(timeline_t *timeline, timelineaction_t *action,
uint8_t i
);
typedef struct _timelineaction_t {
/** Pointer to any custom user data the timeline action wants to use. */
void *data;
/**
* The time that this action should occur within the timeline
* set to 0 or less to start immediately.
*/
float start;
/**
* The duration of the action, this will decide for how long onDuration will
* be called for, and when onEnd should be called.
* Set to a negative number to have this continue forever.
* Set to 0 to only fire the onStart.
* onStart can fire with either onDuration and onEnd on the same frame, but
* onEnd and onDuration cannot fire the same frame.
*/
float duration;
/**
* Enables animation looping. This works by forcing start to be equal to the
* current time at the point in time that onEnd is called. This will also stop
* onStart being called so ensure that your onStart and onEnd logic works.
*/
bool loop;
timelinecallback_t *onStart;
timelinecallback_t *onDuration;
timelinecallback_t *onEnd;
} timelineaction_t;
typedef struct _timeline_t {
/** The current time as far as the timeline is concerned */
float current;
/** The time of the last "frame" as far as the timeline is concerned */
float previous;
/** The frame time diff, essentially current = previous + diff */
float diff;
/** User pointer, allows you to point to some other data */
void *user;
/** Actions within the timeline */
timelineaction_t actions[TIMELINE_ACTION_COUNT_MAX];
/** For delta actions, storage of the initial values */
float initials[TIMELINE_ACTION_COUNT_MAX];
/** For delta actions, storage of their deltas. */
float deltas[TIMELINE_ACTION_COUNT_MAX];
/** Easing functions to use for delta functions */
easefunction_t *easings[TIMELINE_ACTION_COUNT_MAX];
uint8_t actionCount;
} timeline_t;
/**
* Initializes a timeline back to its default state.
*
* @param timeline Timeline to initialize.
*/
void timelineInit(timeline_t *timeline);
/**
* Ticks the timeline. This can be done using any delta.
*
* @param timeline Timeline to tick
* @param delta Delta to tick.
*/
void timelineUpdate(timeline_t *timeline, float delta);
/**
* Returns true if every action in the timeline has finished.
*
* @param timeline Timeline to check
* @return True if finished, otherwise false.
*/
bool timelineIsFinished(timeline_t *timeline);
/**
* Adds an action to the timeline. This will initialize the action callbacks to
* NULL, you will need to initialize your own callbacks.
*
* @param timeline Timeline to add to.
* @param start Start time.
* @param duration Duration time
* @return Pointer to the timeline action or NULL if the list is full.
*/
timelineaction_t * timelineAddAction(timeline_t *timeline, float start,
float duration
);
/**
* Add a special action kind that can treat delta style animations. These are
* animations that have a start, and an end value, that will be tracked for you
* and keep you up to date.
*
* @param timeline Timeline to add to.
* @param start Starting time.
* @param duration Animation duration.
* @param initial Initial value for the animation.
* @param delta Delta value for the animation.
* @param easing Pointer to an easing function to use, set to NULL for linear.
* @param destination A constant floating point to update.
* @return The queued timeline action.
*/
timelineaction_t * timelineAddDeltaAction(timeline_t *timeline,
float start, float duration, float initial, float delta,
easefunction_t *easing, float *destination
);
/**
* Shorthand for timelineAddDeltaAction that will calculate the delta based on
* and end position.
*
* @param timeline Timeline to add to.
* @param start Starting time.
* @param duration Animation duration.
* @param initial Initial value for the animation.
* @param end End value for the animation.
* @param easing Pointer to an easing function to use, set to NULL for linear.
* @param destination A constant floating point to update.
* @return The queued timeline action.
*/
timelineaction_t * timelineAddDeltaActionTo(timeline_t *timeline,
float start, float duration, float initial, float end,
easefunction_t *easing, float *destination
);
/**
* Gets the timeline action's animation time. This is a representation of
* 0 - 1 where 0 means the animation is at the start, and 1 meaning the
* animation is at full completion. This is not clamped and may exceed 1.
*
* @param timeline Timeline the action belongs to.
* @param action Action itself.
* @return 0 - 1+, where 0 = start, 1 = duration, >1 is time since duration.
*/
float timelineActionGetTimeRaw(timeline_t *timeline, timelineaction_t *action);
/**
* Gets the timeline action's animation time between 0 - 1, clamped.
*
* @param tl Timeline to get delta from.
* @param at Timeline action.
* @return 0 - 1, where 0 = start, 1 = duration.
*/
float timelineActionGetTime(timeline_t *tl, timelineaction_t *at);
/**
* Removes all actions from the timeline.
*
* @param timeline Timeline to clear.
*/
void timelineClear(timeline_t *timeline);

View File

@ -1,127 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "bitmapfont.h"
tilesetdiv_t * bitmapFontGetCharacterDivision(tileset_t *tileset,
char character
) {
int32_t i = ((int32_t)character) - BITMAP_FONT_CHAR_START;
ASSERT_NOT_NULL(tileset);
return tileset->divisions + i;
}
bitmapfontmeasure_t bitmapFontMeasure(char *string,
float charWidth, float charHeight
) {
int32_t i;
float x, y;
char c;
bitmapfontmeasure_t measure = {
.height = 0, .lines = 1, .width = 0
};
ASSERT_NOT_NULL(string);
ASSERT_GREATER_THAN(charWidth, 0);
ASSERT_GREATER_THAN(charHeight, 0);
i = 0;
y = 0;
x = 0;
while(true) {
c = string[i];
if(c == '\0') break;
i++;
if(c == '\n') {
measure.width = mathMax(x, measure.width);
x = 0;
y += charHeight;
measure.lines++;
continue;
} else if(c == ' ') {
x += charWidth;
continue;
}
x += charWidth;
}
measure.width = mathMax(x, measure.width);
measure.height = y + charHeight;
return measure;
}
bitmapfontmeasure_t bitmapFontSpriteBatchBuffer(
spritebatch_t *batch, tileset_t *tileset,
char *string, float x, float y, float z, float charWidth, float charHeight
) {
int32_t i;
char c;
tilesetdiv_t *div;
float cx, cy;
bitmapfontmeasure_t measure;
// Detect char dimensions
if(charWidth == -1) charWidth = tileset->divX * (charHeight / tileset->divY);
if(charHeight == -1) charHeight = tileset->divY * (charWidth / tileset->divX);
// Position the text.
if(x == BITMAP_FONT_CENTER_X ||
y == BITMAP_FONT_CENTER_Y ||
x == BITMAP_FONT_RIGHT_X
) {
measure = bitmapFontMeasure(string, charWidth, charHeight);
if(x == BITMAP_FONT_CENTER_X) {
x = -(measure.width/2);
} else if(x == BITMAP_FONT_RIGHT_X) {
x = -measure.width;
}
if(y == BITMAP_FONT_CENTER_Y) y = -(measure.height/2);
}
// Begin buffering the sprite batch
measure.width = 0;
measure.height = 0;
measure.lines = 1;
i = 0;
cx = x, cy = y;
while(true) {
c = string[i];
if(c == '\0') break;
i++;
// Special chars
if(c == '\n') {
measure.width = mathMax(cx-x, measure.width);
cx = x;
cy += charHeight;
measure.lines++;
continue;
} else if(c == ' ') {
cx += charWidth;
continue;
}
div = bitmapFontGetCharacterDivision(tileset, c);
spriteBatchQuad(batch, -1,
cx, cy, z, charWidth, charHeight,
div->x0, div->y1, div->x1, div->y0
);
cx += charWidth;
}
measure.width = mathMax(cx-x, measure.width);
measure.height = cy-y + charHeight;
return measure;
}

View File

@ -1,72 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "../assert/assert.h"
#include "spritebatch.h"
#include "tileset.h"
#include "../util/math.h"
/** Which is the first character within the font tilemap */
#define BITMAP_FONT_CHAR_START 33
/** Center a font along the X axis */
#define BITMAP_FONT_CENTER_X 9876543
/** Center a font along the Y axis */
#define BITMAP_FONT_CENTER_Y -BITMAP_FONT_CENTER_X
/** Align right edge of font to origin */
#define BITMAP_FONT_RIGHT_X (BITMAP_FONT_CENTER_X-1)
typedef struct {
float width, height;
int32_t lines;
} bitmapfontmeasure_t;
/**
* Get the division for a given character.
*
* @param tileset Tileset to get the division from.
* @param character Character to get the division for.
* @return The division from the tileset for the character.
*/
tilesetdiv_t * bitmapFontGetCharacterDivision(tileset_t *tileset,
char character
);
/**
* Measures a string's fully rendered size.
*
* @param string The string to measure
* @param charWidth The width of each character.
* @param charHeight The height of each character.
* @return The measured string.
*/
bitmapfontmeasure_t bitmapFontMeasure(char *string,
float charWidth, float charHeight
);
/**
* Renders a set of font characters to the sprite. Coordinates are anchored to
* the top left (0,0) origin.
*
* @param batch Sprite Batch to render to.
* @param tileset Tileset for the font.
* @param string String to render.
* @param x Position in X space.
* @param y Position in Y space.
* @param z Position in Z space.
* @param charWidth Width of each character. Set to -1 to use the height ratio.
* @param charHeight Height of each character. Set to -1 to be the width ratio.
* @returns The string measurement.
*/
bitmapfontmeasure_t bitmapFontSpriteBatchBuffer(
spritebatch_t *batch, tileset_t *tileset,
char *string, float x, float y, float z, float charWidth, float charHeight
);

View File

@ -1,67 +0,0 @@
/**
* Copyright (c) 2021 Dominic Msters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "camera.h"
void cameraLookAt(camera_t *camera,
float x, float y, float z,
float targetX, float targetY, float targetZ
) {
ASSERT_NOT_NULL(camera);
matrixIdentity(&camera->view);
matrixLookAt(&camera->view, x, y, z, targetX, targetY, targetZ, 0, 1, 0);
}
void cameraLookAtStruct(camera_t *camera, cameralookat_t look) {
ASSERT_NOT_NULL(camera);
cameraLookAt(camera,
look.x, look.y, look.z, look.lookX, look.lookY, look.lookZ
);
}
void cameraLook(camera_t *camera,
float x, float y, float z,
float pitch, float yaw, float roll
) {
ASSERT_NOT_NULL(camera);
matrixIdentity(&camera->view);
matrixLook(&camera->view, x, y, z, pitch, yaw, roll, 0, 1, 0);
}
void cameraPerspective(camera_t *camera,
float fov, float aspect, float camNear, float camFar
) {
ASSERT_NOT_NULL(camera);
matrixIdentity(&camera->projection);
matrixPerspective(&camera->projection,mathDeg2Rad(fov),aspect,camNear,camFar);
}
void cameraOrtho(camera_t *camera,
float left, float right, float bottom, float top, float camNear, float camFar
) {
ASSERT_NOT_NULL(camera);
matrixIdentity(&camera->projection);
matrixOrtho(&camera->projection, left, right, bottom, top, camNear, camFar);
}
void cameraOrbit(camera_t *camera,
float distance, float yaw, float pitch,
float targetX, float targetY, float targetZ
) {
float cy = cosf(pitch);
float x = distance * sinf(yaw) * cy;
float y = distance * sinf(pitch);
float z = distance * cosf(yaw) * cy;
ASSERT_NOT_NULL(camera);
cameraLookAt(camera, x, y, z, targetX, targetY, targetZ);
}

View File

@ -1,107 +0,0 @@
// Copyright (c) 2021 Dominic Msters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "../libs.h"
#include "../assert/assert.h"
#include "../util/math.h"
#include "matrix.h"
/** The math for the camera is stored here. */
typedef struct {
/** View Matrix (Where the camera looks) */
matrix_t view;
/** Projection Matrix (How the camera looks) */
matrix_t projection;
} camera_t;
typedef struct {
float x, y, z, lookX, lookY, lookZ;
} cameralookat_t;
/**
* Make a camera look at a position in world space while itself being positioned
* within world space.
*
* @param camera The camera to position.
* @param x The X position in world space of the camera.
* @param y The Y position in world space of the camera.
* @param z The Z position in world space of the camera.
* @param targetX The Target X position in world space of the camera.
* @param targetY The Target Y position in world space of the camera.
* @param targetZ The Target Z position in world space of the camera.
*/
void cameraLookAt(camera_t *camera,
float x, float y, float z,
float targetX, float targetY, float targetZ
);
/**
* Shorthand for look at that uses the look struct.
*
* @param camera Camera to position.
* @param look Look vectors.
*/
void cameraLookAtStruct(camera_t *camera, cameralookat_t look);
/**
* Make a camera look in a direction based on a rotation direction.
*
* @param camera The camera to position.
* @param x The X position in world space of the camera.
* @param y The Y position in world space of the camera.
* @param z The Z position in world space of the camera.
* @param pitch The pitch of the camera.
* @param yaw The yaw of the camera.
* @param roll The roll of the camera.
*/
void cameraLook(camera_t *camera,
float x, float y, float z,
float pitch, float yaw, float roll
);
/**
* Make a camera's projection be a 3D Perspective view.
*
* @param camera The camera to project.
* @param fov The field of view of the camera (in degrees).
* @param aspect The aspect ratio of the camera (w / h)
* @param camNear The near plane clip.
* @param camFar the far plane clip.
*/
void cameraPerspective(camera_t *camera,
float fov, float aspect, float camNear, float camFar
);
/**
* Defines an orthorgonal camera matrix.
*
* @param camera Camera to position.
* @param left The left side of the viewport.
* @param right The right side of the viewport.
* @param bottom The bottom side of the viewport.
* @param camNear The near plane clip.
* @param camFar the far plane clip.
*/
void cameraOrtho(camera_t *camera,
float left, float right, float bottom, float top, float camNear, float camFar
);
/**
* Update a camera to orbit around a point.
*
* @param camera Camera to update
* @param distance Distance from the point
* @param yaw Yaw (Y axis) rotation.
* @param pitch Pitch (X/Z axis) rotation.
* @param targetX X point to orbit around.
* @param targetY Y point to orbit around.
* @param targetZ Z point to orbit around.
*/
void cameraOrbit(camera_t *camera,
float distance, float yaw, float pitch,
float targetX, float targetY, float targetZ
);

View File

@ -1,238 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "font.h"
// Due to some compiler bullshit, this is here.
#ifndef STB_TRUETYPE_IMPLEMENTATION
#define STB_TRUETYPE_IMPLEMENTATION
#include <stb_truetype.h>
#endif
void fontInit(font_t *font, char *data) {
int32_t i, s;
uint8_t *bitmapData;
pixel_t *pixels;
ASSERT_NOT_NULL(font);
ASSERT_NOT_NULL(data);
s = FONT_TEXTURE_WIDTH * FONT_TEXTURE_HEIGHT;
bitmapData = malloc(sizeof(uint8_t) * s);
ASSERT_NOT_NULL(bitmapData);
pixels = malloc(sizeof(pixel_t) * s);
ASSERT_NOT_NULL(pixels);
// STBTT Loads fonts as single channel values only.
stbtt_BakeFontBitmap(
data, 0, FONT_TEXTURE_SIZE, bitmapData,
FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT,
FONT_FIRST_CHAR, FONT_NUM_CHARS,
font->characterData
);
for(i = 0; i < FONT_TEXTURE_WIDTH * FONT_TEXTURE_HEIGHT; i++) {
pixels[i].r = 0xFF;
pixels[i].g = 0xFF;
pixels[i].b = 0xFF;
pixels[i].a = bitmapData[i];
}
textureInit(&font->texture, FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT, pixels);
free(bitmapData);
free(pixels);
}
void fontDispose(font_t *font) {
ASSERT_NOT_NULL(font);
textureDispose(&font->texture);
}
float fontGetScale(float fontSize) {
ASSERT_GREATER_THAN(fontSize, 0);
return fontSize / FONT_SIZE_DEFAULT * FONT_GLOBAL_SCALE;
}
bool _fontTextBufferAddLine(fonttextinfo_t *info, int32_t start, int32_t len) {
ASSERT_NOT_NULL(info);
ASSERT_GREATER_THAN_EQUAL_TO(start, 0);
ASSERT_GREATER_THAN(len, 0);
info->lineCount++;
if(info->lineCount >= FONT_TEXT_INFO_LINES_MAX) {
return false;
}
info->lines[info->lineCount].start = start;
info->lines[info->lineCount].length = len;
return true;
}
void fontTextBuffer(
font_t *font, primitive_t *primitive, fonttextinfo_t *info, char *text,
float maxWidth, float fontSize
) {
int32_t i, j, wordStart;
char c;
float x, y, wordX, scale;
stbtt_aligned_quad *quads;
stbtt_aligned_quad *quad;
ASSERT_NOT_NULL(font);
ASSERT_NOT_NULL(primitive);
ASSERT_NOT_NULL(info);
ASSERT_NOT_NULL(text);
ASSERT_GREATER_THAN(maxWidth, 0);
ASSERT_GREATER_THAN(fontSize, 0);
// Make some space
quads = malloc(sizeof(stbtt_aligned_quad) * strlen(text));
ASSERT_NOT_NULL(quads);
// Get the font scale
scale = fontGetScale(fontSize);
// Adjust the max width to match the scale, and allow "no max width".
maxWidth = maxWidth == -1 ? 9999999 : maxWidth * (1 / scale);
/** Which index in the original text var is the current word from */
wordStart = 0;
// Setup Scales
info->length = 0;
info->realLength = 0;
info->lineCount = 0;
// Prepare the line counters
info->lines[0].start = 0;
info->lines[0].length = 0;
// Reset Dimensions
info->width = 0, info->height = 0;
// Setup the initial loop state, and X/Y coords for the quad.
i = 0;
x = 0;
y = FONT_INITIAL_LINE;
wordX = 0;
while(c = text[i++]) {
if(info->lineCount >= FONT_TEXT_INFO_LINES_MAX) break;
info->length++;
// When space, start of new word about to begin
if(c == FONT_SPACE) {
x += FONT_SPACE_SIZE * scale;
// Did this space cause a newline?
if(x > maxWidth) {
_fontTextBufferAddLine(info, info->realLength, 0);
y += FONT_LINE_HEIGHT;
x = 0;
}
wordX = x;
wordStart = info->realLength;
continue;
}
// New line.
if(c == FONT_NEWLINE) {
_fontTextBufferAddLine(info, info->realLength, 0);
wordStart = info->realLength;
y += FONT_LINE_HEIGHT;
x = 0;
continue;
}
// Generate the quad.
quad = quads + info->realLength;
stbtt_GetBakedQuad(font->characterData,
FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT,
((int32_t)c)-FONT_FIRST_CHAR, &x, &y, quad, FONT_FILL_MODE
);
// Now measure the width of the line (take the right side of that quad)
if(quad->x1 > maxWidth) {
// We've exceeded the edge, go back to the start of the word and newline.
x = quad->x1 - wordX;
for(j = wordStart; j <= info->realLength; j++) {
quad = quads + j;
quad->x0 -= wordX;
quad->x1 -= wordX;
quad->y0 += FONT_LINE_HEIGHT;
quad->y1 += FONT_LINE_HEIGHT;
}
// Go back to the previous (still current) line and remove the chars
info->lines[info->lineCount].length -= info->realLength - wordStart;
// Next line begins with this word
y += FONT_LINE_HEIGHT;
if(!_fontTextBufferAddLine(info, wordStart, info->realLength-wordStart)) {
continue;
}
wordX = 0;
}
info->lines[info->lineCount].length++;
info->realLength++;
}
info->lineCount++;
// Initialize primitive
primitiveInit(primitive,
QUAD_VERTICE_COUNT * info->realLength,
QUAD_INDICE_COUNT * info->realLength
);
for(j = 0; j < info->realLength; j++) {
quad = quads + j;
// Scale the Quad
if(scale != 1.0) {
quad->x0 *= scale;
quad->x1 *= scale;
quad->y0 *= scale;
quad->y1 *= scale;
}
// Update the dimensions.
info->width = mathMax(info->width, quad->x1);
info->height = mathMax(info->height, quad->y1);
// Buffer the quad.
quadBuffer(primitive, 0,
quad->x0, quad->y0, quad->s0, quad->t0,
quad->x1, quad->y1, quad->s1, quad->t1,
j * QUAD_VERTICE_COUNT, j * QUAD_INDICE_COUNT
);
}
// Free up
free(quads);
}
int32_t fontGetLineCharCount(fonttextinfo_t *info,int32_t start,int32_t count) {
int32_t charCount, i, m;
ASSERT_NOT_NULL(info);
ASSERT_GREATER_THAN_EQUAL_TO(start, 0);
ASSERT_GREATER_THAN(count, 0);
m = mathMin(start+count, info->lineCount);
charCount = 0;
for(i = start; i < m; i++) {
charCount += info->lines[i].length;
}
return charCount;
}

View File

@ -1,139 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "texture.h"
#include "primitive/primitive.h"
#include "primitive/quad.h"
#include "../util/mem.h"
#include "../util/math.h"
#include "../assert/assert.h"
/** Which character (ASCII) to start the font from */
#define FONT_FIRST_CHAR 32
/** How many characters (after the first char) to generate */
#define FONT_NUM_CHARS 96
/** Width of the loaded font texture */
#define FONT_TEXTURE_WIDTH 1024
/** Height of the loaded font texture */
#define FONT_TEXTURE_HEIGHT FONT_TEXTURE_WIDTH
/** Refer to STBTT docs for OpenGL Fill Mode v d3d Fill Modes */
#define FONT_FILL_MODE 1
/** Passed to STBTT for scaling the font, essentially the font resolution */
#define FONT_TEXTURE_SIZE 64.0f
/** The global scale, just used to provide fine control of font sizes */
#define FONT_GLOBAL_SCALE 0.5f;
/** Default Font Size (on which all font scales are based) */
#define FONT_SIZE_DEFAULT 16.0f
// Chars
#define FONT_NEWLINE '\n'
#define FONT_SPACE ' '
// Heights
#define FONT_LINE_HEIGHT FONT_TEXTURE_SIZE * 0.75f
#define FONT_INITIAL_LINE FONT_LINE_HEIGHT * 0.75f
#define FONT_SPACE_SIZE FONT_TEXTURE_SIZE * 0.45f
/** Maximum number of newlines that a font text info can hold. */
#define FONT_TEXT_INFO_LINES_MAX 16
/** Representation of a font that can be used to render text */
typedef struct {
texture_t texture;
stbtt_bakedchar characterData[FONT_NUM_CHARS];
} font_t;
typedef struct {
/** What (real character) index the line starts at */
int32_t start;
/** How many (real) characters the line is in length */
int32_t length;
} fonttextinfoline_t;
typedef struct {
/** How many raw chars are in the string */
int32_t length;
/** How many real characters (non whitespace) are in the string */
int32_t realLength;
/** How many lines is the string? Trailing newlines will count */
int32_t lineCount;
/** The real character info for each line */
fonttextinfoline_t lines[FONT_TEXT_INFO_LINES_MAX];
/** Dimensions of the string */
float width, height;
} fonttextinfo_t;
/**
* Initializes Font from raw TTF data.
* @param font Font to initialize
* @param data Data to intialize for.
*/
void fontInit(font_t *font, char *data);
/**
* Clean up a previously loaded font
* @param font Loaded font.
*/
void fontDispose(font_t *Font);
/**
* Convert a Font's Size into a Font Scale. The scale is based on the font's
* default size for the given texture size (Refer to FONT_SIZE_DEFAULT).
*
* @param fontSize Font size to convert.
* @return The times scale that the font size is to the textured default.
*/
float fontGetScale(float fontSize);
/**
* Internal method that adds a line to the text buffer process.
*
* @param info Info to add to.
* @param start Start character index for the next line.
* @param len Length of the next line.
* @return True if added a line successfully, otherwise false.
*/
bool _fontTextBufferAddLine(fonttextinfo_t *info, int32_t start, int32_t len);
/**
* Clamps text to a max width, inserting newlines where possible.
*
* @param font Font to use
* @param primitive Primitive to buffer the text to.
* @param info Font text info to clamp into.
* @param text Text to clamp.
* @param maxWidth Max width (pixels) to clamp the text to, -1 for no max width.
* @param fontSize Font Size of the text.
*/
void fontTextBuffer(
font_t *font, primitive_t *primitive, fonttextinfo_t *info, char *text,
float maxWidth, float fontSize
);
/**
* Returns the number of real characters on the lines specified. Useful when
* attempting to clamp to a set of lines.
*
* @param info Info to get the character counts from.
* @param start Starting line index.
* @param count Count of lines, this method will clamp to info's line length.
* @returns The count of characters in those lines summed.
*/
int32_t fontGetLineCharCount(fonttextinfo_t *info, int32_t start,int32_t count);

View File

@ -1,76 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "framebuffer.h"
void frameBufferInit(framebuffer_t *fb, int32_t w, int32_t h) {
// At least one pixel
if(w <= 0) w = 1;
if(h <= 0) h = 1;
// Create Color Attachment texture.
textureInit(&fb->texture, w, h, NULL);
// Create Frame Buffer
glGenFramebuffers(1, &fb->fboId);
glBindFramebuffer(GL_FRAMEBUFFER, fb->fboId);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, fb->texture.id, 0
);
// Render Buffer
glGenRenderbuffers(1, &fb->rboId);
glBindRenderbuffer(GL_RENDERBUFFER, fb->rboId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, fb->rboId
);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
uint32_t error;
error = 0;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void frameBufferUse(framebuffer_t *frameBuffer, bool clear) {
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer->fboId);
glViewport(0, 0, frameBuffer->texture.width, frameBuffer->texture.height);
if(clear) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
}
void frameBufferResize(framebuffer_t *frameBuffer,int32_t width,int32_t height){
if((
frameBuffer->texture.width == width &&
frameBuffer->texture.height == height
)) return;
frameBufferDispose(frameBuffer);
frameBufferInit(frameBuffer, width, height);
}
void frameBufferUnbind(float viewWidth, float viewHeight, bool clear) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, (GLsizei)viewWidth, (GLsizei)viewHeight);
if(clear) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
}
void frameBufferDispose(framebuffer_t *frameBuffer) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glDeleteRenderbuffers(1, &frameBuffer->rboId);
glDeleteFramebuffers(1, &frameBuffer->fboId);
textureDispose(&frameBuffer->texture);
}

View File

@ -1,59 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "texture.h"
typedef struct {
GLuint fboId;
GLuint rboId;
texture_t texture;
} framebuffer_t;
/**
* Initializes frame buffer that can be rendered to.
* @param frameBuffer Frame buffer to initialize.
* @param width Width of the frame buffer (in pixels).
* @param height Height of the frame buffer (in pixels).
* @return A renderable frame buffer.
*/
void frameBufferInit(framebuffer_t *buffer, int32_t width, int32_t height);
/**
* Use a given frame buffer as the current rendering context.
*
* @param frameBuffer Frame buffer to use.
* @param clear Whether or not to clear the frame buffer prior to rendering.
*/
void frameBufferUse(framebuffer_t *frameBuffer, bool clear);
/**
* Resize an existing frame buffer. This will do the check if resizing is even
* necessary for you.
*
* @param frameBuffer Frame buffer to resize.
* @param width New width of the frame buffer.
* @param height New height of the frame buffer.
*/
void frameBufferResize(framebuffer_t *frameBuffer,int32_t width,int32_t height);
/**
* Unbind the currently bound frame buffer.
*
* @param viewWidth Viewport width.
* @param viewHeight Viewport height.
* @param clear Whether or not to clear the back buffer.
*/
void frameBufferUnbind(float viewWidth, float viewHeight, bool clear);
/**
* Dispose/cleanup a previously created frame buffer.
*
* @param frameBuffer Frame Buffer to clean.
*/
void frameBufferDispose(framebuffer_t *frameBuffer);

View File

@ -1,90 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "matrix.h"
void matrixIdentity(matrix_t *matrix) {
ASSERT_NOT_NULL(matrix);
glm_mat4_identity(matrix->internalMatrix);
}
void matrixLookAt(matrix_t *matrix,
float x,float y,float z,
float tx,float ty, float tz,
float ux, float uy, float uz
) {
ASSERT_NOT_NULL(matrix);
glm_lookat(
(vec3){ x, y, z },
(vec3){ tx, ty, tz },
(vec3){ ux, uy, uz },
matrix->internalMatrix
);
}
void matrixLook(matrix_t *matrix,
float x, float y, float z,
float pitch, float yaw, float roll,
float ux, float uy, float uz
) {
ASSERT_NOT_NULL(matrix);
glm_look(
(vec3){ x, y, z },
(vec3){ pitch, yaw, roll },
(vec3){ ux, uy, uz },
matrix->internalMatrix
);
}
void matrixPerspective(matrix_t *matrix,
float fov, float aspect, float camNear, float camFar
) {
ASSERT_NOT_NULL(matrix);
glm_perspective(fov, aspect, camNear, camFar, matrix->internalMatrix);
}
void matrixOrtho(matrix_t *matrix,
float left, float right, float bottom, float top, float camNear, float camFar
) {
ASSERT_NOT_NULL(matrix);
glm_ortho(left, right, bottom, top, camNear, camFar, matrix->internalMatrix);
}
void matrixTranslate(matrix_t *matrix, float x, float y, float z) {
ASSERT_NOT_NULL(matrix);
glm_translate(matrix->internalMatrix, (vec3){ x, y, z });
}
void matrixRotate(matrix_t *matrix, float angle, float x, float y, float z) {
ASSERT_NOT_NULL(matrix);
glm_rotate(matrix->internalMatrix, angle, (vec3){ x, y, z });
}
void matrixScale(matrix_t *matrix, float x, float y, float z) {
ASSERT_NOT_NULL(matrix);
glm_scale(matrix->internalMatrix, (vec3){ x, y, z });
}
matrix_t matrixPositionAndScale(
float x, float y, float z,
float pitch, float yaw, float roll,
float scaleX, float scaleY, float scaleZ
) {
matrix_t matrix;
matrixIdentity(&matrix);
matrixTranslate(&matrix, x, y, z);
// Rotation (YZX order)
matrixRotate(&matrix, yaw, 0, 1, 0);
matrixRotate(&matrix, roll, 0, 0, 1);
matrixRotate(&matrix, pitch, 1, 0, 0);
matrixScale(&matrix, scaleX, scaleY, scaleZ);
return matrix;
}

View File

@ -1,145 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "../assert/assert.h"
/**
* Representation for a matrix. Used as a highlevel wrapper for the math
* functions that sit underneath this API.
*/
typedef struct {
/** Internal Matrix API */
mat4 internalMatrix;
} matrix_t;
/**
* Makes matrix identity.
* @param matrix Matrix to identify.
*/
void matrixIdentity(matrix_t *matrix);
/**
* Applies a look at point vector to a matrix.
*
* @param matrix Matrix to apply to.
* @param x Camera source X.
* @param y Camera source Y.
* @param z Camera source Z.
* @param tx Camera target X.
* @param ty Camera target Y.
* @param tz Camera target Z.
* @param ux Camera up vector X.
* @param uy Camera up vector Y.
* @param uz Camera up vector Z.
*/
void matrixLookAt(matrix_t *matrix,
float x,float y,float z,
float tx,float ty, float tz,
float ux, float uy, float uz
);
/**
* Applies a look vector to a matrix.
*
* @param matrix Matrix to apply to.
* @param x Camera source X.
* @param y Camera source Y.
* @param z Camera source Z.
* @param pitch Camera pitch
* @param yaw Camera yaw.
* @param roll Camera roll.
* @param ux Camera up vector X.
* @param uy Camera up vector Y.
* @param uz Camera up vector Z.
*/
void matrixLook(matrix_t *matrix,
float x, float y, float z,
float pitch, float yaw, float roll,
float ux, float uy, float uz
);
/**
* Applies a perspective projection to a matrix.
*
* @param matrix Matrix to apply to.
* @param fov Field of View (in radians) to use.
* @param aspect Aspect ratio (w/h) of the viewport.
* @param camNear Near vector, > 0.
* @param camFar Far view vector.
*/
void matrixPerspective(matrix_t *matrix,
float fov,float aspect, float camNear, float camFar
);
/**
* Applies an orthogonal projection to a matrix.
*
* @param matrix Matrix to apply to.
* @param left Left view position.
* @param right Right view position.
* @param bottom Bottom view position.
* @param top Top view position.
* @param camNear Near vector, > 0.
* @param camFar Far view vector.
*/
void matrixOrtho(matrix_t *matrix,
float left, float right, float bottom, float top, float camNear, float camFar
);
/**
* Performs a matrix translation.
*
* @param matrix Matrix to translate.
* @param x X coordinate to translate on.
* @param y Y coordinate to translate on.
* @param z Z coordinate to translate on.
*/
void matrixTranslate(matrix_t *matrix, float x, float y, float z);
/**
* Applies a rotation vector to a matrix.
*
* @param matrix Matrix to rotate.
* @param angle Angle (in radians) to rotate.
* @param x X vector to rotate on.
* @param y Y vector to rotate on.
* @param z Z vector to rotate on.
*/
void matrixRotate(matrix_t *matrix, float angle, float x, float y, float z);
/**
* Scales a matrix.
*
* @param matrix Matrix to scale
* @param x X vector to scale.
* @param y Y vector to scale.
* @param z Z vector to scale.
*/
void matrixScale(matrix_t *matrix, float x, float y, float z);
/**
* Calculates a fairly standard position and scale matrix. Note that the matrix
* is calculated in the order of Translate, Yaw, Pitch, Roll, Scale.
*
* @param x X translation to apply.
* @param y Y translation to apply.
* @param z Z translation to apply.
* @param pitch Pitch rotation to apply.
* @param yaw Yaw rotation to apply.
* @param roll Roll rotation to apply.
* @param scaleX X scale factor.
* @param scaleY Y scale factor.
* @param scaleZ Z scale factor.
* @return A specially created transformation matrix.
*/
matrix_t matrixPositionAndScale(
float x, float y, float z,
float pitch, float yaw, float roll,
float scaleX, float scaleY, float scaleZ
);

View File

@ -1,13 +0,0 @@
# Copyright (c) 2021 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${PROJECT_NAME}
PRIVATE
cube.c
primitive.c
quad.c
skywall.c
)

View File

@ -1,112 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "cube.h"
void cubeBuffer(primitive_t *prim,
float x, float y, float z,
float w, float h, float d,
int32_t verticeStart, int32_t indiceStart
) {
vertice_t vertices[CUBE_VERTICE_COUNT];
indice_t indices[CUBE_INDICE_COUNT];
ASSERT_GREATER_THAN(w, 0);
ASSERT_GREATER_THAN(h, 0);
ASSERT_GREATER_THAN(d, 0);
vertices[0].x = x, vertices[0].y = y, vertices[0].z = z;
vertices[0].u = 0, vertices[0].v = 0;
vertices[1].x = x+w, vertices[1].y = y, vertices[1].z = z;
vertices[1].u = 1, vertices[1].v = 0;
vertices[2].x = x, vertices[2].y = y+h, vertices[2].z = z;
vertices[2].u = 0, vertices[2].v = 1;
vertices[3].x = x+w, vertices[3].y = y+h, vertices[3].z = z;
vertices[3].u = 1, vertices[3].v = 1;
vertices[4].x = x, vertices[4].y = y, vertices[4].z = z+d;
vertices[4].u = 0, vertices[4].v = 0;
vertices[5].x = x+w, vertices[5].y = y, vertices[5].z = z+d;
vertices[5].u = 1, vertices[5].v = 0;
vertices[6].x = x, vertices[6].y = y+h, vertices[6].z = z+d;
vertices[6].u = 0, vertices[6].v = 1;
vertices[7].x = x+w, vertices[7].y = y+h, vertices[7].z = z+d;
vertices[7].u = 1, vertices[7].v = 1;
// Back
indices[ 0] = (indice_t)(verticeStart + 0);
indices[ 1] = (indice_t)(verticeStart + 1);
indices[ 2] = (indice_t)(verticeStart + 3);
indices[ 3] = (indice_t)(verticeStart + 0);
indices[ 4] = (indice_t)(verticeStart + 2);
indices[ 5] = (indice_t)(verticeStart + 3);
// Right
indices[ 6] = (indice_t)(verticeStart + 1);
indices[ 7] = (indice_t)(verticeStart + 5);
indices[ 8] = (indice_t)(verticeStart + 7);
indices[ 9] = (indice_t)(verticeStart + 1);
indices[10] = (indice_t)(verticeStart + 3);
indices[11] = (indice_t)(verticeStart + 7);
// Left
indices[12] = (indice_t)(verticeStart + 4);
indices[13] = (indice_t)(verticeStart + 0);
indices[14] = (indice_t)(verticeStart + 2);
indices[15] = (indice_t)(verticeStart + 4);
indices[16] = (indice_t)(verticeStart + 6);
indices[17] = (indice_t)(verticeStart + 2);
// Front
indices[18] = (indice_t)(verticeStart + 5);
indices[19] = (indice_t)(verticeStart + 4);
indices[20] = (indice_t)(verticeStart + 6);
indices[21] = (indice_t)(verticeStart + 5);
indices[22] = (indice_t)(verticeStart + 7);
indices[23] = (indice_t)(verticeStart + 6);
// Top
indices[24] = (indice_t)(verticeStart + 7);
indices[25] = (indice_t)(verticeStart + 2);
indices[26] = (indice_t)(verticeStart + 6);
indices[27] = (indice_t)(verticeStart + 7);
indices[28] = (indice_t)(verticeStart + 3);
indices[29] = (indice_t)(verticeStart + 2);
// Bottom
indices[30] = (indice_t)(verticeStart + 1);
indices[31] = (indice_t)(verticeStart + 0);
indices[32] = (indice_t)(verticeStart + 4);
indices[33] = (indice_t)(verticeStart + 1);
indices[34] = (indice_t)(verticeStart + 4);
indices[35] = (indice_t)(verticeStart + 5);
primitiveBufferVertices(prim, verticeStart, CUBE_VERTICE_COUNT, vertices);
primitiveBufferIndices(prim, indiceStart, CUBE_INDICE_COUNT, indices);
}
void cubeInit(primitive_t *primitive, float w, float h, float d) {
primitiveInit(primitive, CUBE_VERTICE_COUNT, CUBE_INDICE_COUNT);
cubeBuffer(primitive,
-w/2, -h/2, -d/2,
w, h, d,
0, 0
);
}

View File

@ -1,38 +0,0 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "../../libs.h"
#include "primitive.h"
#define CUBE_VERTICE_COUNT 8
#define CUBE_INDICE_COUNT 36
/**
* Buffer the vertices and indices of a cube onto a primitive.
* @param primitive Primitive to buffer to.
* @param x X position of the cube.
* @param y Y position of the cube.
* @param z Z position of the cube.
* @param w Width of cube.
* @param h Height of cube.
* @param d Depth of cube.
* @param verticeStart The position of the vertex buffer to buffer into.
* @param indiceStart The position of the index buffer to buffer into.
*/
void cubeBuffer(primitive_t *primitive,
float x, float y, float z,
float w, float h, float d,
int32_t verticeStart, int32_t indiceStart
);
/**
* Creates a cube primitive of given size.
* @param primitive Primitive to create into a cube.
* @param w Width of cube.
* @param h Height of cube.
* @param d Depth of cube.
*/
void cubeInit(primitive_t *primitive, float w, float h, float d);

View File

@ -1,154 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "primitive.h"
void primitiveInit(primitive_t *primitive,
int32_t verticeCount, int32_t indiceCount
) {
ASSERT_NOT_NULL(primitive);
ASSERT_GREATER_THAN(verticeCount, 0);
ASSERT_GREATER_THAN(indiceCount, 0);
primitive->verticeCount = verticeCount;
primitive->indiceCount = indiceCount;
// size_t sizeIndices = sizeof(uint32_t) * verticeCount;
size_t sizePositions = sizeof(float) * verticeCount * PRIMITIVE_POSITIONS_PER_VERTICE;
size_t sizeCoordinates = sizeof(float) * verticeCount * PRIMITIVE_COORDINATES_PER_VERTICE;
size_t sizeIndices = sizeof(indice_t) * indiceCount;
// Create some buffers, one for the vertex data, one for the indices
GLuint buffer[2];
glGenBuffers(2, buffer);
primitive->vertexBuffer = buffer[0];
primitive->indexBuffer = buffer[1];
// Buffer an empty set of data then buffer each component
glBindBuffer(GL_ARRAY_BUFFER, primitive->vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, primitive->indexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizePositions+sizeCoordinates, 0, GL_DYNAMIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeIndices, 0, GL_DYNAMIC_DRAW);
size_t offset = 0;
// Setup the attrib pointers
glVertexAttribPointer(0, PRIMITIVE_POSITIONS_PER_VERTICE, GL_FLOAT,
GL_FALSE, 0, (void *)offset
);
glEnableVertexAttribArray(0);
offset += sizePositions;
glVertexAttribPointer(1, PRIMITIVE_COORDINATES_PER_VERTICE, GL_FLOAT,
GL_FALSE, 0, (void *)offset
);
glEnableVertexAttribArray(1);
}
void primitiveBufferVertices(primitive_t *primitive,
int32_t position, int32_t count, vertice_t *vertices
) {
// Memory
size_t lengthPositions, lengthCoordinates, offsetPositions, offsetCoordinates;
float *positions, *coordinates;
int32_t i;
ASSERT_NOT_NULL(primitive);
ASSERT_NOT_NULL(vertices);
ASSERT_GREATER_THAN_EQUAL_TO(position, 0);
ASSERT_GREATER_THAN(count, 0);
// Setup the size of the memory that the positions and coordinates will use
lengthPositions = sizeof(float) * PRIMITIVE_POSITIONS_PER_VERTICE * count;
offsetPositions = sizeof(float) * PRIMITIVE_POSITIONS_PER_VERTICE * position;
lengthCoordinates = sizeof(float) * PRIMITIVE_COORDINATES_PER_VERTICE * count;
offsetCoordinates = (
(sizeof(float) * PRIMITIVE_POSITIONS_PER_VERTICE * primitive->verticeCount)+
(sizeof(float) * PRIMITIVE_COORDINATES_PER_VERTICE * position)
);
// Create some memory
positions = malloc(lengthPositions);
ASSERT_NOT_NULL(positions);
coordinates = malloc(lengthCoordinates);
ASSERT_NOT_NULL(coordinates);
// Now copy the positions and coordinates from the vertices into the buffer
for(i = 0; i < count; i++) {
positions[i * PRIMITIVE_POSITIONS_PER_VERTICE] = vertices[i].x;
positions[i * PRIMITIVE_POSITIONS_PER_VERTICE + 1] = vertices[i].y;
positions[i * PRIMITIVE_POSITIONS_PER_VERTICE + 2] = vertices[i].z;
coordinates[i * PRIMITIVE_COORDINATES_PER_VERTICE] = vertices[i].u;
coordinates[i * PRIMITIVE_COORDINATES_PER_VERTICE + 1] = vertices[i].v;
}
// Buffer the data into the GPU
glBindBuffer(GL_ARRAY_BUFFER, primitive->vertexBuffer);
glBufferSubData(GL_ARRAY_BUFFER, offsetPositions, lengthPositions, positions);
glBufferSubData(GL_ARRAY_BUFFER, offsetCoordinates, lengthCoordinates, coordinates);
// Free the vertices.
free(positions);
free(coordinates);
}
void primitiveBufferIndices(primitive_t *primitive,
int32_t position, int32_t count, indice_t *indices
) {
size_t length, offset;
offset = position * sizeof(indice_t);
length = count * sizeof(indice_t);
ASSERT_NOT_NULL(primitive);
ASSERT_NOT_NULL(indices);
ASSERT_GREATER_THAN_EQUAL_TO(position, 0);
ASSERT_GREATER_THAN(count, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, primitive->indexBuffer);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, length, indices);
}
void primitiveDraw(primitive_t *primitive, int32_t start, int32_t count) {
ASSERT_NOT_NULL(primitive);
ASSERT_GREATER_THAN_EQUAL_TO(start, 0);
ASSERT_IF(count < 0, ASSERT_EQUAL(count, -1));
if(count == -1) count = primitive->indiceCount;
// Re-Bind the buffers
glBindBuffer(GL_ARRAY_BUFFER, primitive->vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, primitive->indexBuffer);
// Re-Calculate the attrib pointers.
size_t offset = 0;
glVertexAttribPointer(0, PRIMITIVE_POSITIONS_PER_VERTICE, GL_FLOAT,
GL_FALSE, 0, (void *)offset
);
glEnableVertexAttribArray(0);
offset += sizeof(float) * primitive->verticeCount * PRIMITIVE_POSITIONS_PER_VERTICE;
glVertexAttribPointer(1, PRIMITIVE_COORDINATES_PER_VERTICE, GL_FLOAT,
GL_FALSE, 0, (void *)offset
);
glEnableVertexAttribArray(1);
// Render the elements.
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, (void *)(
sizeof(indice_t)*start
));
}
void primitiveDispose(primitive_t *primitive) {
ASSERT_NOT_NULL(primitive);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &primitive->vertexBuffer);
glDeleteBuffers(1, &primitive->indexBuffer);
}

View File

@ -1,83 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../../libs.h"
#include "../../assert/assert.h"
#define PRIMITIVE_POSITIONS_PER_VERTICE 3
#define PRIMITIVE_COORDINATES_PER_VERTICE 2
/** Structure containing information about a primitive */
typedef struct {
/** How many vertices are in the primitive */
int32_t verticeCount;
/** How many indices are in the primitive */
int32_t indiceCount;
/** Pointer to the vertex buffer on the GPU */
GLuint vertexBuffer;
/** Pointer to the index buffer on the GPU */
GLuint indexBuffer;
} primitive_t;
/** Structure containing vertice position information */
typedef struct {
/** Coordinates */
float x, y, z;
/** Texture UVs */
float u, v;
} vertice_t;
/** Indice that references a specific vertice */
typedef unsigned int indice_t;
/**
* Creates a new primitive.
* @param primitive Primitive to initialize.
* @param verticeCount How many vertices can the primitive hold.
* @param indiceCount How many indices can the primitive hold.
*/
void primitiveInit(primitive_t *primitive,
int32_t verticeCount, int32_t indiceCount
);
/**
* Buffer Vertices to a primitive for use in rendering.
* @param primitive The primitive to buffer vertices into.
* @param position The position (index) to overwrite the vertices of.
* @param count The count of vertices to buffer.
* @param vertices Array of vertices to buffer into the primitive.
*/
void primitiveBufferVertices(primitive_t *primitive,
int32_t position, int32_t count, vertice_t *vertices
);
/**
* Buffer Indices to a primitive for use in rendering.
* @param primitive The primitive to buffer indices into.
* @param position The position (index) to overwrite the indices of.
* @param count The count of indices to buffer.
* @param indices Array of indices to buffer into the primitive.
*/
void primitiveBufferIndices(primitive_t *primitive,
int32_t position, int32_t count, indice_t *indices
);
/**
* Draw a primitive. Primitives are drawn by their indices.
* @param primitive Primitive to draw.
* @param start Start indice (index) to draw.
* @param count Count of indices to draw. Use -1 to draw all.
*/
void primitiveDraw(primitive_t *primitive, int32_t start, int32_t count);
/**
* Cleanup a previously initialized primitive.
* @param primitive Primitive to cleanup.
*/
void primitiveDispose(primitive_t *primitive);

View File

@ -1,53 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "quad.h"
void quadBuffer(primitive_t *primitive, float z,
float x0, float y0, float u0, float v0,
float x1, float y1, float u1, float v1,
int32_t verticeStart, int32_t indiceStart
) {
vertice_t vertices[QUAD_VERTICE_COUNT];
indice_t indices[QUAD_INDICE_COUNT];
vertices[0].x = x0, vertices[0].y = y0, vertices[0].z = z;
vertices[0].u = u0, vertices[0].v = v0;
vertices[1].x = x1, vertices[1].y = y0, vertices[1].z = z;
vertices[1].u = u1, vertices[1].v = v0;
vertices[2].x = x0, vertices[2].y = y1, vertices[2].z = z;
vertices[2].u = u0, vertices[2].v = v1;
vertices[3].x = x1, vertices[3].y = y1, vertices[3].z = z;
vertices[3].u = u1, vertices[3].v = v1;
indices[0] = (indice_t)(verticeStart + 0);
indices[1] = (indice_t)(verticeStart + 1);
indices[2] = (indice_t)(verticeStart + 2);
indices[3] = (indice_t)(verticeStart + 1);
indices[4] = (indice_t)(verticeStart + 2);
indices[5] = (indice_t)(verticeStart + 3);
primitiveBufferVertices(primitive, verticeStart,QUAD_VERTICE_COUNT,vertices);
primitiveBufferIndices(primitive, indiceStart, QUAD_INDICE_COUNT, indices );
}
void quadInit(primitive_t *primitive, float z,
float x0, float y0, float u0, float v0,
float x1, float y1, float u1, float v1
) {
primitiveInit(primitive, QUAD_VERTICE_COUNT, QUAD_INDICE_COUNT);
quadBuffer(primitive, z,
x0, y0, u0, v0,
x1, y1, u1, v1,
0, 0
);
}

View File

@ -1,53 +0,0 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "../../libs.h"
#include "primitive.h"
#define QUAD_VERTICE_COUNT 4
#define QUAD_INDICE_COUNT 6
#define QUAD_INDICE_PER_QUAD 2
/**
* Buffers the vertices of a quad onto a primitive.
*
* @param primitive The primitive to buffer to.
* @param z The Z axis coordinate of the quad.
* @param x0 The X lower coordinate.
* @param y0 The Y lower coordinate.
* @param u0 The X lower texture coordinate.
* @param v0 The Y lower texture coordinate.
* @param x1 The X higher coordinate.
* @param y1 The Y higher coordinate.
* @param u1 The X higher texture coordinate.
* @param v1 The Y higher texture coordinate.
* @param verticeStart Start vertice to buffer to.
* @param indiceStart Start indice to buffer to.
*/
void quadBuffer(primitive_t *primitive, float z,
float x0, float y0, float u0, float v0,
float x1, float y1, float u1, float v1,
int32_t verticeStart, int32_t indiceStart
);
/**
* Creates a new quad primitive.
*
* @param primitive Primitive to turn into a quad.
* @param z The Z axis coordinate of the quad.
* @param x0 The X lower coordinate.
* @param y0 The Y lower coordinate.
* @param u0 The X lower texture coordinate.
* @param v0 The Y lower texture coordinate.
* @param x1 The X higher coordinate.
* @param y1 The Y higher coordinate.
* @param u1 The X higher texture coordinate.
* @param v1 The Y higher texture coordinate.
*/
void quadInit(primitive_t *primitive, float z,
float x0, float y0, float u0, float v0,
float x1, float y1, float u1, float v1
);

View File

@ -1,58 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "skywall.h"
void skywallInit(primitive_t *primitive) {
vertice_t vertices[SKYWALL_VERTICE_COUNT];
indice_t indices[SKYWALL_INDICE_COUNT];
int32_t n, i, j;
float x, y, z, p, r;
primitiveInit(primitive, SKYWALL_VERTICE_COUNT, SKYWALL_INDICE_COUNT);
// For each slice. We iterate slices+1 to do the wrapping mentioned below.
for(i = 0; i < SKYWALL_SLICE_COUNT+1; i++) {
// Get the "percentage" of the current slice, slice 0 is 0, slice n is 1
p = (float)i/(float)SKYWALL_SLICE_COUNT;
// Because we we are to "seal the cylinder" we wrap around back to 0 on the
// last slice to have the last vertice meet the first.
if(SKYWALL_SLICE_COUNT == i) {
r = 0;
} else {
r = p * MATH_PI * 2.0f;// Convert % to radians
}
r += mathDeg2Rad(90);
// Determine the X/Z for the given radian
x = SKYWALL_SIZE * (float)cos(r);
z = SKYWALL_SIZE * (float)sin(r);
y = SKYWALL_SIZE * 1;
// Get the start index for the ertices
n = i * SKYWALL_VERTICES_PER_SLICE;
vertices[n].x = x, vertices[n].y = -y, vertices[n].z = z;
vertices[n].u = p, vertices[n].v = 1;
vertices[n+1].x = x, vertices[n+1].y = y, vertices[n+1].z = z;
vertices[n+1].u = p, vertices[n+1].v = 0;
if(i == SKYWALL_SLICE_COUNT) continue;
j = i * SKYWALL_INDICES_PER_SLICE;
indices[j] = (indice_t)n;
indices[j+1] = (indice_t)n+1;
indices[j+2] = (indice_t)n+2;
indices[j+3] = (indice_t)n+3;
indices[j+4] = (indice_t)n+2;
indices[j+5] = (indice_t)n+1;
}
primitiveBufferVertices(primitive, 0, SKYWALL_VERTICE_COUNT, vertices);
primitiveBufferIndices(primitive, 0, SKYWALL_INDICE_COUNT, indices);
}

View File

@ -1,29 +0,0 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "../../libs.h"
#include "../../util/math.h"
#include "primitive.h"
/** How many slices in each cylinder. */
#define SKYWALL_SLICE_COUNT 40
/** How many vertices per slice */
#define SKYWALL_VERTICES_PER_SLICE 2
/** How many indices per slice */
#define SKYWALL_INDICES_PER_SLICE 6
/** How many vertices in the cylinder, +1 to have the cylinder "wrap" */
#define SKYWALL_VERTICE_COUNT (SKYWALL_SLICE_COUNT+1)*SKYWALL_VERTICES_PER_SLICE
/** How many indices in the cylinder */
#define SKYWALL_INDICE_COUNT SKYWALL_INDICES_PER_SLICE*SKYWALL_SLICE_COUNT
/** How big the skywall cylinder is */
#define SKYWALL_SIZE 10
void skywallInit(primitive_t *primitive);

View File

@ -1,47 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "render.h"
void renderInit() {
// Enable GL things.
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
// Setup the alpha blend function.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glClearColor(0,0,0, 0.0);
}
void renderFrameStart(render_t *render) {
// Clear the frame buffer.
renderResetFramebuffer(render);
}
void renderDispose() {
}
void renderSetResolution(render_t *render, float width, float height) {
ASSERT_NOT_NULL(render);
ASSERT_GREATER_THAN(width, 0);
ASSERT_GREATER_THAN(height, 0);
render->width = width;
render->height = height;
}
void renderResetFramebuffer(render_t *render) {
ASSERT_NOT_NULL(render);
frameBufferUnbind(render->width, render->height, true);
}

View File

@ -1,51 +0,0 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "../libs.h"
#include "../assert/assert.h"
#include "framebuffer.h"
/**
* Contains information about the current render state, can be used for querying
* how the renderer is currently set up.
*/
typedef struct {
/** Resolution (in pixels). Floats to allow subpixels in future. */
float width, height;
} render_t;
/**
* Initialize the renderer.
*/
void renderInit();
/**
* Render a single frame of the render loop. The renderer is not (currently)
* responsible for render looping.
* @param render The render manager
*/
void renderFrameStart(render_t *render);
/**
* Cleanup a render context.
*/
void renderDispose();
/**
* Sets the internal display resolution.
*
* @param render Render context to resize.
* @param width Width of the display (in pixels).
* @param height Height of the display (in pixels).
*/
void renderSetResolution(render_t *render, float width, float height);
/**
* Reset the framebuffer back to the original backbuffer.
*
* @param render Render to reset the backbuffer to.
*/
void renderResetFramebuffer(render_t *render);

View File

@ -1,107 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "renderlist.h"
void renderListInit(renderlist_t *list,int32_t width, int32_t height) {
frameBufferInit(&list->frame, width, height);
quadInit(&list->quad, 0, 0,0,0,0, 1,1,1,1);
list->passCount = 0;
}
renderpass_t * renderListGetPass(renderlist_t *list, uint8_t pass) {
return list->passes + pass;
}
uint8_t renderPassAdd(renderlist_t *list, shaderprogram_t *shader) {
uint8_t i;
renderpass_t *pass;
i = list->passCount++;
pass = renderListGetPass(list, i);
pass->shader = shader;
frameBufferInit(&pass->frame,
list->frame.texture.width, list->frame.texture.height
);
return i;
}
renderpass_t * renderListRenderPass(
renderlist_t *list, engine_t *engine, uint8_t pass
) {
renderpass_t *renderPass;
renderPass = renderListGetPass(list, pass);
// Bind the shader.
frameBufferUse(&renderPass->frame, true);
shaderUse(renderPass->shader);
return renderPass;
}
void renderListRender(renderlist_t *list, renderlistbackshader_t *backShader) {
camera_t camera;
int32_t i;
renderpass_t *pass;
matrix_t matrix;
// Setup the camera
cameraLookAt(&camera, 0,0,1, 0,0,0);
cameraOrtho(&camera, 0,1, 0,1, 0.5f, 1.5f);
// Bind the framebuffer
frameBufferUse(&list->frame, true);
// Set the shader
shaderUse(backShader->program);
shaderUseCamera(
backShader->program, backShader->uniformView,
backShader->uniformProjection, &camera
);
matrix = matrixPositionAndScale(0,0,0, 0,0,0, 1,1,1);
shaderUseMatrix(backShader->program, backShader->uniformPosition, &matrix);
// Render each pass.
for(i = 0; i < list->passCount; i++) {
pass = renderListGetPass(list, i);
textureBind(&pass->frame.texture, i);
shaderUseTexture(backShader->program, backShader->uniformTexture[i], i);
}
primitiveDraw(&list->quad, 0, -1);
}
void renderListResize(renderlist_t *list, int32_t width, int32_t height) {
uint8_t i;
if(
width == list->frame.texture.width &&
height == list->frame.texture.height
) return;
frameBufferDispose(&list->frame);
frameBufferInit(&list->frame, width, height);
for(i = 0; i < list->passCount; i++) {
frameBufferDispose(&list->passes[i].frame);
frameBufferInit(&list->passes[i].frame, width, height);
}
}
void renderListDispose(renderlist_t *list) {
uint8_t i;
for(i = 0; i < list->passCount; i++) {
frameBufferDispose(&list->passes[i].frame);
}
frameBufferDispose(&list->frame);
primitiveDispose(&list->quad);
}

View File

@ -1,109 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "framebuffer.h"
#include "primitive/primitive.h"
#include "shaderprogram.h"
#include "camera.h"
#include "../engine/engine.h"
#include "primitive/quad.h"
#include "../util/dynarray.h"
#include "render.h"
#define RENDER_PASSES_MAX 8
typedef struct {
framebuffer_t frame;
shaderprogram_t *shader;
} renderpass_t;
typedef struct {
framebuffer_t frame;
primitive_t quad;
renderpass_t passes[RENDER_PASSES_MAX];
uint8_t passCount;
} renderlist_t;
typedef struct {
shaderprogram_t *program;
shaderuniform_t uniformView;
shaderuniform_t uniformPosition;
shaderuniform_t uniformProjection;
shaderuniform_t uniformTexture[RENDER_PASSES_MAX];
} renderlistbackshader_t;
/**
* Initialize a render pass list.
*
* @param list List to initialize.
* @param width Width of the frame buffer(s).
* @param height Height of the frame buffer(s).
*/
void renderListInit(renderlist_t *list, int32_t width, int32_t height);
/**
* Retrieve the render pass at the given index.
*
* @param list List to get the pass from.
* @param pass Render pass index to get.
* @return The render pass at the given index.
*/
renderpass_t * renderListGetPass(renderlist_t *list, uint8_t pass);
/**
* Adds a render pass to the render list.
*
* @param list Render list to add the pass to.
* @param shader Shader to use for the render pass.
* @return The render pass index.
*/
uint8_t renderPassAdd(renderlist_t *list, shaderprogram_t *shader);
/**
* Prepare the rendering for a specific render pass. This will set up the
* render pass framebuffer, shader and prepare it for rendering.
*
* @param list List to get the render pass from.
* @param engine Game engine for the render pass.
* @param pass Pass index to render.
* @return The pointer to the render pass that is now active.
*/
renderpass_t * renderListRenderPass(
renderlist_t *list, engine_t *engine, uint8_t pass
);
/**
* Render a render list. The render list will provide the sum of the textures to
* the given shader as uniforms and then call a single render against a textured
* quad. The given shader will need to decide how to multiply the provided
* texture indexes.
*
* @param list List to render.
* @param backShader Shader to use while rendering.
*/
void renderListRender(renderlist_t *list, renderlistbackshader_t *backShader);
/**
* Resize an existing render list and all its render pass frame buffers. This
* will dispose (and clear) the existing frame buffers for both the list and
* each of the passes. Resizing to the same size won't cause an update to occur.
*
* @param list List to update.
* @param width New render list width.
* @param height New render list height.
*/
void renderListResize(renderlist_t *list, int32_t width, int32_t height);
/**
* Dispose a render list entirely.
*
* @param list Render list to dispose.
*/
void renderListDispose(renderlist_t *list);

View File

@ -1,142 +0,0 @@
/**
* Copyright (c) 2021 Dominic Msters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "shaderprogram.h"
void shaderInit(shaderprogram_t *shader,
char *vertexShaderSource, char* fragmentShaderSource
) {
int isSuccess, maxLength;
char *error;
GLuint shaderVertex, shaderFragment, shaderProgram;
ASSERT_NOT_NULL(shader);
ASSERT_NOT_NULL(vertexShaderSource);
ASSERT_NOT_NULL(fragmentShaderSource);
// Load the vertex shader first
shaderVertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(shaderVertex, 1, &vertexShaderSource, 0);
glCompileShader(shaderVertex);
// Validate
glGetShaderiv(shaderVertex, GL_COMPILE_STATUS, &isSuccess);
if(!isSuccess) {
glGetShaderiv(shaderVertex, GL_INFO_LOG_LENGTH, &maxLength);
error = malloc(maxLength);
glGetShaderInfoLog(shaderVertex, maxLength, &maxLength, error);
printf("Failed to compile vertex shader %s\n", error);
free(error);
return;
}
// Now load the Frag shader
shaderFragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(shaderFragment, 1, &fragmentShaderSource, 0);
glCompileShader(shaderFragment);
glGetShaderiv(shaderFragment, GL_COMPILE_STATUS, &isSuccess);
if(!isSuccess) {
glGetShaderiv(shaderFragment, GL_INFO_LOG_LENGTH, &maxLength);
error = malloc(maxLength);
glGetShaderInfoLog(shaderFragment, maxLength, &maxLength, error);
printf("Failed to compile fragment shader %s\n", error);
free(error);
glDeleteShader(shaderVertex);
return;
}
// Now create the shader program.
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, shaderVertex);
glAttachShader(shaderProgram, shaderFragment);
//Bind, Verify & Use the shader program
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &isSuccess);
if(!isSuccess) {
glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &maxLength);
error = malloc(maxLength);
glGetProgramInfoLog(shaderProgram, maxLength, &maxLength, error);
printf("Failed to load shader program %s\n", error);
free(error);
glDeleteShader(shaderVertex);
glDeleteShader(shaderFragment);
return;
}
// Everything is okay, let's create the encapsulated shader.
shader->shaderVertex = shaderVertex;
shader->shaderFrag = shaderFragment;
shader->shaderProgram = shaderProgram;
// Bind the shader
shaderUse(shader);
}
void shaderDispose(shaderprogram_t *shader) {
ASSERT_NOT_NULL(shader);
glDeleteProgram(shader->shaderProgram);
glDeleteShader(shader->shaderVertex);
glDeleteShader(shader->shaderFrag);
}
void shaderUse(shaderprogram_t *shader) {
ASSERT_NOT_NULL(shader);
glUseProgram(shader->shaderProgram);
}
void shaderUseCamera(
shaderprogram_t *shader, shaderuniform_t uniformView,
shaderuniform_t uniformProjection, camera_t *camera
) {
ASSERT_NOT_NULL(shader);
ASSERT_NOT_NULL(camera);
ASSERT_GREATER_THAN_EQUAL_TO(uniformView, 0);
ASSERT_GREATER_THAN_EQUAL_TO(uniformProjection, 0);
shaderUseMatrix(shader, uniformView, &camera->view);
shaderUseMatrix(shader, uniformProjection, &camera->projection);
}
void shaderUseTexture(
shaderprogram_t *shader, shaderuniform_t uniform, textureslot_t slot
) {
ASSERT_NOT_NULL(shader);
ASSERT_GREATER_THAN_EQUAL_TO(uniform, 0);
ASSERT_GREATER_THAN_EQUAL_TO(slot, 0);
ASSERT_LESS_THAN(slot, TEXTURE_SLOTS_MAX);
glUniform1i(uniform, slot);
}
void shaderUseMatrix(
shaderprogram_t *shader, shaderuniform_t uniform, matrix_t *matrix
) {
ASSERT_NOT_NULL(shader);
ASSERT_NOT_NULL(matrix);
ASSERT_GREATER_THAN_EQUAL_TO(uniform, 0);
glUniformMatrix4fv(uniform, 1, GL_FALSE, matrix->internalMatrix[0]);
}
void shaderUseColor(
shaderprogram_t *shader, shaderuniform_t uniform, pixel_t color
) {
ASSERT_NOT_NULL(shader);
ASSERT_GREATER_THAN_EQUAL_TO(uniform, 0);
glUniform4f(uniform,
(float)color.r / 255.0f,
(float)color.g / 255.0f,
(float)color.b / 255.0f,
(float)color.a / 255.0f
);
}
shaderuniform_t shaderGetUniformByName(shaderprogram_t *sp, const char *name) {
ASSERT_NOT_NULL(sp);
ASSERT_NOT_NULL(name);
return glGetUniformLocation(sp->shaderProgram, name);
}

View File

@ -1,111 +0,0 @@
/**
* Copyright (c) 2021 Dominic Msters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "../assert/assert.h"
#include "matrix.h"
#include "camera.h"
#include "texture.h"
/** Representation of a shader uniform */
typedef GLuint shaderuniform_t;
/**
* Structure containing information about an OpenGL Shader. For simplicity sake
* we demand certain uninforms to be present on the shader target.
*/
typedef struct {
/** Pointer to an uploaded vertex shader program */
shaderuniform_t shaderVertex;
/** Pointer to an uploaded fragment shader program */
shaderuniform_t shaderFrag;
/** Pointer to an uploaded shader program linked */
shaderuniform_t shaderProgram;
} shaderprogram_t;
/**
* Compiles a shader from vertex and fragment shader code.
*
* @param shader Shader to compile into.
* @param vertexShaderSource The raw vertex shader code.
* @param fragmentShaderSource The raw fragment shader code.
*/
void shaderInit(shaderprogram_t *shader,
char *vertexShaderSource, char* fragmentShaderSource
);
/**
* Cleanup and unload a previously loaded shader.
*
* @param shader The shader to unload
*/
void shaderDispose(shaderprogram_t *shader);
/**
* Attaches the supplied shader as the current shader.
*
* @param shader The shader to attach
*/
void shaderUse(shaderprogram_t *shader);
/**
* Attaches a camera to the shader.
*
* @param shader Shader to attach to.
* @param uniformView Uniform for the view matrix
* @param uniformProjection Uniform for the projection matrix.
* @param camera Camera to attach.
*/
void shaderUseCamera(
shaderprogram_t *shader, shaderuniform_t uniformView,
shaderuniform_t uniformProjection, camera_t *camera
);
/**
* Attaches a texture to the shader.
*
* @param shader Shader to attach to.
* @param uniform Uniform to set the texture on to.
* @param slot Which texture slot to bind to the uniform.
*/
void shaderUseTexture(
shaderprogram_t *shader, shaderuniform_t uniform, textureslot_t slot
);
/**
* Set's a specific shader uniform to a matrix.
*
* @param shader Shader to apply to.
* @param uniform Uniform on the shader to set.
* @param matrix Matrix to apply.
*/
void shaderUseMatrix(
shaderprogram_t *shader, shaderuniform_t uniform, matrix_t *matrix
);
/**
* Set a color on to the shader.
*
* @param shader Shader to set the color on to.
* @param uniform Uniform to set the color to.
* @param color Color to set.
*/
void shaderUseColor(
shaderprogram_t *shader, shaderuniform_t uniform, pixel_t color
);
/**
* Locate a shader uniform by its name.
*
* @param sp Shader program to get the uniform for.
* @param name Name of the uniform to get.
* @return The shader uniform.
*/
shaderuniform_t shaderGetUniformByName(shaderprogram_t *sp, const char *name);

View File

@ -1,10 +0,0 @@
# Copyright (c) 2022 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${PROJECT_NAME}
PRIVATE
standardshader.c
)

View File

@ -1,116 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "standardshader.h"
void _standardShaderUpdateUniforms(standardshader_t *stds) {
shaderprogram_t *sp;
ASSERT_NOT_NULL(stds);
sp = STANDARD_SHADER_SHADER(stds);
stds->uniformView = shaderGetUniformByName(
sp, STANDARD_SHADER_UNIFORM_NAME_VIEW
);
stds->uniformProjection = shaderGetUniformByName(
sp, STANDARD_SHADER_UNIFORM_NAME_PROJ
);
stds->uniformTexture = shaderGetUniformByName(
sp, STANDARD_SHADER_UNIFORM_NAME_TEXT
);
stds->uniformColor = shaderGetUniformByName(
sp, STANDARD_SHADER_UNIFORM_NAME_COLOR
);
stds->uniformPosition = shaderGetUniformByName(
sp, STANDARD_SHADER_UNIFORM_NAME_MODEL
);
}
bool _standardShaderOnAssetItemLoaded(
void *u, event_t e, const void *s[], const int32_t c
) {
standardshader_t *ss = (standardshader_t *)u;
ASSERT_NOT_NULL(ss);
ASSERT_EQUAL(e, ASSET_MANAGER_EVENT_ITEM_LOADED);
ASSERT_NOT_NULL(s);
ASSERT_EQUAL(c, 2);
if(s[1] != ss->shaderProgram) return true;
eventManagerUnsubscribe(&((assetmanager_t *)s[0])->events, ss->onItemLoaded);
_standardShaderUpdateUniforms(ss);
return true;
}
void standardShaderInit(standardshader_t *stds, assetmanager_t *assetManager) {
ASSERT_NOT_NULL(stds);
ASSERT_NOT_NULL(assetManager);
// Begin loading the shader.
stds->holder = assetManagerHolderCreate(assetManager);
stds->shaderProgram = assetManagerLoadShader(
assetManager, stds->holder,
STANDARD_SHARER_FILE_VERTEX, STANDARD_SHADER_FILE_FRAGMENT
);
// Update uniforms
if(assetManagerItemIsFinished(stds->shaderProgram)) {
_standardShaderUpdateUniforms(stds);
} else {
stds->onItemLoaded = eventManagerSubscribe(
&assetManager->events, ASSET_MANAGER_EVENT_ITEM_LOADED,
stds, &_standardShaderOnAssetItemLoaded
);
}
}
void standardShaderUse(standardshader_t *stds) {
ASSERT_NOT_NULL(stds);
if(!assetManagerItemIsFinished(stds->shaderProgram)) return;
shaderUse(STANDARD_SHADER_SHADER(stds));
}
void standardShaderSetCamera(standardshader_t *stds, camera_t *camera) {
ASSERT_NOT_NULL(stds);
ASSERT_NOT_NULL(camera);
if(!assetManagerItemIsFinished(stds->shaderProgram)) return;
shaderUseCamera(STANDARD_SHADER_SHADER(stds),
stds->uniformView, stds->uniformProjection, camera
);
}
void standardShaderSetTexture(standardshader_t *stds, texture_t *texture) {
ASSERT_NOT_NULL(stds);
ASSERT_NOT_NULL(texture);
if(!assetManagerItemIsFinished(stds->shaderProgram)) return;
textureBind(texture, 0);
shaderUseTexture(STANDARD_SHADER_SHADER(stds), stds->uniformTexture, 0);
}
void standardShaderSetColor(standardshader_t *stds, pixel_t color) {
ASSERT_NOT_NULL(stds);
if(!assetManagerItemIsFinished(stds->shaderProgram)) return;
shaderUseColor(STANDARD_SHADER_SHADER(stds), stds->uniformColor, color);
}
void standardShaderSetPosition(standardshader_t *stds, matrix_t *matrix) {
ASSERT_NOT_NULL(stds);
ASSERT_NOT_NULL(matrix);
if(!assetManagerItemIsFinished(stds->shaderProgram)) return;
shaderUseMatrix(STANDARD_SHADER_SHADER(stds), stds->uniformPosition, matrix);
}
void standardShaderDispose(standardshader_t *stds, assetmanager_t *assMan) {
ASSERT_NOT_NULL(stds);
ASSERT_NOT_NULL(assMan);
assetManagerHolderRelease(assMan, stds->holder);
}

View File

@ -1,91 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../../libs.h"
#include "../../assert/assert.h"
#include "../../engine/event.h"
#include "../shaderprogram.h"
#include "../../file/assetmanager.h"
#define STANDARD_SHADER_UNIFORM_NAME_VIEW "u_View"
#define STANDARD_SHADER_UNIFORM_NAME_PROJ "u_Proj"
#define STANDARD_SHADER_UNIFORM_NAME_TEXT "u_Text"
#define STANDARD_SHADER_UNIFORM_NAME_MODEL "u_Model"
#define STANDARD_SHADER_UNIFORM_NAME_COLOR "u_Color"
#define STANDARD_SHARER_FILE_VERTEX "shaders/textured.vert"
#define STANDARD_SHADER_FILE_FRAGMENT "shaders/textured.frag"
#define STANDARD_SHADER_SHADER(ss) (&ss->shaderProgram->data.shader.shader)
typedef struct {
assetmanageritem_t *shaderProgram;
assetmanagerholder_t holder;
eventlistener_t *onItemLoaded;
shaderuniform_t uniformView;
shaderuniform_t uniformProjection;
shaderuniform_t uniformPosition;
shaderuniform_t uniformTexture;
shaderuniform_t uniformColor;
} standardshader_t;
/**
* Initialize the standard shader.
*
* @param stds Standard Shader Instance.
* @param assetManager Asset Manager to load the shaders' assets.
*/
void standardShaderInit(standardshader_t *stds, assetmanager_t *assetManager);
/**
* Bind the standard shader as the currently active shader.
*
* @param stds Standard shader to bind.
*/
void standardShaderUse(standardshader_t *stds);
/**
* Set the camera for the standard shader.
*
* @param stds Standard shader instance.
* @param camera Camera to bind.
*/
void standardShaderSetCamera(standardshader_t *stds, camera_t *camera);
/**
* Set the texture for the standard shader.
*
* @param stds Standard shader instance.
* @param texture Texture to bind.
*/
void standardShaderSetTexture(standardshader_t *stds, texture_t *texture);
/**
* Set the color for the standard shader.
*
* @param stds Standard shader instance.
* @param color Color to bind.
*/
void standardShaderSetColor(standardshader_t *stds, pixel_t color);
/**
* Set the position matrix for the standard shader.
*
* @param stds Standard shader to use.
* @param matrix Matrix to use.
*/
void standardShaderSetPosition(standardshader_t *stds, matrix_t *matrix);
/**
* Dispose/cleanup the standard shader.
*
* @param stds Standard shader instance.
* @param assMan Asset manager instance.
*/
void standardShaderDispose(standardshader_t *stds, assetmanager_t *assMan);

View File

@ -1,49 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "spritebatch.h"
void spriteBatchInit(spritebatch_t *batch, int32_t maxSprites) {
batch->maxSprites = maxSprites;
batch->currentSprite = 0;
primitiveInit(&batch->primitive,
maxSprites*QUAD_VERTICE_COUNT, maxSprites*QUAD_INDICE_COUNT
);
}
void spriteBatchQuad(spritebatch_t *spriteBatch, int32_t index,
float x, float y, float z, float width, float height,
float u0, float v0, float u1, float v1
) {
if(index == -1) {
index = spriteBatch->currentSprite++;
} else {
spriteBatch->currentSprite = mathMax(index, spriteBatch->currentSprite);
}
quadBuffer(&spriteBatch->primitive, z,
x, y, u0, v0,
x+width, y+height, u1, v1,
index*QUAD_VERTICE_COUNT, index*QUAD_INDICE_COUNT
);
}
void spriteBatchFlush(spritebatch_t *spriteBatch) {
spriteBatch->currentSprite = 0;
}
void spriteBatchDraw(spritebatch_t *spriteBatch, int32_t index, int32_t count) {
if(count == -1) count = spriteBatch->currentSprite;
primitiveDraw(&spriteBatch->primitive,
index*QUAD_INDICE_COUNT, count*QUAD_INDICE_COUNT
);
}
void spriteBatchDispose(spritebatch_t *spriteBatch) {
primitiveDispose(&spriteBatch->primitive);
}

View File

@ -1,71 +0,0 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "../libs.h"
#include "../util/math.h"
#include "primitive/primitive.h"
#include "primitive/quad.h"
/** Definition of a Sprite Batch. */
typedef struct {
/** Maximum sprites the batch can hold. */
int32_t maxSprites;
/** The current/next sprite index. */
int32_t currentSprite;
/** Internal primitive */
primitive_t primitive;
} spritebatch_t;
/**
* Creates a new Sprite Batch made of standard quads.
*
* @param batch Sprite batch to init.
* @param maxSprites The maxiumum number of sprites the batch can hold.
*/
void spriteBatchInit(spritebatch_t *batch, int32_t maxSprites);
/**
* Renders a sprite onto a given Sprite Batch.
*
* @param spriteBatch The sprite batch to render to.
* @param index The index within the sprite batch. Set to -1 to select "next".
* @param x X coordinate of the sprite.
* @param y Y coordinate of the sprite.
* @param width Width of the sprite.
* @param height Height of the sprite.
* @param u0 Texture U coordinate (min).
* @param v0 Texture V coordinate (min).
* @param u1 Texture U coordinate (max).
* @param v1 Texture V coordinate (max).
*/
void spriteBatchQuad(spritebatch_t *spriteBatch, int32_t index,
float x, float y, float z, float width, float height,
float u0, float v0, float u1, float v1
);
/**
* Flushes a sprite batch to reset the indexes.
* @param spriteBatch The batch.
*/
void spriteBatchFlush(spritebatch_t *spriteBatch);
/**
* Draws the Sprite Batch.
*
* @param spriteBatch The sprite batch to render.
* @param start Start index to render from.
* @param count Count of sprites to render. Set to -1 to render to the current.
*/
void spriteBatchDraw(spritebatch_t *spriteBatch, int32_t start, int32_t count);
/**
* Disposes a previously created Sprite Batch.
*
* @param spriteBatch The sprite batch to dispose.
*/
void spriteBatchDispose(spritebatch_t *spriteBatch);

View File

@ -1,87 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "texture.h"
// Due to some compiler bullshit, this is here.
#ifndef STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#endif
void textureInit(texture_t *texture, int32_t width, int32_t height,
pixel_t *pixels
) {
ASSERT_NOT_NULL(texture);
ASSERT_GREATER_THAN(width, 0);
ASSERT_GREATER_THAN(height, 0);
texture->width = width;
texture->height = height;
// Generate a texture ID and bind.
glGenTextures(1, &texture->id);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture->id);
// Setup our preferred texture params
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Start by buffering all transparent black pixels.
if(pixels == NULL) {
// TODO: I can optimize this, I think the GPU can default this somehow
pixels = calloc(width * height, sizeof(pixel_t));
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, pixels
);
free(pixels);
} else {
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, pixels
);
}
textureBind(texture, 0x00);
}
void textureBind(texture_t *texture, textureslot_t slot) {
ASSERT_NOT_NULL(texture);
ASSERT_GREATER_THAN_EQUAL_TO(slot, 0);
ASSERT_LESS_THAN(slot, TEXTURE_SLOTS_MAX);
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, texture->id);
}
void textureBufferPixels(texture_t *texture,
int32_t x, int32_t y, int32_t width, int32_t height, pixel_t *pixels
) {
ASSERT_NOT_NULL(texture);
ASSERT_NOT_NULL(pixels);
ASSERT_GREATER_THAN_EQUAL_TO(x, 0);
ASSERT_GREATER_THAN_EQUAL_TO(y, 0);
ASSERT_GREATER_THAN(width, 0);
ASSERT_GREATER_THAN(height, 0);
ASSERT_LESS_THAN_EQUAL_TO(width, texture->width);
ASSERT_LESS_THAN_EQUAL_TO(height, texture->height);
glBindTexture(GL_TEXTURE_2D, texture->id);
glTexSubImage2D(GL_TEXTURE_2D, 0,
x, y, width, height,
GL_RGBA, GL_UNSIGNED_BYTE, pixels
);
}
void textureDispose(texture_t *texture) {
ASSERT_NOT_NULL(texture);
glDeleteTextures(1, &texture->id);
}

View File

@ -1,83 +0,0 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "../libs.h"
#include "../assert/assert.h"
#define TEXTURE_SLOTS_MAX 8
#define TEXTURE_CHANNELS 4
/** Texture slot that a texture can be bound to */
typedef GLuint textureslot_t;
/**
* Structure detailing information about a texture.
* Because we plan to upload the pixels of a texture into the GPU, we don't
* store the pixels in memory because we don't need to!
*/
typedef struct {
/** Width (in pixels) of the texture */
int32_t width;
/** Height (in pixels) of the texture */
int32_t height;
/** Texture ID on the GPU */
GLuint id;
} texture_t;
/** Information about a single pixel. */
typedef struct {
/** RGBA Color values */
uint8_t r, g, b, a;
} pixel_t;
#define PIXEL_COLOR_WHITE ((pixel_t){ .r = 255, .g = 255, .b = 255, .a = 255 })
#define PIXEL_COLOR_RED ((pixel_t){ .r = 255, .g = 0, .b = 0, .a = 255 })
#define PIXEL_COLOR_GREEN ((pixel_t){ .r = 0, .g = 255, .b = 0, .a = 255 })
#define PIXEL_COLOR_BLUE ((pixel_t){ .r = 0, .g = 0, .b = 255, .a = 255 })
#define PIXEL_COLOR_BLACK ((pixel_t){ .r = 0, .g = 0, .b = 0, .a = 255 })
#define PIXEL_COLOR_TRANSPARENT ((pixel_t){ .r = 0, .g = 0, .b = 0, .a = 0 })
/**
* Initializes a texture that can be written in to.
*
* @param texture Texture to initialize.
* @param width Width of the texture (in pixels).
* @param height Height of the texture (in pixels).
* @param pixels Default pixel array, set to NULL to set all pixel data to 0.
*/
void textureInit(texture_t *texture, int32_t width, int32_t height,
pixel_t *pixels
);
/**
* Bind a texture on to a given texture slot.
*
* @param texture Texture to bind.
* @param slot Slot to bind the texture to.
*/
void textureBind(texture_t *texture, textureslot_t slot);
/**
* Buffer pixel data onto the GPU. Pixel buffering is rather costly so avoid
* doing this too often.
*
* @param texture Texture to buffer in to.
* @param x X coordinate in texture space to render to.
* @param y Y coordinate in texture space to render to.
* @param width Width of the pixel region you're buffering.
* @param height Height of the pixel region you're buffering.
* @param pixels Array of pixels to buffer onto the GPU.
*/
void textureBufferPixels(texture_t *texture,
int32_t x, int32_t y, int32_t width, int32_t height, pixel_t *pixels
);
/**
* Clean a previously created texture.
*
* @param texture Texture to clean up.
*/
void textureDispose(texture_t *texture);

View File

@ -1,29 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "texture.h"
#define MANAGED_TEXTURE_SCALE_MAX 5
typedef struct {
int16_t width;
int16_t height;
uint8_t scale;
} texturescalescale_t;
typedef struct {
uint8_t channels;
const char *file;
const char *path;
int16_t baseWidth;
int16_t baseHeight;
texturescalescale_t scales[MANAGED_TEXTURE_SCALE_MAX];
uint8_t scaleCount;
} texturescale_t;

View File

@ -1,62 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "tileset.h"
void tilesetInit(tileset_t *tileset,
int32_t columns, int32_t rows,
int32_t width, int32_t height,
int32_t gapX, int32_t gapY,
int32_t borderX, int32_t borderY
) {
float tdivX, tdivY;
int32_t x, y, i;
tileset->count = rows * columns;
tileset->divisions = malloc(sizeof(tilesetdiv_t) * tileset->count);
tileset->columns = columns;
tileset->rows = rows;
// Calculate division sizes (pixels)
tileset->divX = (
(float)width - ((float)borderX * 2.0f) - ((float)gapX * ((float)columns-1))
) / columns;
tileset->divY = (
(float)height - ((float)borderY * 2.0f) - ((float)gapY * ((float)rows - 1))
) / rows;
// Calculate the division sizes (units)
tdivX = tileset->divX / width;
tdivY = tileset->divY / height;
// Calculate the divisions (in units)
i = -1;
for(y = 0; y < rows; y++) {
for(x = 0; x < columns; x++) {
tileset->divisions[++i].x0 = (
borderX + (tileset->divX * x) + (gapX * x)
) / width;
tileset->divisions[i].x1 = tileset->divisions[i].x0 + tdivX;
tileset->divisions[i].y0 = (
borderY + (tileset->divY * y) + (gapY * y)
) / height;
tileset->divisions[i].y1 = tileset->divisions[i].y0 + tdivY;
}
}
}
tilesetdiv_t tilesetGetDivision(tileset_t *tileset,int32_t column,int32_t row) {
return tileset->divisions[
(column % tileset->columns) + (row * tileset->columns)
];
}
void tilesetDispose(tileset_t *tileset) {
free(tileset->divisions);
}

View File

@ -1,64 +0,0 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "../libs.h"
/** Division of a texture */
typedef struct {
float x0, y0, x1, y1;
} tilesetdiv_t;
/** Definition of a Tileset */
typedef struct {
/** Count of X/Y divisions */
int32_t columns, rows;
/** Size of each divison (in pixels) */
float divX, divY;
/** Count of divisions (unused) */
int32_t count;
/** Division information */
tilesetdiv_t *divisions;
} tileset_t;
/**
* Create a tileset. Tilesets will be pre-divided to save performance later.
*
* @param tileset Tileset to init into.
* @param columns Count of columns.
* @param rows Count of rows.
* @param width Width of the tileset.
* @param height Height of the tileset.
* @param gapX Space between each column.
* @param gapY Space between each row.
* @param borderX Space around the edge of the tileset.
* @param borderY Space around the edge of the tileset.
*/
void tilesetInit(tileset_t *tileset,
int32_t columns, int32_t rows,
int32_t width, int32_t height,
int32_t gapX, int32_t gapY,
int32_t borderX, int32_t borderY
);
/**
* Retreive the division for a given tileset coordinate.
*
* @param tileset Tileset to retreive from.
* @param column X axis of the tileset.
* @param row Y axis of the tileset.
* @returns The Tileset division.
*/
tilesetdiv_t tilesetGetDivision(tileset_t *tileset,int32_t column, int32_t row);
/**
* Cleans a previously created tileset
*
* @param tileset Cleanup the tileset.
*/
void tilesetDispose(tileset_t *tileset);

View File

@ -1,19 +0,0 @@
# Copyright (c) 2021 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${PROJECT_NAME}
PRIVATE
align.c
breakpoint.c
frame.c
framedtextmenu.c
grid.c
image.c
label.c
menu.c
rectangle.c
textmenu.c
)

View File

@ -1,78 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "align.h"
void alignmentGetAxis(
uint8_t align,
float containerSize, float childSize, float childPos,
float *outSize, float *outPos
) {
if(align & ALIGN_SIZE_FILL) {
*outSize = containerSize;
} else if(align & ALIGN_SIZE_ORIGINAL) {
*outSize = childSize;
}
if(align & ALIGN_POS_START) {
*outPos = 0;
} else if(align & ALIGN_POS_CENTER) {
*outPos = (containerSize/2.0f) - ((*outSize) / 2.0f);
} else if(align & ALIGN_POS_END) {
*outPos = containerSize - (*outSize);
}
}
align_t alignmentGet(
uint8_t alignX, uint8_t alignY,
float containerWidth, float containerHeight,
float childWidth, float childHeight,
float childX, float childY
) {
align_t out = {
.x = 0,
.y = 0,
.width = 0,
.height = 0
};
if(alignX & ALIGN_SIZE_RATIO) {
// Work out Y size and alignment first, then we base off that.
alignmentGetAxis(
alignY, containerHeight, childHeight, childY, &out.height, &out.y
);
// Now work out ratio
out.width = out.height * (childWidth / childHeight);
// Now do X
alignmentGetAxis(
alignX, containerWidth, childWidth, childX, &out.width, &out.x
);
} else {
alignmentGetAxis(
alignX, containerWidth, childWidth, childX, &out.width, &out.x
);
}
// Same as above but inverted for Y axis.
if(alignY & ALIGN_SIZE_RATIO) {
alignmentGetAxis(
alignX, containerWidth, childWidth, childX, &out.width, &out.x
);
out.height = out.width * (childHeight / childWidth);
alignmentGetAxis(
alignY, containerHeight, childHeight, childY, &out.height, &out.y
);
} else {
alignmentGetAxis(
alignY, containerHeight, childHeight, childY, &out.height, &out.y
);
}
return out;
}

View File

@ -1,60 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../../libs.h"
#include "../../util/flags.h"
#define ALIGN_POS_CENTER flagDefine(0)
#define ALIGN_POS_START flagDefine(1)
#define ALIGN_POS_END flagDefine(2)
#define ALIGN_SIZE_FILL flagDefine(3)
#define ALIGN_SIZE_ORIGINAL flagDefine(4)
#define ALIGN_SIZE_RATIO flagDefine(5)
typedef struct {
float x, y;
float width, height;
} align_t;
/**
* Return the alignment for a specific access, really this doesn't need to be
* used. Does not support the ALIGN_SIZE_RATIO alignment method.
*
* @param align Alignment flags to get.
* @param containerSize Size of the container.
* @param childSize Size of the child.
* @param childPos Currently unused.
* @param outSize Pointer to a float for the size output.
* @param outPos Poitner to a float for the position output.
*/
void alignmentGetAxis(
uint8_t align,
float containerSize, float childSize, float childPos,
float *outSize, float *outPos
);
/**
* Get the alignment set for a given set of options.
*
* @param alignX Alignment options for the X axis.
* @param alignY Alignment options for the Y axis.
* @param containerWidth Width of the container.
* @param containerHeight Height of the container.
* @param childWidth Width of the child
* @param childHeight Height of the child.
* @param childX Currently unused.
* @param childY Currently unused.
* @return The alignment calculation.
*/
align_t alignmentGet(
uint8_t alignX, uint8_t alignY,
float containerWidth, float containerHeight,
float childWidth, float childHeight,
float childX, float childY
);

View File

@ -1,44 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "breakpoint.h"
void breakpointListInit(breakpointlist_t *list) {
list->breakpointCount = 0;
list->user = NULL;
list->onBreakpoint = NULL;
list->breakpointCurrent = 0x00;
}
uint8_t breakpointGet(breakpointlist_t *list, float width) {
uint8_t bp, i;
bp = 0xFF;
for(i = 0; i < list->breakpointCount; i++) {
if(list->breakpoints[i] > width) break;
bp = i;
}
if(bp == 0xFF) bp = 0;
return bp;
}
void breakpointAdd(breakpointlist_t *list, float width) {
list->breakpoints[list->breakpointCount++] = width;
}
void breakpointResize(breakpointlist_t *list, float width) {
uint8_t bp;
// Determine breakpoint
bp = breakpointGet(list, width);
if(list->breakpointCurrent == bp) return;
list->breakpointCurrent = bp;
// Fire event.
if(list->onBreakpoint != NULL) {
list->onBreakpoint(list->user, bp, list->breakpoints[bp]);
}
}

View File

@ -1,60 +0,0 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "../../libs.h"
/** Maximum breakpoints that the list can support. */
#define BREAKPOINT_COUNT_MAX 0x04
/** Callback for when a new breakpint is reached. */
typedef void breakpointcallback_t(void *user, uint8_t i, float breakpoint);
typedef struct {
/** List of breakpoints */
float breakpoints[BREAKPOINT_COUNT_MAX];
uint8_t breakpointCount;
/** Which breakpoint is current */
uint8_t breakpointCurrent;
/** Pointer to any custom user data. */
void *user;
/** Callback for when a breakpoint is reached */
breakpointcallback_t *onBreakpoint;
} breakpointlist_t;
/**
* Initialize a breakpoint.
*
* @param list List to initialize.
*/
void breakpointInit(breakpointlist_t *list);
/**
* Get the breakpoint for a given width set.
*
* @param list List to get from.
* @param width Width to use.
* @return The breakpoint (index) for this screen size.
*/
uint8_t breakpointGet(breakpointlist_t *list, float width);
/**
* Add a breakpoint definition to a breakpoint list.
*
* @param list List to add to.
* @param width Width of the breakpoint.
*/
void breakpointAdd(breakpointlist_t *list, float width);
/**
* Resize a breakpoint list, which (in turn) will fire the necessary events.
*
* @param list List to resize.
* @param width Width to use.
*/
void breakpointResize(breakpointlist_t *list, float width);

View File

@ -1,112 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "frame.h"
void frameInit(frame_t *frame) {
frame->texture = NULL;
primitiveInit(
&frame->primitive,
QUAD_VERTICE_COUNT * FRAME_PRIMITIVE_COUNT,
QUAD_INDICE_COUNT * FRAME_PRIMITIVE_COUNT
);
frameSetInnerSize(frame, FRAME_BORDER_SIZE, FRAME_BORDER_SIZE);
}
void frameSetSize(frame_t *frame, float width, float height) {
frameSetInnerSize(frame,
width - FRAME_BORDER_SIZE_FULL, height - FRAME_BORDER_SIZE_FULL
);
}
void frameSetInnerSize(frame_t *frame, float width, float height) {
float rightStart = FRAME_BORDER_SIZE + width;
float rightEnd = rightStart + FRAME_BORDER_SIZE;
float bottomStart = FRAME_BORDER_SIZE + height;
float bottomEnd = bottomStart + FRAME_BORDER_SIZE;
float tw = 1.0f / 3.0f;
float th = tw;
// Buffer the top left edge
quadBuffer(&frame->primitive, 0,
0, 0, 0, 0,
FRAME_BORDER_SIZE, FRAME_BORDER_SIZE, tw, th,
0, 0
);
// Buffer the top edge.
quadBuffer(&frame->primitive, 0,
FRAME_BORDER_SIZE, 0, tw, 0,
rightStart, FRAME_BORDER_SIZE, tw*2, th,
QUAD_VERTICE_COUNT, QUAD_INDICE_COUNT
);
// Buffer the top right edge.
quadBuffer(&frame->primitive, 0,
rightStart, 0, tw*2, 0,
rightEnd, FRAME_BORDER_SIZE, tw*3, th,
QUAD_VERTICE_COUNT*2, QUAD_INDICE_COUNT*2
);
// Buffer the left edge
quadBuffer(&frame->primitive, 0,
0, FRAME_BORDER_SIZE, 0, th,
FRAME_BORDER_SIZE, bottomStart, tw, th*2,
QUAD_VERTICE_COUNT*3, QUAD_INDICE_COUNT*3
);
// Buffer the center
quadBuffer(&frame->primitive, 0,
FRAME_BORDER_SIZE, FRAME_BORDER_SIZE, tw, th,
rightStart, bottomStart, tw*2, th*2,
QUAD_VERTICE_COUNT*4, QUAD_INDICE_COUNT*4
);
// Buffer the right edge.
quadBuffer(&frame->primitive, 0,
rightStart, FRAME_BORDER_SIZE, tw*2, th,
rightEnd, bottomStart, tw*3, th*2,
QUAD_VERTICE_COUNT*5, QUAD_INDICE_COUNT*5
);
// Buffer the bottom left edge.
quadBuffer(&frame->primitive, 0,
0, bottomStart, 0, th*2,
FRAME_BORDER_SIZE, bottomEnd, tw, th*3,
QUAD_VERTICE_COUNT*6, QUAD_INDICE_COUNT*6
);
// Buffer the bottom edge.
quadBuffer(&frame->primitive, 0,
FRAME_BORDER_SIZE, bottomStart, tw, th*2,
rightStart, bottomEnd, tw*2, th*3,
QUAD_VERTICE_COUNT*7, QUAD_INDICE_COUNT*7
);
// Buffer the bottom right edge.
quadBuffer(&frame->primitive, 0,
rightStart, bottomStart, tw*2, th*2,
rightEnd, bottomEnd, tw*3, th*3,
QUAD_VERTICE_COUNT*8, QUAD_INDICE_COUNT*8
);
}
void frameRender(frame_t *frame, shaderprogram_t *shader, float x, float y) {
if(frame->texture == NULL) return;
shaderUsePosition(shader, x, y, 0, 0, 0, 0);
shaderUseTexture(shader, frame->texture);
primitiveDraw(&frame->primitive, 0, -1);
}
void frameDispose(frame_t *frame) {
primitiveDispose(&frame->primitive);
}

View File

@ -1,67 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../../libs.h"
#include "../shaderprogram.h"
#include "../primitive/primitive.h"
#include "../primitive/quad.h"
#include "../font.h"
/** Size of the border (in pixels) on each edge */
#define FRAME_BORDER_SIZE 16
/** Total border size for a given frame on each axis */
#define FRAME_BORDER_SIZE_FULL FRAME_BORDER_SIZE * 2
/** How many quads are within the frame */
#define FRAME_PRIMITIVE_COUNT 9
typedef struct {
texture_t *texture;
primitive_t primitive;
} frame_t;
/**
* Initialize a GUI Frame.
*
* @param frame Frame to initialize.
*/
void frameInit(frame_t *frame);
/**
* Set the size of the frame (including the size of the border).
*
* @param frame Frame to set the size of.
* @param width Width of the frame.
* @param height Height of the frame
*/
void frameSetSize(frame_t *frame, float width, float height);
/**
* Set the size of the frame's innards (size excluding the borders).
*
* @param frame Frame to set the size of
* @param width Width of the inner frame.
* @param height Height of the inner frame.
*/
void frameSetInnerSize(frame_t *frame, float width, float height);
/**
* Render a game frame.
*
* @param frame Frame to render.
* @param shader Shader to use while rendering.
* @param x X position.
* @param y Y position.
*/
void frameRender(frame_t *frame, shaderprogram_t *shader, float x, float y);
/**
* Cleanup a previously initialized frame.
*
* @param frame Frame to dispose.
*/
void frameDispose(frame_t *frame);

View File

@ -1,42 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "framedtextmenu.h"
void framedTextMenuInit(framedtextmenu_t *menu, font_t *font, texture_t *text) {
frameInit(&menu->frame);
textMenuInit(&menu->menu, font);
menu->frame.texture = text;
menu->menu.grid.borderX = FRAME_BORDER_SIZE;
menu->menu.grid.borderY = FRAME_BORDER_SIZE;
menu->menu.grid.gutterX = FRAMED_TEXT_MENU_GUTTER_DEFAULT;
menu->menu.grid.gutterY = FRAMED_TEXT_MENU_GUTTER_DEFAULT;
}
void framedTextMenuResize(framedtextmenu_t *menu, float width, float height) {
if(menu->menu.grid.width == width && menu->menu.grid.height == height) {
return;
}
gridResize(&menu->menu.grid, width, height);
frameSetSize(&menu->frame, width, height);
}
void framedTextMenuUpdate(framedtextmenu_t *menu, engine_t *engine) {
menuUpdate(&menu->menu.menu, engine);
}
void framedTextMenuRender(
framedtextmenu_t *menu, shaderprogram_t *shader, float x, float y
) {
frameRender(&menu->frame, shader, x, y);
textMenuRender(&menu->menu, shader, x, y);
}
void framedTextMenuDispose(framedtextmenu_t *menu) {
textMenuDispse(&menu->menu);
frameDispose(&menu->frame);
}

View File

@ -1,67 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../engine/engine.h"
#include "../libs.h"
#include "frame.h"
#include "textmenu.h"
#include "grid.h"
#include "menu.h"
/** The default gutter for the grid of a framed text menu */
#define FRAMED_TEXT_MENU_GUTTER_DEFAULT 8.0f
typedef struct {
frame_t frame;
textmenu_t menu;
} framedtextmenu_t;
/**
* Initialize a framed text ui element.
*
* @param menu Menu to initialize.
* @param font Font to use for the text.
* @param text Texture for the frame.
*/
void framedTextMenuInit(framedtextmenu_t *menu, font_t *font, texture_t *text);
/**
* Resize a framed text menu.
*
* @param menu Menu to resize.
* @param width Width of the menu.
* @param height Height of the menu.
*/
void framedTextMenuResize(framedtextmenu_t *menu, float width, float height);
/**
* Update a framed text menu.
*
* @param menu Menu to update.
* @param engine Engine to use when updating.
*/
void framedTextMenuUpdate(framedtextmenu_t *menu, engine_t *engine);
/**
* Render a framed text menu.
*
* @param menu Menu to render.
* @param shader Shader to use.
* @param x X Position.
* @param y Y Position.
*/
void framedTextMenuRender(
framedtextmenu_t *menu, shaderprogram_t *shader, float x, float y
);
/**
* Dispose a previously created framed text menu.
*
* @param menu Menu to dispose.
*/
void framedTextMenuDispose(framedtextmenu_t *menu);

View File

@ -1,138 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "grid.h"
void gridInit(grid_t *grid) {
uint8_t i;
grid->columns = 1;
grid->rows = 1;
grid->gutterX = 0;
grid->gutterY = 0;
grid->borderX = 0;
grid->borderY = 0;
grid->width = 1;
grid->height = 1;
for(i = 0; i < GRID_COLUMN_COUNT_MAX; i++) {
grid->columnDefinitions[i] = GRID_CEL_SIZE_AUTO;
}
for(i = 0; i < GRID_ROW_COUNT_MAX; i++) {
grid->rowDefinitions[i] = GRID_CEL_SIZE_AUTO;
}
}
void gridRecalculate(grid_t *grid) {
uint8_t i, countFlexiColumns, countFlexiRows;
float flexiWidth, flexiHeight, s, p, totalFlexiWidth, totalFlexiHeight;
// Pass 1, determine the "flexible width size"
countFlexiColumns = 0;
countFlexiRows = 0;
totalFlexiWidth = (
grid->width -
(grid->gutterX * mathMax(grid->columns-1, 0)) -
(grid->borderX * 2.0f)
);
totalFlexiHeight = (
grid->height -
(grid->gutterY * mathMax(grid->rows-1, 0)) -
(grid->borderY * 2.0f)
);
for(i = 0; i < grid->columns; i++) {
if(grid->columnDefinitions[i] == GRID_CEL_SIZE_AUTO) {
countFlexiColumns++;
} else {
totalFlexiWidth -= grid->columnDefinitions[i];
}
}
for(i = 0; i < grid->rows; i++) {
if(grid->rowDefinitions[i] == GRID_CEL_SIZE_AUTO) {
countFlexiRows++;
} else {
totalFlexiHeight -= grid->rowDefinitions[i];
}
}
// Determine the "flexi size for each flexi cell"
flexiWidth = totalFlexiWidth / countFlexiColumns;
flexiHeight = totalFlexiHeight / countFlexiRows;
// Now set up the positions and sizes for each cell.
p = grid->borderX;
for(i = 0; i < grid->columns; i++) {
s = grid->columnDefinitions[i];
if(s == GRID_CEL_SIZE_AUTO) s = flexiWidth;
grid->columnPositions[i] = p;
grid->columnSizes[i] = s;
p += s + grid->gutterX;
}
p = grid->borderY;
for(i = 0; i < grid->rows; i++) {
s = grid->rowDefinitions[i];
if(s == GRID_CEL_SIZE_AUTO) s = flexiHeight;
grid->rowPositions[i] = p;
grid->rowSizes[i] = s;
p += s + grid->gutterY;
}
}
void gridResize(grid_t *grid, float width, float height) {
if(grid->width == width && grid->height == height) return;
grid->width = width;
grid->height = height;
gridRecalculate(grid);
}
void gridGetChild(
grid_t *grid, uint8_t col, uint8_t row, uint8_t columns, uint8_t rows,
float *x, float *y, float *width, float *height
) {
uint8_t i;
float s;
// Set positions
*x = grid->columnPositions[col];
*y = grid->rowPositions[row];
// Calculate width.
s = 0;
for(i = col; i < col+columns; i++) {
s += grid->columnSizes[i];
}
*width = s;
// Calculate height
s = 0;
for(i = row; i < row+rows; i++) {
s += grid->rowSizes[i];
}
*height = s;
}
align_t gridGetAndAlignChild(
grid_t *grid, uint8_t col, uint8_t row, uint8_t columns, uint8_t rows,
uint8_t alignX, uint8_t alignY, float width, float height
) {
float gx, gy, gw, gh;
// Get the size of the child first
gridGetChild(grid, col, row, columns, rows, &gx, &gy, &gw, &gh);
// Now align
align_t align = alignmentGet(alignX, alignY, gw, gh, width, height, -1,-1);
align.x += gx;
align.y += gy;
return align;
}

View File

@ -1,102 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "../util/math.h"
#include "align.h"
/** Maximum number of columns a grid can have */
#define GRID_COLUMN_COUNT_MAX 16
/** Maximum number of rows a grid can have */
#define GRID_ROW_COUNT_MAX GRID_COLUMN_COUNT_MAX
/** Cell size for "auto", basically to fill the remaining space evenly */
#define GRID_CEL_SIZE_AUTO -1
/** Definitio of a grid */
typedef struct {
/** Count of columns/rows in the grid */
uint8_t columns, rows;
/** Cell Definitions, used to control how the cells will size themselves */
float columnDefinitions[GRID_COLUMN_COUNT_MAX];
float rowDefinitions[GRID_COLUMN_COUNT_MAX];
/** Settings to control gutters (space between cells) and border (of grid) */
float gutterX, gutterY;
float borderX, borderY;
/** Calculated sizes and positions for each cell */
float columnSizes[GRID_COLUMN_COUNT_MAX];
float columnPositions[GRID_COLUMN_COUNT_MAX];
float rowSizes[GRID_ROW_COUNT_MAX];
float rowPositions[GRID_COLUMN_COUNT_MAX];
/** Cached size of the grid */
float width, height;
} grid_t;
/**
* Initialize a grid system.
*
* @param grid Grid system to initialize.
*/
void gridInit(grid_t *grid);
/**
* Recalculate the cell size and positions.
*
* @param grid Grid to recalculate for.
*/
void gridRecalculate(grid_t *grid);
/**
* Resize (and recalculate) a grid.
*
* @param grid Grid to resize.
* @param width Width to use.
* @param height Height to use.
*/
void gridResize(grid_t *grid, float width, float height);
/**
* Get the dimensions of a particular cell and span.
*
* @param grid Grid to get from.
* @param col Starting column.
* @param row Starting row.
* @param columns Count of columns the cell spans.
* @param rows Count of rows the cell spans.
* @param x Pointer to output X float.
* @param y Pointer to output Y float
* @param width Pointer to output width float.
* @param height Pointer to output height float.
*/
void gridGetChild(
grid_t *grid, uint8_t col, uint8_t row, uint8_t columns, uint8_t rows,
float *x, float *y, float *width, float *height
);
/**
* Align a child within its set cell.
*
* @param grid Grid to use when aligning.
* @param col Starting column.
* @param row Starting row.
* @param columns Count of columns the cell spans.
* @param rows Count of rows the cell spans.
* @param alignX Alignment flags for the X axis.
* @param alignY Alignment flags for the Y axis.
* @param width Current width of the child.
* @param height Current height of the child.
* @return The alignment information to align the child within the cell.
*/
align_t gridGetAndAlignChild(
grid_t *grid, uint8_t col, uint8_t row, uint8_t columns, uint8_t rows,
uint8_t alignX, uint8_t alignY, float width, float height
);

View File

@ -1,62 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "image.h"
void imageInit(image_t *image) {
image->quad.verticeCount = -1;
image->width = 1;
image->height = 1;
imageSetTexture(image, NULL);
}
void imageSetTexture(image_t *image, texture_t *texture) {
imageSetTextureAndCrop(image, texture,
0, 0,
texture == NULL ? 0 : (float)texture->width,
texture == NULL ? 0 : (float)texture->height
);
}
void imageSetTextureAndCrop(image_t *image, texture_t *texture,
float x, float y, float width, float height
) {
float u0, u1, v0, v1;
if(image->quad.verticeCount != -1) {
primitiveDispose(&image->quad);
image->quad.verticeCount = -1;
}
if(texture == NULL) return;
u0 = x / texture->width;
u1 = u0 + (width / texture->width);
v0 = y / texture->height;
v1 = v0 + (height / texture->height);
image->texture = texture;
image->width = width;
image->height = height;
quadInit(&image->quad, 0,
0,0,u0,v0,
1,1,u1,v1
);
}
void imageRender(image_t *image, shaderprogram_t *shader, float x, float y) {
if(image->texture == NULL) return;
shaderUsePositionAndScale(shader,
x,y,0,
0,0,0,
image->width, image->height, 1
);
shaderUseTexture(shader, image->texture);
primitiveDraw(&image->quad, 0, -1);
}
void imageDispose(image_t *image) {
if(image->quad.verticeCount != -1) primitiveDispose(&image->quad);
}

View File

@ -1,66 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "../display/primitive/primitive.h"
#include "../display/primitive/quad.h"
#include "../display/texture.h"
#include "../display/shaderprogram.h"
typedef struct {
texture_t *texture;
primitive_t quad;
float width, height;
} image_t;
/**
* Initialize an image.
*
* @param image Image to initialize.
*/
void imageInit(image_t *image);
/**
* Set the texture for an image. This will also initialize the underlying quad.
*
* @param image Image to set the texture for.
* @param texture Texture to use.
*/
void imageSetTexture(image_t *image, texture_t *texture);
/**
* Set the texture for an image. This will also initialize the underlying quad.
* Also allows cropping of the texture image.
*
* @param image Image to set the texture for.
* @param texture Texture to use.
* @param x X position of the crop.
* @param y Y position of the crop.
* @param width Width of the crop.
* @param height Height of the crop.
*/
void imageSetTextureAndCrop(image_t *image, texture_t *texture,
float x, float y, float width, float height
);
/**
* Render an image
*
* @param image Image to render.
* @param shader Shader to use while rendering.
* @param x X position.
* @param y Y position.
*/
void imageRender(image_t *image, shaderprogram_t *shader, float x, float y);
/**
* Cleanup a previously initialized image.
*
* @param image Image to dispose.
*/
void imageDispose(image_t *image);

View File

@ -1,39 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "label.h"
void labelInit(label_t *label) {
label->fontSize = FONT_SIZE_DEFAULT;
label->font = NULL;
label->maxWidth = -1;
label->primitive.verticeCount = 0;
}
void labelSetText(label_t *label, font_t *font, char *text) {
if(label->primitive.verticeCount != 0) {
primitiveDispose(&label->primitive);
label->primitive.verticeCount = 0;
}
label->font = font;
fontTextBuffer(
font, &label->primitive, &label->info, text,
label->maxWidth, label->fontSize
);
}
void labelRender(label_t *label, shaderprogram_t *shader, float x, float y) {
if(label->primitive.verticeCount == 0) return;
shaderUsePosition(shader, x,y,0, 0,0,0);
shaderUseTexture(shader, &label->font->texture);
primitiveDraw(&label->primitive, 0, -1);
}
void labelDispose(label_t *label) {
primitiveDispose(&label->primitive);
}

View File

@ -1,51 +0,0 @@
// Copyright (c) 2021 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "../libs.h"
#include "../display/shaderprogram.h"
#include "../display/primitive/primitive.h"
#include "../display/font.h"
/** Representation of a Label UI Element */
typedef struct {
font_t *font;
float fontSize;
float maxWidth;
fonttextinfo_t info;
primitive_t primitive;
} label_t;
/**
* Initialize a Label UI Element.
* @param label Label to initialize.
*/
void labelInit(label_t *label);
/**
* Sets the text for a given label.
*
* @param label Label to update.
* @param font Font to use.
* @param text Text to set.
*/
void labelSetText(label_t *label, font_t *font, char *text);
/**
* Render a label UI element.
*
* @param label Label to render.
* @param shader Shader to use while rendering.
* @param x X position.
* @param y Y position.
*/
void labelRender(label_t *label, shaderprogram_t *shader, float x, float y);
/**
* Dispose a previously created label.
*
* @param label Label to dispose.
*/
void labelDispose(label_t *label);

View File

@ -1,97 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "menu.h"
void menuInit(menu_t *menu) {
menu->itemCount = 0;
menu->selected = 0;
menu->cursorX = 0;
menu->cursorY = 0;
menu->user = NULL;
menu->onSelect = NULL;
}
void menuUpdate(menu_t *menu, engine_t *engine) {
menuitem_t *current;
menuitem_t *item;
uint8_t x, y, i, j;
current = menu->items + menu->selected;
if(inputIsPressed(&engine->input, INPUT_ACCEPT)) {
if(menu->onSelect != NULL) {
menu->onSelect(menu->user, menu->selected);
}
return;
}
// Handle press binds.
if(inputIsPressed(&engine->input, INPUT_DOWN)) {
x = 0;
y = 1;
} else if(inputIsPressed(&engine->input, INPUT_UP)) {
x = 0;
y = -1;
} else if(inputIsPressed(&engine->input, INPUT_LEFT)) {
x = -1;
y = 0;
} else if(inputIsPressed(&engine->input, INPUT_RIGHT)) {
x = 1;
y = 0;
} else {
x = 0;
y = 0;
}
// Update cursor positions
if(x != 0 || y != 0) {
if(x > 0) {
menu->cursorX = (current->x + current->width - 1) + x;
} else if(x < 0) {
menu->cursorX = current->x + x;
}
if(y > 0) {
menu->cursorY = (current->y + current->height - 1) + y;
} else if(y < 0) {
menu->cursorY = current->y + y;
}
// Get the item selected
j = MENU_ITEMS_MAX;
for(i = 0; i < menu->itemCount; i++) {
if(i == menu->selected) continue;
item = menu->items + i;
if(
item->x > menu->cursorX || (item->x+item->width-1) < menu->cursorX ||
item->y > menu->cursorY || (item->y+item->height-1) < menu->cursorY
) continue;
j = i;
break;
}
// Was a target found?
if(j == MENU_ITEMS_MAX) return;
menu->selected = j;
}
}
menuitem_t * menuAdd(menu_t *menu) {
menuitem_t *item;
if(menu->itemCount >= MENU_ITEMS_MAX) return NULL;
item = menu->items + menu->itemCount++;
item->x = 0;
item->y = 0;
item->width = 1;
item->height = 1;
return item;
}

View File

@ -1,62 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "../input/input.h"
#include "../epoch/epoch.h"
#include "../util/array.h"
#include "../engine/engine.h"
/** The maximum number of items a menu can hold */
#define MENU_ITEMS_MAX 32
/** Callback for when menu events are fired. */
typedef void menucallback_t(void *user, uint8_t i);
typedef struct {
uint8_t x;
uint8_t y;
uint8_t width;
uint8_t height;
} menuitem_t;
typedef struct {
menuitem_t items[MENU_ITEMS_MAX];
uint8_t itemCount;
uint8_t selected;
uint8_t cursorX;
uint8_t cursorY;
void *user;
menucallback_t *onSelect;
} menu_t;
/**
* Initialize a menu.
*
* @param menu Menu to initialize.
* @param columns Count of rows.
* @param rows Count of columns.
*/
void menuInit(menu_t *menu);
/**
* Updates the menu to handle inputs.
*
* @param menu Menu to update.
* @param engine Engine to update from.
*/
void menuUpdate(menu_t *menu, engine_t *engine);
/**
* Add an item to the menu
*
* @param menu Menu to add to.
* @return Item to add to.
*/
menuitem_t * menuAdd(menu_t *menu);

View File

@ -1,38 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "rectangle.h"
void rectangleInit(rectangle_t *rectangle) {
rectangle->width = 32;
rectangle->height = 32;
textureInit(&rectangle->texture, 1, 1, NULL);
quadInit(&rectangle->quad, 0, 0,0,0,0, 1,1,1,1);
}
void rectangleSetColor(rectangle_t *rectangle, pixel_t color) {
textureBufferPixels(&rectangle->texture,
0, 0, 1, 1, &color
);
}
void rectangleRender(
rectangle_t *rect, shaderprogram_t *shader, float x, float y
) {
shaderUsePositionAndScale(shader,
x, y, 0,
0, 0, 0,
rect->width, rect->height, 1
);
shaderUseTexture(shader, &rect->texture);
primitiveDraw(&rect->quad, 0, -1);
}
void rectangleDispose(rectangle_t *rectangle) {
primitiveDispose(&rectangle->quad);
textureDispose(&rectangle->texture);
}

View File

@ -1,30 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "../display/texture.h"
#include "../display/shaderprogram.h"
#include "../display/primitive/primitive.h"
#include "../display/primitive/quad.h"
typedef struct {
float width, height;
texture_t texture;
primitive_t quad;
} rectangle_t;
void rectangleInit(rectangle_t *rectangle);
void rectangleSetColor(rectangle_t *rectangle, pixel_t color);
void rectangleRender(
rectangle_t *rect, shaderprogram_t *shader,
float x, float y
);
void rectangleDispose(rectangle_t *rectangle);

View File

@ -1,79 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "textmenu.h"
void _textMenuOnSelect(void *user, uint8_t i) {
textmenu_t *textMenu = (textmenu_t *)user;
if(textMenu->onSelect != NULL) {
textMenu->onSelect(textMenu->user, i, textMenu->texts[i]);
}
}
void textMenuInit(textmenu_t *menu, font_t *font) {
menuInit(&menu->menu);
gridInit(&menu->grid);
rectangleInit(&menu->rectangle);
rectangleSetColor(&menu->rectangle, TEXTMENU_SELECTION_COLOR);
menu->menu.user = menu;
menu->menu.onSelect = &_textMenuOnSelect;
menu->font = font;
menu->onSelect = NULL;
}
menuitem_t * textMenuAdd(textmenu_t *menu, char *item) {
menu->texts[menu->menu.itemCount] = item;
labelInit(menu->labels + menu->menu.itemCount);
labelSetText(menu->labels + menu->menu.itemCount, menu->font, item);
(menu->labels + menu->menu.itemCount)->font = menu->font;
return menuAdd(&menu->menu);
}
void textMenuRender(
textmenu_t *menu, shaderprogram_t *shader, float x, float y
) {
uint8_t i;
label_t *label;
menuitem_t *item;
align_t align;
float gx, gy;
// Render selection box.
item = menu->menu.items + menu->menu.selected;
gridGetChild(
&menu->grid, item->x, item->y, item->width, item->height,
&gx, &gy, &menu->rectangle.width, &menu->rectangle.height
);
rectangleRender(
&menu->rectangle, shader, x + gx, y + gy
);
// Render labels
for(i = 0; i < menu->menu.itemCount; i++) {
item = menu->menu.items + i;
label = menu->labels + i;
align = gridGetAndAlignChild(
&menu->grid, item->x, item->y, item->width, item->height,
ALIGN_POS_START | ALIGN_SIZE_ORIGINAL,
ALIGN_POS_START | ALIGN_SIZE_ORIGINAL,
label->info.width, label->info.height
);
labelRender(
label, shader, align.x + x, align.y + y
);
}
}
void textMenuDispse(textmenu_t *menu) {
uint8_t i;
rectangleDispose(&menu->rectangle);
for(i = 0; i < menu->menu.itemCount; i++) {
labelDispose(menu->labels + i);
}
}

View File

@ -1,69 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "menu.h"
#include "grid.h"
#include "label.h"
#include "rectangle.h"
/** Colour of the selection box for the text menu */
#define TEXTMENU_SELECTION_COLOR ((pixel_t){.r=0xFF,.g=0xFF,.b=0xFF,.a=0x64})
/** Callback type for when an item is selected */
typedef void textmenucallback_t(void *user, uint8_t i, char *text);
typedef struct {
menu_t menu;
grid_t grid;
font_t *font;
rectangle_t rectangle;
char *texts[MENU_ITEMS_MAX];
label_t labels[MENU_ITEMS_MAX];
textmenucallback_t *onSelect;
void *user;
} textmenu_t;
/** Callback to be notified from the menu when the menu items are selected. */
void _textMenuOnSelect(void *user, uint8_t i);
/**
* Initialize a text menu item.
*
* @param menu Menu to initialize.
* @param font Font to use during initialization.
*/
void textMenuInit(textmenu_t *menu, font_t *font);
/**
* Add text to a menu list.
*
* @param menu Menu to add to.
* @param item Text to add (must be a constant value).
* @return The grid subsystem item.
*/
menuitem_t * textMenuAdd(textmenu_t *menu, char *item);
/**
* Render a text menu list.
*
* @param menu Menu to render.
* @param shader Shader to use.
* @param x X position of the menu.
* @param y Y position of the menu.
*/
void textMenuRender(textmenu_t *menu, shaderprogram_t *shader,float x, float y);
/**
* Dispose/Cleanup a text menu.
*
* @param menu Text menu to dispose.
*/
void textMenuDispse(textmenu_t *menu);

View File

@ -1,12 +0,0 @@
# Copyright (c) 2021 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${PROJECT_NAME}
PRIVATE
engine.c
thread.c
event.c
)

View File

@ -1,57 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "engine.h"
void engineInit(engine_t *engine) {
ASSERT_NOT_NULL(engine);
randSeed(123);
#if defined(GAME_NAME)
engine->name = GAME_NAME;
#else
engine->name = "Dawn";
#endif
epochInit(&engine->time);
saveManagerInit(&engine->save);
inputInit(&engine->input);
assetManagerInit(&engine->assetManager, &engine->save);
renderInit();
assetManagerStart(&engine->assetManager);
}
void engineUpdateStart(engine_t *engine, float delta) {
ASSERT_NOT_NULL(engine);
ASSERT_GREATER_THAN(delta, 0);
epochUpdate(&engine->time, delta);
inputUpdate(&engine->input);
assetManagerUpdate(&engine->assetManager);
renderFrameStart(&engine->render);
}
bool engineUpdateEnd(engine_t *engine) {
ASSERT_NOT_NULL(engine);
if(inputIsPressed(&engine->input, INPUT_NULL)) {
printf("Game exit requested\n");
return false;
}
return true;
}
void engineDispose(engine_t *engine) {
ASSERT_NOT_NULL(engine);
assetManagerDispose(&engine->assetManager);
inputDispose(&engine->input);
renderDispose();
}

View File

@ -1,70 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "../assert/assert.h"
#include "../util/rand.h"
#include "../input/input.h"
#include "../epoch/epoch.h"
#include "../display/render.h"
#include "../file/assetmanager.h"
#include "../save/save.h"
#include "scene/scenemanager.h"
typedef struct {
/** Name of the game */
char *name;
/** Time Manager for the game */
epoch_t time;
/** Render Manager for the game */
render_t render;
/** Asset Manager for the game */
assetmanager_t assetManager;
/** Input Manager for the game */
input_t input;
/** Save Manager for the game */
savemanager_t save;
/** Scene Manager for the game */
scenemanager_t scene;
} engine_t;
/**
* Initializes the provided engine. This will initialize all of the various
* managers for the game to use.
*
* @param engine Engine to initialize.
*/
void engineInit(engine_t *engine);
/**
* Updates the given engine at the start of a frame.
*
* @param engine Engine that is being updated
* @param delta Delta tick provided by the game's platform.
*/
void engineUpdateStart(engine_t *engine, float delta);
/**
* Updates the given engine at the end of a frame.
*
* @param engine Engine to update.
*/
bool engineUpdateEnd(engine_t *engine);
/**
* Cleanup the engine context.
*
* @param engine Engine to clean up.
*/
void engineDispose(engine_t *engine);

View File

@ -1,81 +0,0 @@
/**
* Copyright (c) 2022 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "event.h"
void eventManagerInit(eventmanager_t *manager) {
uint8_t i;
ASSERT_NOT_NULL(manager);
for(i = 0; i < EVENT_LISTENER_COUNT_MAX; i++) {
manager->listeners[i].callback = NULL;
}
}
bool _eventManagerFindFree(int32_t i, void *item) {
return ((eventlistener_t *) item)->callback == NULL;
}
eventlistener_t * eventManagerSubscribe(
eventmanager_t *man, event_t event, void *user, eventcallback_t *callback
) {
int32_t first;
eventlistener_t *listener;
ASSERT_NOT_NULL(man);
ASSERT_NOT_NULL(callback);
// Find the first available space.
first = arrayFindCallback(
sizeof(eventmanager_t), man->listeners,
EVENT_LISTENER_COUNT_MAX, _eventManagerFindFree
);
ASSERT_LESS_THAN(first, EVENT_LISTENER_COUNT_MAX);
ASSERT_GREATER_THAN_EQUAL_TO(first, 0);
// Insert
listener = man->listeners + first;
listener->callback = callback;
listener->user = user;
listener->event = event;
return listener;
}
void eventManagerUnsubscribe(eventmanager_t *man, eventlistener_t *listener) {
ASSERT_NOT_NULL(man);
ASSERT_NOT_NULL(listener);
listener->callback = NULL;
}
bool eventManagerTrigger(
eventmanager_t *manager, event_t event, const void *args[], const int32_t argc
) {
uint8_t i;
eventlistener_t *listener;
bool result;
ASSERT_GREATER_THAN_EQUAL_TO(argc, 0);
ASSERT_IF(
argc > 0,
ASSERT_NOT_NULL(args)
);
for(i = 0; i < EVENT_LISTENER_COUNT_MAX; i++) {
listener = manager->listeners + i;
if(listener->callback == NULL) continue;
if(listener->event != event) continue;
result = listener->callback(listener->user, event, args, argc);
if(!result) return false;
}
return true;
}

View File

@ -1,68 +0,0 @@
// Copyright (c) 2022 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "../libs.h"
#include "../assert/assert.h"
#include "../util/array.h"
#define EVENT_LISTENER_COUNT_MAX 128
typedef uint8_t event_t;
typedef bool eventcallback_t(
void *user, event_t event, const void *args[], const int32_t argc
);
typedef struct {
void *user;
event_t event;
eventcallback_t *callback;
} eventlistener_t;
typedef struct {
eventlistener_t listeners[EVENT_LISTENER_COUNT_MAX];
} eventmanager_t;
/**
* Initialize the event manager.
*
* @param manager Event manager to initialize.
*/
void eventManagerInit(eventmanager_t *manager);
/**
* Subscribe to an event on a given event manager.
*
* @param man Event manager to subscribe to.
* @param event Event to subscribe to.
* @param user Any custom user data to provide to the event callback.
* @param callback Callback to fire when the event is triggered.
* @return The event listener that was subscribed to.
*/
eventlistener_t * eventManagerSubscribe(
eventmanager_t *man, event_t event, void *user, eventcallback_t *callback
);
/**
* Unsubscribe an event listener that was previously subscribed.
*
* @param listener Listener to unsubscribe.
*/
void eventManagerUnsubscribe(eventmanager_t *man, eventlistener_t *listener);
/**
* Trigger a specific event on the event manager.
*
* @param manager Manager to trigger the event on.
* @param event Event to trigger
* @param args Array of pointers for event arguments.
* @param argc Count of event arguments.
* @return True if no events are subscribed, otherwise only returns true if all
* event listeners also return true.
*/
bool eventManagerTrigger(
eventmanager_t *manager, event_t event, const void *args[], const int32_t argc
);

View File

@ -1,62 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "thread.h"
void threadInit(thread_t *thread, threadfunction_t *call) {
ASSERT_NOT_NULL(thread);
ASSERT_NOT_NULL(call);
thread->call = call;
thread->user = NULL;
thread->state = 0x00;
}
void threadStart(thread_t *thread) {
ASSERT_NOT_NULL(thread);
ASSERT_FLAG_OFF(thread->state, THREAD_FLAG_RUNNING);
ASSERT_FLAG_OFF(thread->state, THREAD_FLAG_QUEUED);
thread->state |= THREAD_FLAG_QUEUED;
sysThreadCreate(&_threadWrappedCallback, thread->pt, thread);
}
void threadJoin(thread_t *thread) {
ASSERT_NOT_NULL(thread);
ASSERT_FLAG_ON(thread->state, THREAD_FLAG_RUNNING);
sysThreadJoin(thread->pt);
}
void threadCancel(thread_t *thread) {
ASSERT_NOT_NULL(thread);
ASSERT_FLAG_ON(thread->state, THREAD_FLAG_RUNNING);
sysThreadCancel(thread->pt, 1);
}
void threadSleep(float time) {
ASSERT_GREATER_THAN(time, 0);
sleep((unsigned long)(time * 1000.0f));
}
int32_t _threadWrappedCallback(thread_t *thread) {
int32_t response;
ASSERT_NOT_NULL(thread);
thread->state |= THREAD_FLAG_RUNNING;
thread->state = flagOff(thread->state, THREAD_FLAG_QUEUED);
response = thread->call(thread);
thread->state |= THREAD_FLAG_HAS_RUN;
thread->state = flagOff(thread->state, THREAD_FLAG_RUNNING);
return response;
}

View File

@ -1,73 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "../assert/assert.h"
#include "../util/flags.h"
typedef struct _thread_t thread_t;
#define THREAD_FLAG_RUNNING flagDefine(0)
#define THREAD_FLAG_QUEUED flagDefine(1)
#define THREAD_FLAG_HAS_RUN flagDefine(2)
/**
* Thread function itself.
*
* @param thread Thread that was called.
* @return The exit code, try to ensure only 0 is possible.
*/
typedef int32_t threadfunction_t(thread_t *thread);
typedef struct _thread_t {
threadhandle_t pt;
void *user;
uint8_t state;
threadfunction_t *call;
} thread_t;
/**
* Initialize a thread, prepare it to be started. You need to manually start it
* yourself.
*
* @param thread Thread pointer to maintain.
* @param call User callback to fire when the thread is started.
*/
void threadInit(thread_t *thread, threadfunction_t *call);
/**
* Start a previously prepared thread.
*
* @param thread Thread to start.
*/
void threadStart(thread_t *thread);
/**
* Wait for the given thread to finish execution.
*
* @param thread Thread to join.
*/
void threadJoin(thread_t *thread);
/**
* Cancel a running thread, avoid using where possible incase of any undefined
* behaviour.
*
* @param thread Thread to cancel.
*/
void threadCancel(thread_t *thread);
/**
* Sleep the current thread.
*
* @param time Time in seconds to sleep for.
*/
void threadSleep(float time);
/** Managing function for thread to help update the state */
int32_t _threadWrappedCallback(thread_t *thread);

View File

@ -1,10 +0,0 @@
# Copyright (c) 2021 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${PROJECT_NAME}
PRIVATE
epoch.c
)

View File

@ -1,28 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "epoch.h"
void epochInit(epoch_t *epoch) {
ASSERT_NOT_NULL(epoch);
epoch->delta = EPOCH_FIXED_STEP;
epoch->last = EPOCH_FIXED_STEP;
epoch->current = EPOCH_FIXED_STEP + EPOCH_FIXED_STEP;
}
void epochUpdate(epoch_t *epoch, float platformDelta) {
ASSERT_NOT_NULL(epoch);
ASSERT_GREATER_THAN(platformDelta, 0);
platformDelta = mathClamp(platformDelta, 0, EPOCH_FIXED_STEP);
epoch->last = epoch->current;
epoch->current = epoch->current + platformDelta;
epoch->delta = epoch->current - epoch->last;
epoch->fixedDelta = EPOCH_FIXED_STEP;
}

View File

@ -1,59 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "../assert/assert.h"
#include "../util/math.h"
#define EPOCH_FIXED_STEP 0.016f
#define EPOCH_SMALLEST_STEP 0.001f
typedef struct {
/**
* Current time (as a float of seconds since game start).
*
* When time is initialized this will start at a fixed value of 2/60ths of a
* second, regardless of what engine the game is running.
*
* This is to avoid any divide by zero errors.
*/
float current;
/**
* Last Time (as a float of seconds since the game start).
*
* This value will start at 1/60th of a second regardless of engine the game
* is running on to avoid divide by zero errors.
*/
float last;
/**
* Varying timestep that occured since the last frame.
*/
float delta;
/**
* Fixed timestep that is not affected by framerate but remains consistent.
*/
float fixedDelta;
} epoch_t;
/**
* Initializes the epoch time tracking.
*
* @param epoch Epoch to initialize.
*/
void epochInit(epoch_t *epoch);
/**
* Ticks the current epoch time.
*
* @param epoch Epoch to update.
* @param platformDelta The delta step between frames from the platform engine.
*/
void epochUpdate(epoch_t *epoch, float platformDelta);

View File

@ -1,16 +0,0 @@
# Copyright (c) 2021 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${PROJECT_NAME}
PRIVATE
asset.c
assetmanager.c
csv.c
xml.c
)
# Subdirs
add_subdirectory(loaders)

View File

@ -1,104 +0,0 @@
/**
* Copyright (c) 2021 Dominic Msters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "asset.h"
size_t assetRawLoad(char *assetName, uint8_t *buffer) {
assetbuffer_t *asset;
size_t length, read;
// Open a buffer.
asset = assetBufferOpen(assetName);
if(asset == NULL) return 0;
// Read the count of bytes in the file
assetBufferEnd(asset);
length = assetBufferGetCurrentPosition(asset);// Get our current position (the end)
// Are we only reading the size?
if(buffer == NULL) {
assetBufferClose(asset);
return length;
}
// Reset to start
assetBufferStart(asset);
// Read and seal the string.
read = assetBufferRead(asset, buffer, length);
assetBufferClose(asset); // Close the buffer.
// Did we read successfully?
if(read < length) return 0;
return read;
}
char * assetStringLoad(char *assetName) {
size_t length;
char *string;
length = assetRawLoad(assetName, NULL);
if(length == 0) return NULL;
string = malloc(length + 1);// +1 for null terminator
if(string == NULL) return NULL;
length = assetRawLoad(assetName, string);
if(length == 0) {
free(string);
return NULL;
}
string[length] = '\0';// Null terminate
return string;
}
assetbuffer_t * assetBufferOpen(char *assetName) {
// Get the directory based on the raw input by creating a new string.
FILE *fptr;
char filename[512];
// Prep filename
filename[0] = '\0';//Start at null
strcat(filename, ASSET_PREFIX);//Add prefix
strcat(filename, assetName);//Add body
printf("Opening up %s\n", filename);
// Open the file pointer now.
fptr = fopen(filename, "rb");
if(fptr == NULL) {
printf("Error opening %s: %s\n", filename, strerror(errno));
return NULL;// File available?
}
return (assetbuffer_t *)fptr;
}
bool assetBufferClose(assetbuffer_t *buffer) {
return fclose((FILE *)buffer);
}
int32_t assetBufferRead(assetbuffer_t *buffer, char *data, size_t size) {
return (int32_t)fread(data, 1, size, (FILE *)buffer);
}
int32_t assetBufferEnd(assetbuffer_t *buffer) {
// return feof((FILE *)buffer);
return fseek((FILE *)buffer, 0, SEEK_END);// Seek to the end
}
int32_t assetBufferStart(assetbuffer_t *buffer) {
return fseek((FILE *)buffer, 0, SEEK_SET);
}
int32_t assetBufferSkip(assetbuffer_t *buffer, long n) {
return fseek((FILE *)buffer, n, SEEK_CUR);
}
size_t assetBufferGetCurrentPosition(assetbuffer_t *buffer) {
return ftell((FILE *)buffer);
}

View File

@ -1,88 +0,0 @@
/**
* Copyright (c) 2021 Dominic Msters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "../display/font.h"
#if !defined(ASSET_PREFIX)
#error Asset Prefix has not been defined.
#endif
/** Definition of an asset ready to be buffered */
typedef FILE assetbuffer_t;
/**
* Buffer an asset from the file system into memory.
*
* @param assetName Path to the asset to buffer.
* @param buffer Place to buffer the data in to, or NULL to simply read the size
* @return The length (in bytes) of the file.
*/
size_t assetRawLoad(char *assetName, uint8_t *buffer);
/**
* Load a string from an asset into memory.
*
* @param assetName Asset to load
* @return A newly loaded string (malloced into existance.)
*/
char * assetStringLoad(char *assetName);
/**
* Platform-centric method to open a file buffer to an asset.
* @param assetName The asset name to open a buffer for.
* @return Pointer to a buffer, NULL if unsuccessfuil.
*/
assetbuffer_t * assetBufferOpen(char *assetName);
/**
* Closes a previously opened asset buffer.
* @param buffer Buffer to close.
* @return True if successful, otherwise false.
*/
bool assetBufferClose(assetbuffer_t *buffer);
/**
* Read bytes from buffer.
* @param buffer The buffer pointing to an asset.
* @param data Pointer to a ubyte array to buffer data into.
* @param size Length of the data buffer. Represents how many bytes can be read.
* @return The count of bytes read. Complete when less than data array size.
*/
int32_t assetBufferRead(assetbuffer_t *buffer, char *data, size_t size);
/**
* Skip to the end of the buffer, useful to find the length of the buffer.
* @param Buffer The buffer pointing to an asset.
* @return How many bytes were skipped
*/
int32_t assetBufferEnd(assetbuffer_t *buffer);
/**
* Rewinds an asset buffer to the start.
*
* @param buffer Buffer to rewind
* @return 0 if successful, otherwise unsuccessful.
*/
int32_t assetBufferStart(assetbuffer_t *buffer);
/**
* Method to skip n bytes in the buffer
* @param buffer The buffer pointing to an asset.
* @param n Count of bytes to skip.
* @return 0 if successful, otherwise unsuccessful.
*/
int32_t assetBufferSkip(assetbuffer_t *buffer, long n);
/**
* Retreive the current byte position within the asset that the head is at.
*
* @param buffer Buffer to get the position of.
* @return Position (in bytes) that the current seek is at.
*/
size_t assetBufferGetCurrentPosition(assetbuffer_t *buffer);

View File

@ -1,267 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "assetmanager.h"
assetmanagerloaderdefinition_t ASSET_MANAGER_LOADERS[] = {
{
&_assetManagerLoaderTextureAsync,
&_assetManagerLoaderTextureSync,
&_assetManagerLoaderTextureDispose
},
{
&_assetManagerLoaderFontAsync,
&_assetManagerLoaderFontSync,
&_assetManagerLoaderFontDispose
},
{
&_assetManagerLoaderShaderAsync,
&_assetManagerLoaderShaderSync,
&_assetManagerLoaderShaderDispose
},
{
&_assetManagerLoaderScaledTextureAsync,
&_assetManagerLoaderScaledTextureSync,
&_assetManagerLoaderScaledTextureDispose
}
};
bool _assetManagerOnSaveManagerValueChange(
void *usr, event_t evt, const void *args[], const int32_t argc
) {
ASSERT_NOT_NULL(args);
ASSERT_EQUAL(argc, 3);
// Was the scale changed?
if(strcmp(args[1], SAVE_KEY_TEXTURE_SCALE) == 0) {
assetManagerScaledTextureRescaleAll((assetmanager_t *)usr);
}
return true;
}
void assetManagerInit(assetmanager_t *manager, savemanager_t *save) {
threadInit(&manager->thread, &_assetManagerThread);
eventManagerInit(&manager->events);
manager->thread.user = manager;
manager->itemCount = 0;
manager->finished = false;
manager->holderCount = 0;
manager->running = false;
manager->save = save;
manager->listenerOnSaveValueChange = eventManagerSubscribe(
&save->events, SAVE_EVENT_VALUE_CHANGED,
manager, &_assetManagerOnSaveManagerValueChange
);
}
float assetManagerProgressGet(assetmanager_t *manager) {
float done;
uint8_t i;
assetmanageritem_t *item;
done = 0.0f;
for(i = 0; i < manager->itemCount; i++) {
item = manager->items + i;
done += assetManagerItemIsFinished(item) ? 1 : 0;
}
return done / ((float)manager->itemCount);
}
float assetManagerProgressGetForHolder(
assetmanager_t *manager, assetmanagerholder_t hold
) {
float done;
uint8_t i, j, c;
assetmanageritem_t *item;
done = 0.0f;
c = 0x00;
for(i = 0; i < manager->itemCount; i++) {
//Is this held by this holder?
item = manager->items + i;
for(j = 0; j < item->holderCount; j++) {
if(item->holders[j] != hold) continue;
c++;
done += assetManagerItemIsFinished(item) ? 1 : 0;
break;
}
}
// Is this thing even holding any assets to begin with?
if(c == 0x00) return 1.0f;
return done / (float)c;
}
assetmanagerholder_t assetManagerHolderCreate(assetmanager_t *man) {
uint8_t i;
// Find first available number.
for(i = 0; i < 0xFF; i++) {
if(arrayFind(
sizeof(assetmanagerholder_t), man->holders, man->holderCount, &i
) == -1) break;
}
man->holders[man->holderCount++] = i;
return i;// No slots left.
}
void assetManagerHolderRelease(assetmanager_t *man, assetmanagerholder_t hold) {
int32_t i;
uint8_t j;
assetmanageritem_t *item;
size_t s;
s = sizeof(assetmanagerholder_t);
i = arrayFind(s, man->holders,man->holderCount,&hold);
if(i == -1) return;
arraySplice(sizeof(uint8_t), man->holders, i, 1, man->holderCount);
man->holderCount--;
for(j = 0; j < man->itemCount; j++) {
item = man->items + j;
i = arrayFind(s, item->holders, item->holderCount, &hold);
if(i == -1) continue;
arraySplice(s, item->holders, i, 1, item->holderCount);
item->holderCount--;
}
}
void assetManagerDisposeReleased(assetmanager_t *man) {
uint8_t i;
assetmanagerloader_t *disp;
assetmanageritem_t *item;
for(i = 0; i < man->itemCount; i++) {
item = man->items + i;
disp = ASSET_MANAGER_LOADERS[item->type].dispose;
if(item->holderCount > 0) continue;
if(disp != NULL) disp(item);
arraySplice(sizeof(assetmanageritem_t), man->items, i, 1, man->itemCount);
man->itemCount--;
}
}
void assetManagerDispose(assetmanager_t *man) {
uint8_t i;
assetmanagerloader_t *disp;
assetmanageritem_t *item;
eventManagerUnsubscribe(&man->save->events, man->listenerOnSaveValueChange);
for(i = 0; i < man->itemCount; i++) {
item = man->items + i;
disp = ASSET_MANAGER_LOADERS[item->type].dispose;
if(item->holderCount > 0) continue;
if(disp != NULL) disp(item);
}
man->itemCount = 0;
man->holderCount = 0;
}
// Thread Management
void assetManagerStart(assetmanager_t *manager) {
if(manager->running) return;
manager->running = true;
threadStart(&manager->thread);
}
int32_t _assetManagerThread(thread_t *thread) {
// TODO: Can I allow multiple threads to run?
uint8_t i;
assetmanager_t *manager;
assetmanageritem_t *item;
assetmanagerloaderdefinition_t *definition;
bool result;
manager = thread->user;
for(i = 0; i < manager->itemCount; i++) {
item = manager->items + i;
definition = ASSET_MANAGER_LOADERS + item->type;
// Only bother with ASYNC items
if(definition->loadAsync == NULL) continue;
// Are we already loading, not ready, or already tried to load?
if(item->state != ASSET_MANAGER_STATE_PENDING) continue;
// Begin loading
item->state = ASSET_MANAGER_STATE_ASYNC_LOADING;
result = definition->loadAsync(item);
// Finish Loading
if(!result) {
item->state = ASSET_MANAGER_STATE_ASYNC_ERROR;
} else {
item->state = ASSET_MANAGER_STATE_ASYNC_DONE;
}
}
manager->finished = assetManagerProgressGet(manager) >= 1.0f;
manager->running = false;
return 0;
}
void assetManagerUpdate(assetmanager_t *manager) {
uint8_t i;
assetmanageritem_t *item;
assetmanagerloaderdefinition_t *definition;
void *args[2];
bool result;
args[0] = manager;
// Autostart
if(assetManagerProgressGet(manager) < 1.0f && !manager->running) {
assetManagerStart(manager);
}
for(i = 0; i < manager->itemCount; i++) {
item = manager->items + i;
definition = ASSET_MANAGER_LOADERS + item->type;
// Update not ready state (Synchronously)
if(item->state == ASSET_MANAGER_STATE_NOT_READY) {
item->state = ASSET_MANAGER_STATE_PENDING;
continue;
}
// If requires ASYNC loading, then confirm it has finished loading.
if(definition->loadAsync != NULL) {
if(item->state != ASSET_MANAGER_STATE_ASYNC_DONE) continue;
} else if(item->state != ASSET_MANAGER_STATE_PENDING) {
continue;
}
if(definition->loadSync == NULL) {
continue;
}
// Begin sync loading
item->state = ASSET_MANAGER_STATE_SYNC_LOADING;
result = definition->loadSync(item);
// Finish loading, fire events
if(!result) {
item->state = ASSET_MANAGER_STATE_SYNC_ERROR;
} else {
item->state = ASSET_MANAGER_STATE_SYNC_DONE;
args[1] = item;
eventManagerTrigger(
&manager->events, ASSET_MANAGER_EVENT_ITEM_LOADED, args, 2
);
}
}
manager->finished = assetManagerProgressGet(manager) >= 1.0f;
}

View File

@ -1,104 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "types/common.h"
#include "loaders/font.h"
#include "loaders/scaledtexture.h"
#include "loaders/shader.h"
#include "loaders/texture.h"
#include "asset.h"
#include "../save/save.h"
#include "../engine/event.h"
/** Callback Listener for save manager value changes */
bool _assetManagerOnSaveManagerValueChange(
void *usr, event_t evt, const void *args[], const int32_t argc
);
/**
* Initialize the asset manager
*
* @param manager Manager to initialize.
*/
void assetManagerInit(assetmanager_t *manager, savemanager_t *save);
/**
* Gets the progress of the asset manager as a representation of 0-1 as a % that
* has loaded.
*
* @param manager Manager to check the state of.
* @return The progress percent as a representation of 0-1
*/
float assetManagerProgressGet(assetmanager_t *manager);
/**
* Gets the progress of the assets for only those held by a specific holder.
*
* @param manager Manager to get the progress from
* @param hold Holder to get the items progress from.
* @return The percentage (0-1) of the loaded assets.
*/
float assetManagerProgressGetForHolder(
assetmanager_t *manager, assetmanagerholder_t hold
);
/**
* Creates a holder for a given asset manager. Asset holders are kept track of
* so that those who requests assets are responsible for those who free them. It
* also ensures only the assets that are actually necessary are kept loaded in
* memory at all times.
*
* @param man Asset manager in question
* @return An asset manager owner ID.
*/
assetmanagerholder_t assetManagerHolderCreate(assetmanager_t *man);
/**
* Release a previously reserved asset manager holder. This will (in turn) cause
* all of the assets that manager was holding to also be released.
*
* @param man Asset manager holder to release for.
* @param hold Holder to release.
*/
void assetManagerHolderRelease(assetmanager_t *man, assetmanagerholder_t hold);
/**
* Disposes all assets that are not currently held (released assets). This can
* only happen from the main thread due to synchronous assets such as Textures.
*
* @param man Manager to dispose.
*/
void assetManagerDisposeReleased(assetmanager_t *man);
/**
* Completely dispose an asset manager. This will also completely dispose all
* of the assets that this asset manager is holding.
*
* @param man Asset manager to dispose
*/
void assetManagerDispose(assetmanager_t *man);
/**
* Begin asynchronously loading all of the assets
*
* @param manager Manager to begin async loading.
*/
void assetManagerStart(assetmanager_t *manager);
/** Private Thread that is executed asynchronously */
int32_t _assetManagerThread(thread_t *thread);
/**
* Synchronously tick the asset manager. Some assets require some form of sync
* operations, such as buffering to the GPU, so make sure this is called at a
* good time for that task, such as right at the end of a frame.
*
* @param manager Manager to synchronously tick.
*/
void assetManagerUpdate(assetmanager_t *manager);

View File

@ -1,223 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "csv.h"
csvbufferresult_t csvBuffer(
assetbuffer_t *asset, csvbuffercallback_t *callback, void *user
) {
int32_t cellChar, read, i, currentColumnCount;
char buffer[CSV_BUFFER_SIZE];
char cell[CSV_CELL_SIZE_MAX];
char c;
bool callbackResponse;
bool insideEncapsulation = false;
csvbufferresult_t result = {
.cellCount = 0,
.rowCount = 0,
.columnCount = 0
};
// Init the cell Char Index.
cellChar = 0;
currentColumnCount = 0;
// Begin buffering.
while(true) {
// Read n bytes into our buffer
read = assetBufferRead(asset, buffer, CSV_BUFFER_SIZE);
// Now read back those bytes.
for(i = 0; i < read; i++) {
c = buffer[i];
// Characters we flat out ignore
if(c == '\r') continue;
// Handle quote marks.
if(c == '"') {
if(buffer[i+1] == '"') {// "" means a single quote (double-escaped)
i++;
cell[cellChar++] = c;
} else if(insideEncapsulation) {
insideEncapsulation = false;
} else {
insideEncapsulation = true;
}
continue;
}
// Is the start of a new cell/row?
if(c == '\0' || (!insideEncapsulation && (c == ',' || c == '\n'))) {
cell[cellChar] = '\0';// Terminate Cell string
// Fire off the callback
if(callback != NULL) {
callbackResponse = callback(asset, user, result.rowCount, currentColumnCount, cell);
if(!callbackResponse) return result;
}
// Prepare for next row/cell
currentColumnCount++;
result.columnCount = mathMax(currentColumnCount, result.columnCount);
if(c == '\n') {
result.rowCount++;
currentColumnCount = 0;
}
result.cellCount++;// Only count cells with
cellChar = 0;
continue;// Skip
}
// Add character to the cell.
cell[cellChar++] = c;
}
if(read < CSV_BUFFER_SIZE) break;
}
// If this is an empty row we don't count it, otherwise we do.
if(currentColumnCount != 0) result.rowCount++;
return result;
}
bool _csvBufferRowParserCallback(
assetbuffer_t *asset, void *user, int32_t row, int32_t column, char *data
) {
csvbufferrowdata_t *rowData = (csvbufferrowdata_t *)user;
// Now did we change rows?
if(row != rowData->row) {
// Yes we did, let's buffer the previous row.
if(rowData->callback != NULL) {
if(!rowData->callback(
asset, rowData->user, rowData->row, &rowData->rowCurrent
)) return false;
}
// Begin next row
rowData->row = row;
rowData->rowCurrent.columnCount = 0;
}
// Determine string info for the cell
int32_t length = (int32_t)strlen(data);
int32_t offset = (column * CSV_CELL_SIZE_MAX);
// Now copy the string data to the buffer
arrayCopy(sizeof(char), data, length + 1, rowData->rowCurrent.data + offset);
// Update the pointer to the string
rowData->rowCurrent.columns[column] = rowData->rowCurrent.data + offset;
rowData->rowCurrent.columnCount++;
return true;
}
csvbufferresult_t csvBufferRow(
assetbuffer_t *asset, csvbufferrowcallback_t *callback, void *user
) {
csvbufferrowdata_t data;
csvbufferresult_t result;
data.row = 0;
data.user = user;
data.callback = callback;
data.rowCurrent.columnCount = 0;
// Perform a per-cell buffer and run the parser callback.
result = csvBuffer(asset, &_csvBufferRowParserCallback, &data);
// Because the buffer may not fire for the last row we handle it here.
if(data.rowCurrent.columnCount > 0 && callback != NULL) {
if(!callback(asset, user, data.row, &data.rowCurrent)) return result;
}
return result;
}
bool _csvBufferRowWithHeadersCallback(
assetbuffer_t *asset, void *user, int32_t row, csvrow_t *csv
) {
csvbufferrowwithheadersdata_t *data = (csvbufferrowwithheadersdata_t *)user;
// Take the headers for row 0
if(row == 0) {
csvRowPopulate(csv, &data->headerRow);
return true;
}
// Fire the callback
return data->callback(asset, data->user, row, &data->headerRow, csv);
}
csvbufferresult_t csvBufferRowWithHeaders(
assetbuffer_t *asset, csvbufferrowwitheaderscallback_t *callback, void *user
) {
csvbufferrowwithheadersdata_t data;
data.user = user;
data.callback = callback;
return csvBufferRow(asset, &_csvBufferRowWithHeadersCallback, &data);
}
void csvRowPopulate(csvrow_t *source, csvrow_t *dest) {
int32_t i;
dest->columnCount = source->columnCount;
// Copy the raw characters from the source buffer.
arrayCopy(sizeof(char), source->data, CSV_ROW_CHARACTERS_MAX, dest->data);
// Now update the destination pointers to reference the data buffer.
for(i = 0; i < source->columnCount; i++) {
dest->columns[i] = dest->data + (i * CSV_CELL_SIZE_MAX);
}
}
bool _csvHeadersGetCallback(
assetbuffer_t *asset, void *user, int32_t row, csvrow_t *current
) {
csvrow_t *rowData = (csvrow_t *)user;
csvRowPopulate(current, rowData);
return false;// False to break the loop
}
csvbufferresult_t csvHeadersGet(assetbuffer_t *asset, csvrow_t *row) {
return csvBufferRow(asset, &_csvHeadersGetCallback, row);
}
int32_t csvColumnGetIndex(csvrow_t *row, char *key) {
return arrayFindString(row->columns, row->columnCount, key);
}
bool _csvRowSearchCallback(
assetbuffer_t *asset, void *user, int32_t row, csvrow_t *csv
) {
csvsearchdata_t *data = (csvsearchdata_t *)user;
// Does the search match?
if(strcmp(csv->columns[data->column], data->value) != 0) return true;
// Matched, copy and end.
csvRowPopulate(csv, data->row);
data->rowIndex = row;
return false;
}
int32_t csvRowSearch(
assetbuffer_t *asset, csvrow_t *row, int32_t column, char *value
) {
csvsearchdata_t data = {
.column = column,
.row = row,
.rowIndex = -1,
.value = value
};
csvBufferRow(asset, &_csvRowSearchCallback, &data);
return data.rowIndex;
}

View File

@ -1,191 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "asset.h"
#include "../util/array.h"
/** Maximum characters that a cell can support */
#define CSV_BUFFER_SIZE 32
/** Maximum characters in any given cell */
#define CSV_CELL_SIZE_MAX 1024
/** Maximum number of columns/cells in a given row */
#define CSV_ROW_COLUMNS_MAX 16
/** Count of characters maximum that a row can support */
#define CSV_ROW_CHARACTERS_MAX CSV_CELL_SIZE_MAX * CSV_ROW_COLUMNS_MAX
/** Result of a CSV buffer operation. */
typedef struct {
/** How many rows within the CSV */
int32_t rowCount;
/** Count of columns in the CSV, this is the longest row in the CSV. */
int32_t columnCount;
/** How many cells within the CSV */
int32_t cellCount;
} csvbufferresult_t;
/** Callback to receive data for each cell in a CSV being buffered */
typedef bool csvbuffercallback_t(
assetbuffer_t *asset, void *user, int32_t row, int32_t column, char *data
);
/** Representation of a CSV Row's complete data. */
typedef struct {
/** Characters within the row */
char data[CSV_ROW_CHARACTERS_MAX];
/** Pointer to the start of each string within the row */
char *columns[CSV_ROW_COLUMNS_MAX];
/** How many columns within the row */
int32_t columnCount;
} csvrow_t;
/** Callback to receive buffer data for a CSV row */
typedef bool csvbufferrowcallback_t(
assetbuffer_t *asset, void *user, int32_t row, csvrow_t *csv
);
/** Callback to receive buffer data for a CSV row, but includes CSV headers. */
typedef bool csvbufferrowwitheaderscallback_t(
assetbuffer_t *asset, void *user, int32_t row,
csvrow_t *header, csvrow_t *current
);
/** Data used by the cell callback for when the row buffering is progressing */
typedef struct {
/** Which row the current buffer is on */
int32_t row;
/** Information about the current row being parsed */
csvrow_t rowCurrent;
/** Pointer to custom user data */
void *user;
/** Pointer to custom user callback */
csvbufferrowcallback_t *callback;
} csvbufferrowdata_t;
/** Data used by the row callback for when the header row is parsed */
typedef struct {
/** Information about the header row */
csvrow_t headerRow;
/** Pointer to custom user data */
void *user;
/** Pointer to custom user callback */
csvbufferrowwitheaderscallback_t *callback;
} csvbufferrowwithheadersdata_t;
/** Data used while searching a CSV */
typedef struct {
/** Row to store the data in */
csvrow_t *row;
/** Row's index */
int32_t rowIndex;
/** Column to check */
int32_t column;
/** Value to check row */
char *value;
} csvsearchdata_t;
/**
* Buffer each cell within a CSV Asset Buffer with a callback.
*
* @param asset Asset to buffer the CSV from.
* @param callback Callback to fire for each cell parsed.
* @param user Pointer to any custom user data.
* @return The result of the CSV Buffer Operation.
*/
csvbufferresult_t csvBuffer(
assetbuffer_t *asset, csvbuffercallback_t *callback, void *user
);
/** Callback for when the CSV Row Buffer is parsing a row */
bool _csvBufferRowParserCallback(
assetbuffer_t *asset, void *user, int32_t row, int32_t column, char *data
);
/**
* Buffer each row within a CSV Asset Buffer with a callback.
*
* @param asset Asset to buffer the CSV from.
* @param callback Callback to fire when a row is parsed.
* @param user Pointer to any custom user data.
* @return The result of the CSV Buffer Operation.
*/
csvbufferresult_t csvBufferRow(
assetbuffer_t *asset, csvbufferrowcallback_t *callback, void *user
);
/** Parser that the header parser buffer uses. */
bool _csvBufferRowWithHeadersCallback(
assetbuffer_t *asset, void *user, int32_t row, csvrow_t *csv
);
/**
* Buffer each row within a CSV Asset Buffer with a callback. This will also
* provide the callback with the header row (The first row), already parsed.
*
* @param asset
* @param callback
* @param user
* @return csvbufferresult_t
*/
csvbufferresult_t csvBufferRowWithHeaders(
assetbuffer_t *asset, csvbufferrowwitheaderscallback_t *callback, void *user
);
/**
* Essentially a CSV Row Cloner, copies data from one CSV row to another and
* updates the char pointers for you.
*
* @param source The source CSV row to copy from.
* @param dest The destination CSV row to copy to.
*/
void csvRowPopulate(csvrow_t *source, csvrow_t *dest);
/** Callback used to parse and get the headers row */
bool _csvHeadersGetCallback(
assetbuffer_t *asset, void *user, int32_t row, csvrow_t *current
);
/**
* Parses just the headers row from a CSV and stores the output into the
* provided buffers.
*
* @param asset Asset to get the headers from.
* @param row The CSV Row to store the headers data in.
* @return The result of the buffer operation.
*/
csvbufferresult_t csvHeadersGet(assetbuffer_t *asset, csvrow_t *row);
/**
* Gets the column index within the CSV Row for the specific key.
* @param row Row to get from.
* @param key Key to search for
* @return The column index for the key, or -1 if not found.
*/
int32_t csvColumnGetIndex(csvrow_t *row, char *key);
/** Callback to use while scanning the CSV to find the matching row */
bool _csvRowSearchCallback(
assetbuffer_t *asset, void *user, int32_t row, csvrow_t *csv
);
/**
* Search the CSV for a matching row. Will return data only if the given column
* matches the given value.
*
* @param asset Asset buffer to search.
* @param row Where the returned row will be stored.
* @param column Column to check.
* @param value Value to check in that column
* @return The row index that the result was found on, or -1 if not found.
*/
int32_t csvRowSearch(
assetbuffer_t *asset, csvrow_t *row, int32_t column, char *value
);

View File

@ -1,14 +0,0 @@
# Copyright (c) 2021 Dominic Msters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${PROJECT_NAME}
PRIVATE
font.c
item.c
scaledtexture.c
shader.c
texture.c
)

View File

@ -1,39 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "font.h"
assetmanageritem_t * assetManagerLoadFont(
assetmanager_t *manager, assetmanagerholder_t owner, const char fileName[]
) {
assetmanageritem_t *item;
item = assetManagerItemGet(manager, fileName);
if(item == NULL) {
item = assetManagerItemAdd(manager, fileName);
item->type = ASSET_MANAGER_TYPE_FONT;
item->data.font.fileName = fileName;
}
assetManagerItemGetOrAddHolder(item, owner);
return item;
}
bool _assetManagerLoaderFontAsync(assetmanageritem_t *item) {
item->data.font.data = assetStringLoad(item->data.font.fileName);
return item->data.font.data != NULL;
}
bool _assetManagerLoaderFontSync(assetmanageritem_t *item) {
fontInit(&item->data.font.font, item->data.font.data);
free(item->data.font.data);
return true;
}
bool _assetManagerLoaderFontDispose(assetmanageritem_t *item) {
fontDispose(&item->data.font.font);
return true;
}

View File

@ -1,27 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "item.h"
#include "../asset.h"
/**
* Queue a font load onto the asset manager buffer.
*
* @param manager Manager to queue on to.
* @param owner Owner ID requesting to load this resource.
* @param font Font to push the result in to.
* @param fileName Filename of the asset to load.
* @return A pointer to the asset manager item for tracking.
*/
assetmanageritem_t * assetManagerLoadFont(
assetmanager_t *manager, assetmanagerholder_t owner, const char fileName[]
);
bool _assetManagerLoaderFontAsync(assetmanageritem_t *item);
bool _assetManagerLoaderFontSync(assetmanageritem_t *item);
bool _assetManagerLoaderFontDispose(assetmanageritem_t *item);

View File

@ -1,67 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "item.h"
assetmanageritem_t * assetManagerItemGet(
assetmanager_t *man, const char key[]
) {
uint8_t i;
assetmanageritem_t *item;
for(i = 0; i < man->itemCount; i++) {
item = man->items + i;
if(strcmp(item->key, key) == 0) return item;
}
return NULL;
}
assetmanageritem_t * assetManagerItemAdd(
assetmanager_t *manager, const char key[]
) {
// Check if key already exists.
assetmanageritem_t *item = manager->items + manager->itemCount++;
item->state = ASSET_MANAGER_STATE_NOT_READY;
item->key = key;
item->holderCount = 0x00;
return item;
}
uint8_t assetManagerItemGetOrAddHolder(
assetmanageritem_t *item, assetmanagerholder_t owner
) {
uint8_t i, firstEmpty;
firstEmpty = 0xFF;
for(i = 0; i < item->holderCount; i++) {
if(item->holders[i] == owner) return i;
if(firstEmpty == 0xFF && item->holders[i] == 0xFF) {
firstEmpty = i;
}
}
if(firstEmpty == 0xFF) firstEmpty = item->holderCount++;
item->holders[firstEmpty] = owner;
return firstEmpty;
}
bool assetManagerItemIsFinished(assetmanageritem_t *item) {
assetmanagerloaderdefinition_t *def;
ASSERT_NOT_NULL(item);
def = ASSET_MANAGER_LOADERS +item->type;
// Sync done is always done
if(item->state == ASSET_MANAGER_STATE_SYNC_DONE) return true;
// Only check if ASYNC is done.
if(item->state != ASSET_MANAGER_STATE_ASYNC_DONE) return false;
// Does it need to still sync load?
if(def->loadSync == NULL) return true;
return false;
}

View File

@ -1,48 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../types/common.h"
/**
* Retreive an exisitng asset manager item by its key.
*
* @param man Manager to get from
* @param key Key to search for.
* @return The matching asset manager item, or NULL if not found.
*/
assetmanageritem_t * assetManagerItemGet(assetmanager_t *man, const char key[]);
/**
* Private method, simply adds an item to the manager and resets the state.
*
* @param manager Manager to add to.
* @param key Key to use when adding.
* @return The added and reset item.
*/
assetmanageritem_t * assetManagerItemAdd(
assetmanager_t *manager, const char key[]
);
/**
* Add or get the index that a given holder has as a manager item.
*
* @param i Asset Item to check.
* @param o Owner to get/add.
* @return The index within the item that the owner is at.
*/
uint8_t assetManagerItemGetOrAddHolder(
assetmanageritem_t *i, assetmanagerholder_t o
);
/**
* Checks if a given asset item is finished loading or not.
*
* @param item Item to check.
* @return True if finished, otherwise false.
*/
bool assetManagerItemIsFinished(assetmanageritem_t *item);

View File

@ -1,232 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "scaledtexture.h"
assetmanageritem_t * assetManagerLoadScaledTexture(
assetmanager_t *manager, assetmanagerholder_t owner,
const char path[], const char file[]
) {
assetmanageritem_t *item;
texturescale_t *st;
uint8_t scale;
char buffer[ASSET_MANAGER_ITEM_NAME_MAX];
ASSERT_NOT_NULL(manager);
ASSERT_NOT_NULL(path);
ASSERT_NOT_NULL(file);
// Get the scale
scale = saveManagerGetU8(manager->save, SAVE_KEY_TEXTURE_SCALE);
ASSERT_LESS_THAN(scale, MANAGED_TEXTURE_SCALE_MAX);
// Generate a key
sprintf(buffer, "%s/%s", path, file);
item = assetManagerItemGet(manager, buffer);
// Already loaded?
if(item == NULL) {
item = assetManagerItemAdd(manager, buffer);
item->type = ASSET_MANAGER_TYPE_SCALED_TEXTURE;
item->data.scaledTexture.scale = scale;
st = &item->data.scaledTexture.textureScale;
st->scaleCount = 0;
st->baseWidth = 0;
st->baseHeight = 0;
st->path = path;
st->file = file;
}
assetManagerItemGetOrAddHolder(item, owner);
return item;
}
bool _assetManagerLoaderScaledTextureAsync(assetmanageritem_t *item) {
char buffer[128];
char *xmlData;
xml_t xml;
xml_t *child;
int16_t i, j;
texturescale_t *st;
texturescalescale_t *sts;
size_t length;
ASSERT_NOT_NULL(item);
ASSERT_EQUAL(item->type, ASSET_MANAGER_TYPE_SCALED_TEXTURE);
// TODO: This can be improved if we allow both asset dependencies and
// dependency sibling adding
st = &item->data.scaledTexture.textureScale;
ASSERT_NOT_NULL(st->path);
ASSERT_NOT_NULL(st->file);
ASSERT_EQUAL(st->scaleCount, 0);
// Begin loading texture XML
sprintf(buffer, "%s/%s.xml", st->path, st->file);
xmlData = assetStringLoad(buffer);
if(xmlData == NULL) return false;
xmlLoad(&xml, xmlData);
free(xmlData);
ASSERT_STRING_EQUALS(xml.node, "texture");
ASSERT_EQUAL(xml.childrenCount, MANAGED_TEXTURE_SCALE_MAX);
// Parse root texture info
i = xmlGetAttributeByName(&xml, "channels");
ASSERT_GREATER_THAN_EQUAL_TO(i, 0);
st->channels = (uint8_t)atoi(xml.attributeDatas[i]);
ASSERT_EQUAL(st->channels, TEXTURE_CHANNELS);
i = xmlGetAttributeByName(&xml, "width");
ASSERT_GREATER_THAN_EQUAL_TO(i, 0);
st->baseWidth = (int16_t)atoi(xml.attributeDatas[i]);
ASSERT_GREATER_THAN(st->baseWidth, 0);
i = xmlGetAttributeByName(&xml, "height");
ASSERT_GREATER_THAN_EQUAL_TO(i, 0);
st->baseHeight = (int16_t)atoi(xml.attributeDatas[i]);
ASSERT_GREATER_THAN(st->baseHeight, 0);
for(j = 0; j < xml.childrenCount; j++) {
child = xml.children + j;
ASSERT_STRING_EQUALS(child->node, "texture-scale");
ASSERT_EQUAL(child->childrenCount, 0);
i = xmlGetAttributeByName(child, "scale");
ASSERT_GREATER_THAN_EQUAL_TO(i, 0);
st->scales[st->scaleCount].scale = (uint8_t)atoi(child->attributeDatas[i]);
ASSERT_GREATER_THAN_EQUAL_TO(st->scales[st->scaleCount].scale, 1);
i = xmlGetAttributeByName(child, "width");
ASSERT_GREATER_THAN_EQUAL_TO(i, 0);
st->scales[st->scaleCount].width = (int16_t)atoi(child->attributeDatas[i]);
ASSERT_GREATER_THAN(st->scales[st->scaleCount].width, 0);
i = xmlGetAttributeByName(child, "height");
ASSERT_GREATER_THAN_EQUAL_TO(i, 0);
st->scales[st->scaleCount].height = (int16_t)atoi(child->attributeDatas[i]);
ASSERT_GREATER_THAN(st->scales[st->scaleCount].height, 0);
st->scaleCount++;
}
// Cleanup XML
xmlDispose(&xml);
// Get the scale
ASSERT_LESS_THAN(item->data.scaledTexture.scale, st->scaleCount);
sts = st->scales + item->data.scaledTexture.scale;
// Get filename
sprintf(buffer, "%s/%s_%i.texture", st->path, st->file, sts->scale);
// Create some space
length = assetRawLoad(buffer, NULL);
if(length <= 0) return false;
item->data.scaledTexture.data = malloc(sizeof(pixel_t) * length);
if(item->data.scaledTexture.data == NULL) return false;
// Load
length = assetRawLoad(buffer, (uint8_t *)item->data.scaledTexture.data);
if(length <= 0) {
free(item->data.scaledTexture.data);
return false;
}
return true;
}
bool _assetManagerLoaderScaledTextureSync(assetmanageritem_t *item) {
texturescale_t *st;
texturescalescale_t *sts;
ASSERT_NOT_NULL(item);
ASSERT_EQUAL(item->type, ASSET_MANAGER_TYPE_SCALED_TEXTURE);
ASSERT_NOT_NULL(item->data.scaledTexture.data);
st = &item->data.scaledTexture.textureScale;
ASSERT_EQUAL(st->scaleCount, MANAGED_TEXTURE_SCALE_MAX);
ASSERT_LESS_THAN(item->data.scaledTexture.scale, st->scaleCount);
sts = st->scales + item->data.scaledTexture.scale;
printf("Loading texture synchronously. %i x %i\n", sts->width, sts->height);
// Create the actual texture.
textureInit(
&item->data.scaledTexture.texture,
sts->width, sts->height,
item->data.scaledTexture.data
);
free(item->data.scaledTexture.data);
return true;
}
bool _assetManagerLoaderScaledTextureDispose(assetmanageritem_t *item) {
textureDispose(&item->data.scaledTexture.texture);
return true;
}
bool _assetManagerLoaderScaledTextureResize(
assetmanager_t *manager, assetmanageritem_t *item, uint8_t scale
) {
ASSERT_NOT_NULL(manager);
ASSERT_NOT_NULL(item);
ASSERT_LESS_THAN(scale, MANAGED_TEXTURE_SCALE_MAX);
ASSERT_EQUAL(item->type, ASSET_MANAGER_TYPE_SCALED_TEXTURE);
// Check if we need to update
if(item->data.scaledTexture.scale == scale) return true;
// Are we in the middle of an async load? If so then we gotta do some jank
while(item->state == ASSET_MANAGER_STATE_ASYNC_LOADING) {
threadSleep(0.1f);
}
// Are we async loaded but sync pending?
if(item->state == ASSET_MANAGER_STATE_ASYNC_DONE) {
// We are async done but pending sync loading. Free the texture data since
// it will be re-malloced later on.
free(item->data.scaledTexture.data);
} else if(item->state == ASSET_MANAGER_STATE_SYNC_DONE) {
// We are already loaded, free the texture
if(!_assetManagerLoaderScaledTextureDispose(item)) return false;
}
// Update scale.
item->data.scaledTexture.scale = scale;
item->data.scaledTexture.textureScale.scaleCount = 0;
// Immediately requeue a texture re-load
if(!_assetManagerLoaderScaledTextureAsync(item)) return false;
// And regenerate the texture synchronously.
if(!_assetManagerLoaderScaledTextureSync(item)) return false;
// Finally, mark texture as loaded (since it is)
item->state = ASSET_MANAGER_STATE_SYNC_DONE;
return true;
}
void assetManagerScaledTextureRescaleAll(assetmanager_t *manager) {
uint8_t i, scale;
ASSERT_NOT_NULL(manager);
// Get the new scale
scale = saveManagerGetU8(manager->save, SAVE_KEY_TEXTURE_SCALE);
ASSERT_LESS_THAN(scale, MANAGED_TEXTURE_SCALE_MAX);
// Rescale each texture. This is, unfortunately, blocking for now.
for(i = 0; i < manager->itemCount; i++) {
if(manager->items[i].type != ASSET_MANAGER_TYPE_SCALED_TEXTURE) continue;
_assetManagerLoaderScaledTextureResize(manager, manager->items + i, scale);
}
}

View File

@ -1,52 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "item.h"
#include "../../assert/assert.h"
#include "../xml.h"
#include "../asset.h"
#include "../../save/save.h"
/**
* Load the given texture scale for a scaled texture.
*
* @param manager Manager to queue on to.
* @param owner Owner ID requesting to load this resource.
* @param path Path of the texture size sets
* @param file Name of the texture that was generated.
* @return A pointer to the asset manager item for tracking.
*/
assetmanageritem_t * assetManagerLoadScaledTexture(
assetmanager_t *manager, assetmanagerholder_t owner,
const char path[], const char file[]
);
bool _assetManagerLoaderScaledTextureAsync(assetmanageritem_t *item);
bool _assetManagerLoaderScaledTextureSync(assetmanageritem_t *item);
bool _assetManagerLoaderScaledTextureDispose(assetmanageritem_t *item);
/**
* Private method to resize a texture after it has been loaded.
*
* @param manager
* @param item
* @param scale
* @return true
* @return false
*/
bool _assetManagerLoaderScaledTextureResize(
assetmanager_t *manager, assetmanageritem_t *item, uint8_t scale
);
/**
* Method that when called will scan the asset manager and find any scaled
* textures that need resizing, and resize them.
*
* @param manager Manager to check against.
*/
void assetManagerScaledTextureRescaleAll(assetmanager_t *manager);

View File

@ -1,55 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "shader.h"
assetmanageritem_t * assetManagerLoadShader(
assetmanager_t *manager, assetmanagerholder_t owner,
const char fileVert[], const char fileFrag[]
) {
assetmanageritem_t *item;
char buffer[ASSET_MANAGER_ITEM_NAME_MAX];
sprintf(buffer, "%s/%s", fileVert, fileFrag);
item = assetManagerItemGet(manager, buffer);
if(item == NULL) {
item = assetManagerItemAdd(manager, buffer);
item->type = ASSET_MANAGER_TYPE_SHADER;
item->data.shader.fileVert = fileVert;
item->data.shader.fileFrag = fileFrag;
}
assetManagerItemGetOrAddHolder(item, owner);
return item;
}
bool _assetManagerLoaderShaderAsync(assetmanageritem_t *item) {
item->data.shader.dataVert = assetStringLoad(item->data.shader.fileVert);
if(item->data.shader.dataVert == NULL) return false;
item->data.shader.dataFrag = assetStringLoad(item->data.shader.fileFrag);
if(item->data.shader.dataFrag == NULL) {
free(item->data.shader.fileVert);
return false;
}
return true;
}
bool _assetManagerLoaderShaderSync(assetmanageritem_t *item) {
shaderInit(
&item->data.shader.shader,
item->data.shader.dataVert,
item->data.shader.dataFrag
);
free(item->data.shader.dataFrag);
free(item->data.shader.dataVert);
return true;
}
bool _assetManagerLoaderShaderDispose(assetmanageritem_t *item) {
shaderDispose(&item->data.shader.shader);
return true;
}

View File

@ -1,29 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "item.h"
#include "../asset.h"
/**
* Queues a shader load onto the asset manager buffer.
*
* @param manager Manager to queue on to.
* @param owner Owner ID requesting to load this resource.
* @param shader Shader to push the result in to.
* @param fileVert Vertex file in question to load.
* @param fileFrag Fragment file in question to load.
* @return A pointer to the asset manager item for tracking.
*/
assetmanageritem_t * assetManagerLoadShader(
assetmanager_t *manager, assetmanagerholder_t owner,
const char fileVert[], const char fileFrag[]
);
bool _assetManagerLoaderShaderAsync(assetmanageritem_t *item);
bool _assetManagerLoaderShaderSync(assetmanageritem_t *item);
bool _assetManagerLoaderShaderDispose(assetmanageritem_t *item);

View File

@ -1,69 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "texture.h"
assetmanageritem_t * assetManagerLoadTexture(
assetmanager_t *manager, assetmanagerholder_t owner, const char fileName[]
) {
assetmanageritem_t *item;
item = assetManagerItemGet(manager, fileName);
if(item == NULL) {
item = assetManagerItemAdd(manager, fileName);
item->type = ASSET_MANAGER_TYPE_TEXTURE;
item->data.texture.fileName = fileName;
}
assetManagerItemGetOrAddHolder(item, owner);
return item;
}
bool _assetManagerLoaderTextureAsync(assetmanageritem_t *item) {
assetbuffer_t *buffer;
int channels;
stbi_io_callbacks OPENGL_STBI_CALLBACKS;
buffer = assetBufferOpen(item->data.texture.fileName);
if(buffer == NULL) return false;
// Setup the interface for STBI
OPENGL_STBI_CALLBACKS.read = &assetBufferRead;
OPENGL_STBI_CALLBACKS.skip = &assetBufferSkip;
OPENGL_STBI_CALLBACKS.eof = &assetBufferEnd;
// Buffer the image
channels = 0;
item->data.texture.data = (pixel_t *)stbi_load_from_callbacks(
&OPENGL_STBI_CALLBACKS, buffer,
&item->data.texture.width, &item->data.texture.height,
&channels, STBI_rgb_alpha
);
// Close the buffer
assetBufferClose(buffer);
if(item->data.texture.data == NULL) return false;
return true;
}
bool _assetManagerLoaderTextureSync(assetmanageritem_t *item) {
// Turn into a texture.
textureInit(
&item->data.texture.texture,
item->data.texture.width,
item->data.texture.height,
item->data.texture.data
);
// Cleanup
stbi_image_free(item->data.texture.data);
return true;
}
bool _assetManagerLoaderTextureDispose(assetmanageritem_t *item) {
textureDispose(&item->data.texture.texture);
return true;
}

View File

@ -1,27 +0,0 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "item.h"
#include "../asset.h"
/**
* Queue a texture load onto the asset manager buffer.
*
* @param manager Manager to queue on to.
* @param owner Owner ID requesting to load this resource.
* @param texture Texture to push the result in to.
* @param fileName Texture filename to load.
* @return A pointer to the asset manager item for tracking.
*/
assetmanageritem_t * assetManagerLoadTexture(
assetmanager_t *manager, assetmanagerholder_t owner, const char fileName[]
);
bool _assetManagerLoaderTextureAsync(assetmanageritem_t *item);
bool _assetManagerLoaderTextureSync(assetmanageritem_t *item);
bool _assetManagerLoaderTextureDispose(assetmanageritem_t *item);

Some files were not shown because too many files have changed in this diff Show More