From 58851e34ac114b67668a053222f941a6d54e59f0 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 9 Feb 2024 13:09:58 -0500 Subject: [PATCH] Got project saving/loading initally working --- code/api.odin | 10 ++++ code/env.odin | 107 ++++++++++-------------------------------- code/gen/genodin.odin | 0 code/replay.odin | 62 ++++++++++++++++++++++++ code/serialize.odin | 86 +++++++++++++++++++++++++++++++++ 5 files changed, 183 insertions(+), 82 deletions(-) create mode 100644 code/gen/genodin.odin create mode 100644 code/replay.odin create mode 100644 code/serialize.odin diff --git a/code/api.odin b/code/api.odin index 4e0f85f..32ccd47 100644 --- a/code/api.odin +++ b/code/api.odin @@ -60,6 +60,8 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^ state := new( State, tracked_allocator( memory.persistent ) ) using state + context.user_ptr = state + input = & input_data[1] input_prev = & input_data[0] @@ -87,6 +89,14 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^ default_font = font_rec_mono_semicasual_reg log( "Default font loaded" ) } + + project.path = "./" + project.name = "First Project" + project.workspace.name = "First Workspace" + + project_save( & project ) + project = {} + project_load( "./First Project.sectr_proj", & project ) } // For some reason odin's symbols conflict with native foreign symbols... diff --git a/code/env.odin b/code/env.odin index d7c200b..babc89d 100644 --- a/code/env.odin +++ b/code/env.odin @@ -25,11 +25,25 @@ Memory :: struct { logger : Logger, } +save_snapshot :: proc( snapshot : [^]u8 ) { + state := get_state() + + // state.font_rec_mono_semicasual_reg + // state.default_font + + live_ptr := cast( ^ rawptr ) memory.live.curr_block.base + mem.copy_non_overlapping( & snapshot[0], live_ptr, memory_chunk_size ) +} + +load_snapshot :: proc( snapshot : [^]u8 ) { + live_ptr := cast( ^ rawptr ) memory.live.curr_block.base + mem.copy_non_overlapping( live_ptr, snapshot, memory_chunk_size ) +} + State :: struct { input_data : [2] InputState, - - input_prev : ^ InputState, - input : ^ InputState, + input_prev : ^ InputState, + input : ^ InputState, debug : DebugData, @@ -48,17 +62,20 @@ State :: struct { default_font : Font, } +get_state :: proc() -> (^ State) { + return cast( ^ State ) raw_data( memory.persistent.backing.data ) +} + Project :: struct { + path : string, + name : string, + // TODO(Ed) : Support multiple workspaces workspace : Workspace } Workspace :: struct { - -} - -get_state :: proc() -> (^ State) { - return cast( ^ State ) raw_data( memory.persistent.backing.data ) + name : string } DebugData :: struct { @@ -92,77 +109,3 @@ poll_debug_actions :: proc( actions : ^ DebugActions, input : ^ InputState ) show_mouse_pos = keyboard.right_alt.ended_down && pressed(keyboard.M) } - -save_snapshot :: proc( snapshot : [^]u8 ) { - state := get_state() - - // state.font_rec_mono_semicasual_reg - // state.default_font - - live_ptr := cast( ^ rawptr ) memory.live.curr_block.base - mem.copy_non_overlapping( & snapshot[0], live_ptr, memory_chunk_size ) -} - -load_snapshot :: proc( snapshot : [^]u8 ) { - live_ptr := cast( ^ rawptr ) memory.live.curr_block.base - mem.copy_non_overlapping( live_ptr, snapshot, memory_chunk_size ) -} - -ReplayMode :: enum { - Off, - Record, - Playback, -} - -ReplayState :: struct { - loop_active : b32, - mode : ReplayMode, - active_file : os.Handle -} - -replay_recording_begin :: proc( path : string ) -{ - if file_exists( path ) { - result := os.remove( path ) - verify( result != os.ERROR_NONE, "Failed to delete replay file before beginning a new one" ) - } - - replay_file, open_error := os.open( path, os.O_RDWR | os.O_CREATE ) - verify( open_error != os.ERROR_NONE, "Failed to create or open the replay file" ) - - os.seek( replay_file, 0, 0 ) - - replay := & memory.replay - replay.active_file = replay_file - replay.mode = ReplayMode.Record -} - -replay_recording_end :: proc() { - replay := & memory.replay - replay.mode = ReplayMode.Off - - os.seek( replay.active_file, 0, 0 ) - os.close( replay.active_file ) -} - -replay_playback_begin :: proc( path : string ) -{ - verify( ! file_exists( path ), "Failed to find replay file" ) - - replay_file, open_error := os.open( path, os.O_RDWR | os.O_CREATE ) - verify( open_error != os.ERROR_NONE, "Failed to create or open the replay file" ) - - os.seek( replay_file, 0, 0 ) - - replay := & memory.replay - replay.active_file = replay_file - replay.mode = ReplayMode.Playback -} - -replay_playback_end :: proc() { - input := get_state().input - replay := & memory.replay - replay.mode = ReplayMode.Off - os.seek( replay.active_file, 0, 0 ) - os.close( replay.active_file ) -} diff --git a/code/gen/genodin.odin b/code/gen/genodin.odin new file mode 100644 index 0000000..e69de29 diff --git a/code/replay.odin b/code/replay.odin new file mode 100644 index 0000000..b35d582 --- /dev/null +++ b/code/replay.odin @@ -0,0 +1,62 @@ +package sectr + +import "core:os" + +ReplayMode :: enum { + Off, + Record, + Playback, +} + +ReplayState :: struct { + loop_active : b32, + mode : ReplayMode, + active_file : os.Handle +} + +replay_recording_begin :: proc( path : string ) +{ + if file_exists( path ) { + result := os.remove( path ) + verify( result != os.ERROR_NONE, "Failed to delete replay file before beginning a new one" ) + } + + replay_file, open_error := os.open( path, os.O_RDWR | os.O_CREATE ) + verify( open_error != os.ERROR_NONE, "Failed to create or open the replay file" ) + + os.seek( replay_file, 0, 0 ) + + replay := & memory.replay + replay.active_file = replay_file + replay.mode = ReplayMode.Record +} + +replay_recording_end :: proc() { + replay := & memory.replay + replay.mode = ReplayMode.Off + + os.seek( replay.active_file, 0, 0 ) + os.close( replay.active_file ) +} + +replay_playback_begin :: proc( path : string ) +{ + verify( ! file_exists( path ), "Failed to find replay file" ) + + replay_file, open_error := os.open( path, os.O_RDWR | os.O_CREATE ) + verify( open_error != os.ERROR_NONE, "Failed to create or open the replay file" ) + + os.seek( replay_file, 0, 0 ) + + replay := & memory.replay + replay.active_file = replay_file + replay.mode = ReplayMode.Playback +} + +replay_playback_end :: proc() { + input := get_state().input + replay := & memory.replay + replay.mode = ReplayMode.Off + os.seek( replay.active_file, 0, 0 ) + os.close( replay.active_file ) +} diff --git a/code/serialize.odin b/code/serialize.odin new file mode 100644 index 0000000..4c53b94 --- /dev/null +++ b/code/serialize.odin @@ -0,0 +1,86 @@ +package sectr + +import "core:encoding/json" +import "core:fmt" +import "core:os" +import "core:strings" + +Serializer_Version :: 1 +Serializer_Loading :: false + +ArchiveData :: struct { + data : [] byte, + version : i32, + is_writting : b32 +} + +archive_init_temp :: proc () -> ^ ArchiveData { + archive := new( ArchiveData, context.temp_allocator ) + archive.version = Serializer_Version + return archive +} + +state_serialize :: proc ( archive : ^ ArchiveData = nil ) { + +} + +project_serialize :: proc ( project : ^ Project, archive : ^ ArchiveData, is_writting : b32 = true ) +{ + options : json.Marshal_Options + options.spec = json.Specification.MJSON + options.indentation = 2 + options.pretty = true + options.use_spaces = false + + if is_writting + { + json_data, marshal_code := json.marshal( project^, options, allocator = context.temp_allocator ) + verify( marshal_code != json.Marshal_Data_Error.None, "Failed to marshal the project to JSON" ) + + archive.data = json_data + } + else + { + parsed_json, parse_code := json.parse( archive.data, json.Specification.MJSON, allocator = context.temp_allocator ) + verify( parse_code != json.Error.None, "Failed to parse project JSON") + + project_json := parsed_json.(json.Object) + project.name = project_json["name"].(json.String) + + // TODO(Ed) : Make this a separate proc + workspace_json := project_json["workspace"].(json.Object) + project.workspace.name = workspace_json["name"].(json.String) + + // DEBUG DUD + options.use_spaces = false + } +} + +project_save :: proc ( project : ^ Project, archive : ^ ArchiveData = nil ) +{ + archive := archive + if archive == nil { + archive = archive_init_temp() + } + project_serialize( project, archive ) + + if ! os.is_dir( project.path ) { + os.make_directory( project.path ) + verify( ! os.is_dir( project.path ), "Failed to create project path for saving" ) + } + + os.write_entire_file( fmt.tprint( project.path, project.name, ".sectr_proj", sep = ""), archive.data ) +} + +project_load :: proc ( path : string, project : ^ Project, archive : ^ ArchiveData = nil ) { + archive := archive + if archive == nil { + archive = archive_init_temp() + } + + data, read_code := os.read_entire_file( path, context.temp_allocator ) + verify( ! read_code, "Failed to read from project file" ) + + archive.data = data + project_serialize( project, archive, Serializer_Loading ) +}