SectrPrototype/code/api.odin
Ed_ 6819336696 Got logging setup
There is an issue with the tracked allocators made for the host module.
I'll need to see later whats going on, for now it doesn't matter.
2024-02-08 22:33:53 -05:00

266 lines
6.9 KiB
Odin

package sectr
import "base:runtime"
import "core:dynlib"
import "core:fmt"
import "core:mem"
import "core:mem/virtual"
import "core:os"
import "core:slice"
import "core:strings"
import rl "vendor:raylib"
Path_Assets :: "../assets/"
Path_Input_Replay :: "scratch.sectr_replay"
ModuleAPI :: struct {
lib : dynlib.Library,
write_time : os.File_Time,
lib_version : i32,
startup : type_of( startup ),
shutdown : type_of( sectr_shutdown),
reload : type_of( reload ),
update : type_of( update ),
render : type_of( render ),
clean_temp : type_of( clean_temp ),
}
@export
startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^ Logger )
{
init( & memory.logger, "Sectr", host_logger.file_path, host_logger.file )
context.logger = to_odin_logger( & memory.logger )
// Setup memory for the first time
{
arena_size :: size_of( mem.Arena)
internals_size :: 4 * Megabyte
using memory;
block := live_mem.curr_block
live = live_mem
snapshot = snapshot_mem
persistent_slice := slice_ptr( block.base, memory_persistent_size )
transient_slice := slice_ptr( memory_after( persistent_slice), memory_trans_temp_size )
temp_slice := slice_ptr( memory_after( transient_slice), memory_trans_temp_size )
// We assign the beginning of the block to be the host's persistent memory's arena.
// Then we offset past the arena and determine its slice to be the amount left after for the size of host's persistent.
persistent = tracked_allocator_init_vmem( persistent_slice, internals_size )
transient = tracked_allocator_init_vmem( transient_slice, internals_size )
temp = tracked_allocator_init_vmem( temp_slice , internals_size )
context.allocator = tracked_allocator( transient )
context.temp_allocator = tracked_allocator( temp )
}
state := new( State, tracked_allocator( memory.persistent ) )
using state
input = & input_data[1]
input_prev = & input_data[0]
// Rough setup of window with rl stuff
screen_width = 1280
screen_height = 1000
win_title : cstring = "Sectr Prototype"
rl.InitWindow( screen_width, screen_height, win_title )
log( "Raylib initialized and window opened" )
// Determining current monitor and setting the target frametime based on it..
monitor_id = rl.GetCurrentMonitor ()
monitor_refresh_hz = rl.GetMonitorRefreshRate( monitor_id )
rl.SetTargetFPS( monitor_refresh_hz )
log( fmt.tprintf( "Set target FPS to: %v", monitor_refresh_hz ) )
// Basic Font Setup
{
path_rec_mono_semicasual_reg := strings.concatenate( { Path_Assets, "RecMonoSemicasual-Regular-1.084.ttf" })
cstr := strings.clone_to_cstring( path_rec_mono_semicasual_reg )
font_rec_mono_semicasual_reg = rl.LoadFontEx( cstr, 24, nil, 0 )
delete( cstr)
rl.GuiSetFont( font_rec_mono_semicasual_reg ) // TODO(Ed) : Does this do anything?
default_font = font_rec_mono_semicasual_reg
log( "Default font loaded" )
}
}
// For some reason odin's symbols conflict with native foreign symbols...
@export
sectr_shutdown :: proc()
{
if memory.persistent == nil {
return
}
state := get_state()
// Replay
{
os.close( memory.replay.active_file )
}
// Raylib
{
rl.UnloadFont ( state.font_rec_mono_semicasual_reg )
rl.CloseWindow()
}
log("Module shutdown complete")
}
@export
reload :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^ Logger )
{
using memory;
block := live_mem.curr_block
live = live_mem
snapshot = snapshot_mem
persistent_slice := slice_ptr( block.base, memory_persistent_size )
transient_slice := slice_ptr( memory_after( persistent_slice), memory_trans_temp_size )
temp_slice := slice_ptr( memory_after( transient_slice), memory_trans_temp_size )
persistent = cast( ^TrackedAllocator ) & persistent_slice[0]
transient = cast( ^TrackedAllocator ) & transient_slice[0]
temp = cast( ^TrackedAllocator ) & temp_slice[0]
log("Module reloaded")
}
// TODO(Ed) : This lang really not have a fucking swap?
swap :: proc( a, b : ^ $Type ) -> ( ^ Type, ^ Type ) {
return b, a
}
@export
update :: proc() -> b32
{
state := get_state(); using state
replay := & memory.replay
state.input, state.input_prev = swap( state.input, state.input_prev )
poll_input( state.input_prev, state.input )
debug_actions : DebugActions = {}
poll_debug_actions( & debug_actions, state.input )
// Input Replay
{
if debug_actions.record_replay { #partial switch replay.mode
{
case ReplayMode.Off : {
save_snapshot( & memory.snapshot[0] )
replay_recording_begin( Path_Input_Replay )
}
case ReplayMode.Record : {
replay_recording_end()
}
}}
if debug_actions.play_replay { switch replay.mode
{
case ReplayMode.Off : {
if ! file_exists( Path_Input_Replay ) {
save_snapshot( & memory.snapshot[0] )
replay_recording_begin( Path_Input_Replay )
}
else {
load_snapshot( & memory.snapshot[0] )
replay_playback_begin( Path_Input_Replay )
}
}
case ReplayMode.Playback : {
replay_playback_end()
load_snapshot( & memory.snapshot[0] )
}
case ReplayMode.Record : {
replay_recording_end()
load_snapshot( & memory.snapshot[0] )
replay_playback_begin( Path_Input_Replay )
}
}}
if replay.mode == ReplayMode.Record {
record_input( replay.active_file, input )
}
else if replay.mode == ReplayMode.Playback {
play_input( replay.active_file, input )
}
}
if debug_actions.show_mouse_pos {
debug.mouse_vis = !debug.mouse_vis
}
debug.mouse_pos.basis = { input.mouse.X, input.mouse.Y }
should_shutdown : b32 = ! cast(b32) rl.WindowShouldClose()
return should_shutdown
}
@export
render :: proc()
{
state := get_state(); using state
replay := & memory.replay
rl.BeginDrawing()
rl.ClearBackground( Color_BG )
defer {
rl.DrawFPS( 0, 0 )
rl.EndDrawing()
// Note(Ed) : Polls input as well.
}
draw_text :: proc( format : string, args : ..any )
{
@static draw_text_scratch : [Kilobyte * 64]u8
state := get_state(); using state
if debug.draw_debug_text_y > 800 {
debug.draw_debug_text_y = 50
}
content := fmt.bprintf( draw_text_scratch[:], format, ..args )
debug_text( content, 25, debug.draw_debug_text_y )
debug.draw_debug_text_y += 16
}
draw_text( "Screen Width : %v", rl.GetScreenWidth () )
draw_text( "Screen Height: %v", rl.GetScreenHeight() )
if replay.mode == ReplayMode.Record {
draw_text( "Recording Input")
}
if replay.mode == ReplayMode.Playback {
draw_text( "Replaying Input")
}
if debug.mouse_vis {
width : f32 = 32
pos := debug.mouse_pos
draw_text( "Position: %v", rl.GetMousePosition() )
mouse_rect : rl.Rectangle
mouse_rect.x = pos.x - width/2
mouse_rect.y = pos.y - width/2
mouse_rect.width = width
mouse_rect.height = width
rl.DrawRectangleRec( mouse_rect, Color_White )
}
debug.draw_debug_text_y = 50
}
@export
clean_temp :: proc()
{
mem.tracking_allocator_clear( & memory.temp.tracker )
}