326 lines
6.9 KiB
C
326 lines
6.9 KiB
C
// TODO(allen): Changes durring this jam
|
|
// fix with os->event_count not resetting
|
|
|
|
////////////////////////////////
|
|
// NOTE(allen): Events
|
|
|
|
internal String8
|
|
KeyName(Key index)
|
|
{
|
|
local_persist char *strings[Key_Max] =
|
|
{
|
|
#define Key(name, str) str,
|
|
#include "os_key_list.inc"
|
|
#undef Key
|
|
};
|
|
char *string = "(Invalid Key)";
|
|
if(index >= 0 && index < ArrayCount(strings))
|
|
{
|
|
string = strings[index];
|
|
}
|
|
String8 result;
|
|
result.str = string;
|
|
result.size = CalculateCStringLength(result.str);
|
|
return result;
|
|
}
|
|
|
|
internal String8
|
|
GamepadButtonName(GamepadButton index)
|
|
{
|
|
local_persist char *strings[GamepadButton_Max] =
|
|
{
|
|
#define GamepadButton(name, str) str,
|
|
#include "os_gamepad_button_list.inc"
|
|
#undef GamepadButton
|
|
};
|
|
char *string = "(Invalid Gamepad Button)";
|
|
if(index >= 0 && index < ArrayCount(strings))
|
|
{
|
|
string = strings[index];
|
|
}
|
|
String8 result;
|
|
result.str = string;
|
|
result.size = CalculateCStringLength(result.str);
|
|
return result;
|
|
}
|
|
|
|
internal b32
|
|
OS_EventIsMouse(OS_Event *event)
|
|
{
|
|
return event->type > OS_EventType_MouseStart && event->type < OS_EventType_MouseEnd;
|
|
}
|
|
|
|
internal b32
|
|
OS_CompareEvents(OS_Event a, OS_Event b)
|
|
{
|
|
b32 result = 0;
|
|
if(a.type == b.type &&
|
|
a.key == b.key &&
|
|
a.mouse_button == b.mouse_button &&
|
|
a.gamepad_button == b.gamepad_button &&
|
|
a.character == b.character &&
|
|
a.modifiers == b.modifiers)
|
|
{
|
|
result = 1;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal OS_Event
|
|
OS_KeyPressEvent(Key key, KeyModifiers modifiers)
|
|
{
|
|
OS_Event event =
|
|
{
|
|
.type = OS_EventType_KeyPress,
|
|
};
|
|
event.key = key;
|
|
event.modifiers = modifiers;
|
|
return event;
|
|
}
|
|
|
|
internal OS_Event
|
|
OS_KeyReleaseEvent(Key key, KeyModifiers modifiers)
|
|
{
|
|
OS_Event event =
|
|
{
|
|
.type = OS_EventType_KeyRelease,
|
|
};
|
|
event.key = key;
|
|
event.modifiers = modifiers;
|
|
return event;
|
|
}
|
|
|
|
internal OS_Event
|
|
OS_CharacterInputEvent(u64 character)
|
|
{
|
|
OS_Event event =
|
|
{
|
|
.type = OS_EventType_CharacterInput,
|
|
};
|
|
event.character = character;
|
|
return event;
|
|
}
|
|
|
|
internal OS_Event
|
|
OS_MouseMoveEvent(v2 position, v2 delta)
|
|
{
|
|
OS_Event event =
|
|
{
|
|
.type = OS_EventType_MouseMove,
|
|
};
|
|
event.position = position;
|
|
event.delta = delta;
|
|
return event;
|
|
}
|
|
|
|
internal OS_Event
|
|
OS_MousePressEvent(MouseButton button, v2 position)
|
|
{
|
|
OS_Event event =
|
|
{
|
|
.type = OS_EventType_MousePress,
|
|
};
|
|
event.mouse_button = button;
|
|
event.position = position;
|
|
return event;
|
|
}
|
|
|
|
internal OS_Event
|
|
OS_MouseReleaseEvent(MouseButton mouse_button, v2 position)
|
|
{
|
|
OS_Event event =
|
|
{
|
|
.type = OS_EventType_MouseRelease,
|
|
};
|
|
event.mouse_button = mouse_button;
|
|
event.position = position;
|
|
return event;
|
|
}
|
|
|
|
internal OS_Event
|
|
OS_MouseScrollEvent(v2 delta, KeyModifiers modifiers)
|
|
{
|
|
OS_Event event =
|
|
{
|
|
.type = OS_EventType_MouseScroll,
|
|
};
|
|
event.scroll = delta;
|
|
event.modifiers = modifiers;
|
|
return event;
|
|
}
|
|
|
|
internal b32
|
|
OS_GetNextEvent(OS_Event **event)
|
|
{
|
|
b32 result = 0;
|
|
Assert(os != 0);
|
|
u32 start_index = 0;
|
|
OS_Event *new_event = 0;
|
|
if(*event)
|
|
{
|
|
start_index = (*event - os->events) + 1;
|
|
}
|
|
for(u32 i = start_index; i < os->event_count; ++i)
|
|
{
|
|
if(os->events[i].type != OS_EventType_Null)
|
|
{
|
|
new_event = os->events+i;
|
|
break;
|
|
}
|
|
}
|
|
*event = new_event;
|
|
result = new_event != 0;
|
|
return result;
|
|
}
|
|
|
|
internal void
|
|
OS_EatEvent(OS_Event *event)
|
|
{
|
|
event->type = OS_EventType_Null;
|
|
}
|
|
|
|
// NOTE(rjf): Only called by platform layers. Do not call in app.
|
|
internal void
|
|
OS_BeginFrame(void)
|
|
{
|
|
os->pump_events = 0;
|
|
}
|
|
|
|
// NOTE(rjf): Only called by platform layers. Do not call in app.
|
|
internal void
|
|
OS_EndFrame(void)
|
|
{
|
|
os->current_time += 1.f / os->target_frames_per_second;
|
|
}
|
|
|
|
// NOTE(rjf): Only called by platform layers. Do not call in app.
|
|
internal void
|
|
OS_PushEvent(OS_Event event)
|
|
{
|
|
Assert(os != 0);
|
|
if(os->event_count < ArrayCount(os->events))
|
|
{
|
|
os->events[os->event_count++] = event;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////
|
|
// NOTE(allen): Thread Context
|
|
|
|
internal OS_ArenaNode*
|
|
_OS_GetFreeScratch(OS_ThreadContext *tctx)
|
|
{
|
|
OS_ArenaNode *usable_node = tctx->free;
|
|
Assert(usable_node != 0);
|
|
SLLStackPop(tctx->free);
|
|
DLLPushBack(tctx->first_used, tctx->last_used, usable_node);
|
|
return(usable_node);
|
|
}
|
|
|
|
internal M_Arena*
|
|
_OS_MarkArenaRestore(OS_ArenaNode *node)
|
|
{
|
|
M_Arena *result = &node->arena;
|
|
OS_ArenaInlineRestore *restore = PushArray(result, OS_ArenaInlineRestore, 1);
|
|
SLLStackPush(node->restore, restore);
|
|
node->ref_count += 1;
|
|
return(result);
|
|
}
|
|
|
|
internal M_Arena*
|
|
OS_GetScratch(void)
|
|
{
|
|
OS_ThreadContext *tctx = os->GetThreadContext();
|
|
OS_ArenaNode *usable_node = tctx->first_used;
|
|
if (usable_node == 0)
|
|
{
|
|
usable_node = _OS_GetFreeScratch(tctx);
|
|
}
|
|
return(_OS_MarkArenaRestore(usable_node));
|
|
}
|
|
|
|
internal M_Arena*
|
|
OS_GetScratch1(M_Arena *a1)
|
|
{
|
|
OS_ThreadContext *tctx = os->GetThreadContext();
|
|
OS_ArenaNode *usable_node = 0;
|
|
for (OS_ArenaNode *node = tctx->first_used;
|
|
node != 0;
|
|
node = node->next)
|
|
{
|
|
if (&node->arena != a1)
|
|
{
|
|
usable_node = node;
|
|
break;
|
|
}
|
|
}
|
|
if (usable_node == 0)
|
|
{
|
|
usable_node = _OS_GetFreeScratch(tctx);
|
|
}
|
|
return(_OS_MarkArenaRestore(usable_node));
|
|
}
|
|
|
|
internal M_Arena*
|
|
OS_GetScratch2(M_Arena *a1, M_Arena *a2)
|
|
{
|
|
OS_ThreadContext *tctx = os->GetThreadContext();
|
|
OS_ArenaNode *usable_node = 0;
|
|
for (OS_ArenaNode *node = tctx->first_used;
|
|
node != 0;
|
|
node = node->next)
|
|
{
|
|
if (&node->arena != a1 && &node->arena != a2)
|
|
{
|
|
usable_node = node;
|
|
break;
|
|
}
|
|
}
|
|
if (usable_node == 0)
|
|
{
|
|
usable_node = _OS_GetFreeScratch(tctx);
|
|
}
|
|
return(_OS_MarkArenaRestore(usable_node));
|
|
}
|
|
|
|
internal void
|
|
OS_ReleaseScratch(M_Arena *arena)
|
|
{
|
|
OS_ArenaNode *node = CastFromMember(OS_ArenaNode, arena, arena);
|
|
Assert(node->ref_count > 0);
|
|
node->ref_count -= 1;
|
|
if (node->ref_count == 0)
|
|
{
|
|
OS_ThreadContext *tctx = os->GetThreadContext();
|
|
DLLRemove(tctx->first_used, tctx->last_used, node);
|
|
M_ArenaClear(arena);
|
|
SLLStackPush(tctx->free, node);
|
|
}
|
|
else
|
|
{
|
|
void *ptr = node->restore;
|
|
node->restore = node->restore->next;
|
|
M_ArenaSetPosBackByPtr(arena, ptr);
|
|
}
|
|
}
|
|
|
|
internal void
|
|
_OS_ThreadSaveFileLine(char *file_name, u64 line_number)
|
|
{
|
|
OS_ThreadContext *tctx = os->GetThreadContext();
|
|
tctx->file_name = file_name;
|
|
tctx->line_number = line_number;
|
|
}
|
|
|
|
#define OS_ThreadSaveFileLine() _OS_ThreadSaveFileLine(__FILE__, __LINE__)
|
|
|
|
internal OS_File_Line
|
|
OS_ThreadRememberFileLine(void)
|
|
{
|
|
OS_ThreadContext *tctx = os->GetThreadContext();
|
|
OS_File_Line result = {tctx->file_name, tctx->line_number};
|
|
return(result);
|
|
}
|
|
|
|
|