Lots of stuff (Big ones are cam and frame initial features)
There is now a 2D camera in the workspace! We have a basic 'Frame' definition. It doesn't have any interaction yet... I started to define spacial math, mostly for doing conversion and getting a grounding on pixel/points/cm reference. The world space is in cm.
This commit is contained in:
		
							
								
								
									
										167
									
								
								code/api.odin
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								code/api.odin
									
									
									
									
									
								
							| @@ -21,8 +21,7 @@ ModuleAPI :: struct { | ||||
| 	startup    : type_of( startup ), | ||||
| 	shutdown   : type_of( sectr_shutdown), | ||||
| 	reload     : type_of( reload ), | ||||
| 	update     : type_of( update ), | ||||
| 	render     : type_of( render ), | ||||
| 	tick       : type_of( tick ), | ||||
| 	clean_temp : type_of( clean_temp ), | ||||
| } | ||||
|  | ||||
| @@ -66,14 +65,18 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^ | ||||
| 	input_prev = & input_data[0] | ||||
|  | ||||
| 	// Rough setup of window with rl stuff | ||||
| 	screen_width  = 1280 | ||||
| 	screen_height = 1000 | ||||
| 	screen_width  = 1920 | ||||
| 	screen_height = 1080 | ||||
| 	win_title     : cstring = "Sectr Prototype" | ||||
| 	rl.InitWindow( screen_width, screen_height, win_title ) | ||||
| 	log( "Raylib initialized and window opened" ) | ||||
|  | ||||
| 	// We do not support non-uniform DPI. | ||||
| 	screen_dpi_scale = rl.GetWindowScaleDPI().x | ||||
| 	screen_dpc       = os_default_dpc * screen_dpi_scale | ||||
|  | ||||
| 	// Determining current monitor and setting the target frametime based on it.. | ||||
| 	monitor_id         = rl.GetCurrentMonitor    () | ||||
| 	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 ) ) | ||||
| @@ -90,13 +93,33 @@ startup :: proc( live_mem : virtual.Arena, snapshot_mem : []u8, host_logger : ^ | ||||
| 		log( "Default font loaded" ) | ||||
| 	} | ||||
|  | ||||
| 	project.path = "./" | ||||
| 	project.name = "First Project" | ||||
| 	project.workspace.name = "First Workspace" | ||||
| 	{ | ||||
| 		using project | ||||
| 		path           = "./" | ||||
| 		name           = "First Project" | ||||
| 		workspace.name = "First Workspace" | ||||
| 		{ | ||||
| 			using project.workspace | ||||
| 			cam = { | ||||
| 				target = { 0, 0 }, | ||||
| 				offset = { f32(screen_width) / 2, f32(screen_height) / 2 }, | ||||
| 				rotation = 0, | ||||
| 				zoom = 1.0, | ||||
| 			} | ||||
| 			// cam = { | ||||
| 			// 	position   = { 0, 0, -100 }, | ||||
| 			// 	target     = { 0, 0, 0 }, | ||||
| 			// 	up         = { 0, 1, 0 }, | ||||
| 			// 	fovy       = 90, | ||||
| 			// 	projection = rl.CameraProjection.ORTHOGRAPHIC, | ||||
| 			// } | ||||
|  | ||||
| 	project_save( & project ) | ||||
| 	project = {} | ||||
| 	project_load( "./First Project.sectr_proj", & project ) | ||||
| 			frame_1.color  = Color_BG_TextBox | ||||
| 			// Frame is getting interpreted as points (It doesn't have to be, I'm just doing it...) | ||||
| 			frame_1.width  = 400 | ||||
| 			frame_1.height = 250 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // For some reason odin's symbols conflict with native foreign symbols... | ||||
| @@ -147,125 +170,11 @@ swap :: proc( a, b : ^ $Type ) -> ( ^ Type, ^ Type ) { | ||||
| } | ||||
|  | ||||
| @export | ||||
| update :: proc() -> b32 | ||||
| tick :: proc ( delta_time : f64 ) -> 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 | ||||
| 	result := update( delta_time ) | ||||
| 	render() | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| @export | ||||
|   | ||||
| @@ -6,6 +6,7 @@ Color :: rl.Color | ||||
|  | ||||
| Color_White :: rl.WHITE | ||||
|  | ||||
| Color_Transparent  :: Color {   0,   0,   0,   0 } | ||||
| Color_BG           :: Color {  41,  41,  45, 255 } | ||||
| Color_BG_TextBox   :: Color {  32,  32,  32, 255 } | ||||
| Color_Frame_Hover  :: Color { 122, 122, 125, 255 } | ||||
|   | ||||
| @@ -49,8 +49,10 @@ State :: struct { | ||||
|  | ||||
| 	project : Project, | ||||
|  | ||||
| 	screen_width  : i32, | ||||
| 	screen_height : i32, | ||||
| 	screen_width       : i32, | ||||
| 	screen_height      : i32, | ||||
| 	screen_dpi_scale   : f32, | ||||
| 	screen_dpc         : f32,  // Pixels per cm | ||||
|  | ||||
| 	monitor_id         : i32, | ||||
| 	monitor_refresh_hz : i32, | ||||
| @@ -75,7 +77,10 @@ Project :: struct { | ||||
| } | ||||
|  | ||||
| Workspace :: struct { | ||||
| 	name : string | ||||
| 	name : string, | ||||
|  | ||||
| 	cam     : Camera, | ||||
| 	frame_1 : Frame | ||||
| } | ||||
|  | ||||
| DebugData :: struct { | ||||
| @@ -85,27 +90,5 @@ DebugData :: struct { | ||||
| 	draw_debug_text_y : f32, | ||||
|  | ||||
| 	mouse_vis : b32, | ||||
| 	mouse_pos : vec2, | ||||
| } | ||||
|  | ||||
| DebugActions :: struct { | ||||
| 	pause_renderer : b32, | ||||
|  | ||||
| 	load_auto_snapshot : b32, | ||||
| 	record_replay      : b32, | ||||
| 	play_replay        : b32, | ||||
|  | ||||
| 	show_mouse_pos : b32, | ||||
| } | ||||
|  | ||||
| poll_debug_actions :: proc( actions : ^ DebugActions, input : ^ InputState ) | ||||
| { | ||||
| 	using actions | ||||
| 	using input | ||||
|  | ||||
| 	base_replay_bind := keyboard.right_alt.ended_down && pressed( keyboard.L) | ||||
| 	record_replay     = base_replay_bind &&   keyboard.right_shift.ended_down | ||||
| 	play_replay       = base_replay_bind && ! keyboard.right_shift.ended_down | ||||
|  | ||||
| 	show_mouse_pos = keyboard.right_alt.ended_down && pressed(keyboard.M) | ||||
| 	mouse_pos : Vec2, | ||||
| } | ||||
|   | ||||
							
								
								
									
										27
									
								
								code/frame.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								code/frame.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| package sectr | ||||
|  | ||||
| Frame :: struct { | ||||
| 	position      : Vec2, | ||||
| 	width, height : f32, | ||||
| 	color         : Color | ||||
| } | ||||
|  | ||||
| get_bounds :: proc( frame : ^ Frame ) -> Bounds2 { | ||||
| 	half_width  := frame.width  / 2 | ||||
| 	half_height := frame.height / 2 | ||||
| 	bottom_left := Vec2 { -half_width, -half_height } | ||||
| 	top_right   := Vec2 {  half_width,  half_height } | ||||
| 	return { bottom_left, top_right } | ||||
| } | ||||
|  | ||||
| get_rect :: proc ( frame : ^ Frame ) -> Rectangle { | ||||
| 	half_width  := frame.width  / 2 | ||||
| 	half_height := frame.height / 2 | ||||
| 	rect : Rectangle = { | ||||
| 		x = frame.position.x - half_width, | ||||
| 		y = frame.position.y - half_height, | ||||
| 		width  = frame.width, | ||||
| 		height = frame.height, | ||||
| 	} | ||||
| 	return rect | ||||
| } | ||||
| @@ -36,9 +36,9 @@ slice_ptr               :: mem.slice_ptr | ||||
| Tracking_Allocator      :: mem.Tracking_Allocator | ||||
| tracking_allocator      :: mem.tracking_allocator | ||||
| tracking_allocator_init :: mem.tracking_allocator_init | ||||
| OS_Type                 :: type_of(ODIN_OS) | ||||
|  | ||||
| import rl "vendor:raylib" | ||||
|  | ||||
| Font :: rl.Font | ||||
|  | ||||
|  | ||||
| Font      :: rl.Font | ||||
| Rectangle :: rl.Rectangle | ||||
|   | ||||
| @@ -126,16 +126,14 @@ load_sectr_api :: proc ( version_id : i32 ) -> sectr.ModuleAPI | ||||
| 	startup    := cast( type_of( sectr.startup        )) dynlib.symbol_address( lib, "startup" ) | ||||
| 	shutdown   := cast( type_of( sectr.sectr_shutdown )) dynlib.symbol_address( lib, "sectr_shutdown" ) | ||||
| 	reload     := cast( type_of( sectr.reload         )) dynlib.symbol_address( lib, "reload" ) | ||||
| 	update     := cast( type_of( sectr.update         )) dynlib.symbol_address( lib, "update" ) | ||||
| 	render     := cast( type_of( sectr.render         )) dynlib.symbol_address( lib, "render" ) | ||||
| 	tick       := cast( type_of( sectr.tick           )) dynlib.symbol_address( lib, "tick" ) | ||||
| 	clean_temp := cast( type_of( sectr.clean_temp     )) dynlib.symbol_address( lib, "clean_temp" ) | ||||
|  | ||||
| 	missing_symbol : b32 = false | ||||
| 	if startup    == nil do fmt.println("Failed to load sectr.startup symbol") | ||||
| 	if shutdown   == nil do fmt.println("Failed to load sectr.shutdown symbol") | ||||
| 	if reload     == nil do fmt.println("Failed to load sectr.reload symbol") | ||||
| 	if update     == nil do fmt.println("Failed to load sectr.update symbol") | ||||
| 	if render     == nil do fmt.println("Failed to load sectr.render symbol") | ||||
| 	if tick       == nil do fmt.println("Failed to load sectr.tick symbol") | ||||
| 	if clean_temp == nil do fmt.println("Failed to load sector.clean_temp symbol") | ||||
| 	if missing_symbol { | ||||
| 		runtime.debug_trap() | ||||
| @@ -151,8 +149,7 @@ load_sectr_api :: proc ( version_id : i32 ) -> sectr.ModuleAPI | ||||
| 		startup    = startup, | ||||
| 		shutdown   = shutdown, | ||||
| 		reload     = reload, | ||||
| 		update     = update, | ||||
| 		render     = render, | ||||
| 		tick       = tick, | ||||
| 		clean_temp = clean_temp, | ||||
| 	} | ||||
| 	return loaded_module | ||||
| @@ -240,15 +237,20 @@ main :: proc() | ||||
| 	sectr_api          = sectr_api | ||||
| 	sectr_api.startup( memory.sectr_live, memory.sectr_snapshot, & logger ) | ||||
|  | ||||
| 	delta_ns : time.Duration | ||||
|  | ||||
| 	// TODO(Ed) : This should have an end status so that we know the reason the engine stopped. | ||||
| 	for ; running ; | ||||
| 	{ | ||||
| 		start_tick := time.tick_now() | ||||
|  | ||||
| 		// Hot-Reload | ||||
| 		sync_sectr_api( & sectr_api, & memory, & logger ) | ||||
|  | ||||
| 		running = sectr_api.update() | ||||
| 		          sectr_api.render() | ||||
| 		          sectr_api.clean_temp() | ||||
| 		running = sectr_api.tick( time.duration_seconds( delta_ns ) ) | ||||
| 		sectr_api.clean_temp() | ||||
|  | ||||
| 		delta_ns = time.tick_lap_time( & start_tick ) | ||||
| 	} | ||||
|  | ||||
| 	// Determine how the run_cyle completed, if it failed due to an error, | ||||
|   | ||||
| @@ -345,6 +345,7 @@ poll_input :: proc( old, new : ^ InputState ) | ||||
|  | ||||
| 		new.mouse.X = mouse_pos.x | ||||
| 		new.mouse.Y = mouse_pos.y | ||||
| 		new.mouse.vertical_wheel = rl.GetMouseWheelMove() | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,25 +1,37 @@ | ||||
| package sectr | ||||
|  | ||||
| import "core:math/linalg" | ||||
|  | ||||
| Vec2 :: linalg.Vector2f32 | ||||
| Vec3 :: linalg.Vector3f32 | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| when false { | ||||
| // TODO(Ed) : Evaluate if this is needed | ||||
|  | ||||
| vec2 :: vec2_f32 | ||||
| vec2_f32 :: struct #raw_union { | ||||
| Vec2 :: Vec2_f32 | ||||
| Vec2_f32 :: struct #raw_union { | ||||
| 	basis : [2] f32, | ||||
| 	using components : struct { | ||||
| 		x, y : f32 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| vec3 :: vec3_f32 | ||||
| vec3_f32 :: struct #raw_union { | ||||
| // make_vec2 :: proc ( x, y : f32 ) { | ||||
|  | ||||
| // } | ||||
|  | ||||
| Vec3 :: Vec3_f32 | ||||
| Vec3_f32 :: struct #raw_union { | ||||
| 	basis : [3] f32, | ||||
| 	using components : struct { | ||||
| 		x, y, z : f32 | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -20,7 +20,7 @@ archive_init_temp :: proc () -> ^ ArchiveData { | ||||
| } | ||||
|  | ||||
| state_serialize :: proc ( archive : ^ ArchiveData = nil ) { | ||||
|  | ||||
| 	// TODO(Ed): We'll need this for a better save/load snapshot setup. | ||||
| } | ||||
|  | ||||
| project_serialize :: proc ( project : ^ Project, archive : ^ ArchiveData, is_writting : b32 = true ) | ||||
| @@ -83,7 +83,8 @@ project_save :: proc ( project : ^ Project, archive : ^ ArchiveData = nil ) | ||||
| 	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 ) { | ||||
| project_load :: proc ( path : string, project : ^ Project, archive : ^ ArchiveData = nil ) | ||||
| { | ||||
| 	archive := archive | ||||
| 	if archive == nil { | ||||
| 		archive = archive_init_temp() | ||||
|   | ||||
							
								
								
									
										57
									
								
								code/space.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								code/space.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| package sectr | ||||
|  | ||||
| import rl "vendor:raylib" | ||||
|  | ||||
| // The points to pixels and pixels to points are our only reference to accurately converting | ||||
| // an object from world space to screen-space. | ||||
| // This prototype engine will have all its spacial unit base for distances in centimetres. | ||||
|  | ||||
| Inches_To_Centimetre  :: cast(f32) 2.54 | ||||
| Points_Per_Centimetre := cast(f32) 28.3465 | ||||
| Centimetres_Per_Point :: cast(f32) 1.0 / 28.3465 // Precalculated reciprocal for multiplication | ||||
| DPT_DPC               :: cast(f32) 72.0 * Inches_To_Centimetre | ||||
|  | ||||
| when ODIN_OS == OS_Type.Windows { | ||||
| 	os_default_dpc :: 96 * Inches_To_Centimetre | ||||
| 	// 1 inch = 2.54 cm, 96 inch * 2.54 = 243.84 DPC | ||||
| } | ||||
|  | ||||
| f32_cm_to_pixels :: proc ( cm : f32 ) -> f32 { | ||||
| 	state := get_state(); using state | ||||
| 	return cm * screen_dpc | ||||
| } | ||||
|  | ||||
| vec2_cm_to_pixels :: proc ( v : Vec2 ) -> Vec2 { | ||||
| 	state := get_state(); using state | ||||
| 	return v * screen_dpc | ||||
| } | ||||
|  | ||||
| points_to_pixels :: proc ( points : f32 ) -> f32 { | ||||
| 	state := get_state(); using state | ||||
| 	cm_per_pixel := 1.0 / screen_dpc | ||||
| 	return points * DPT_DPC * cm_per_pixel | ||||
| } | ||||
|  | ||||
| pixels_to_points :: proc ( pixels : f32 ) -> f32 { | ||||
| 	state := get_state(); using state | ||||
| 	cm_per_pixel := 1.0 / screen_dpc | ||||
| 	return pixels * cm_per_pixel * Points_Per_Centimetre | ||||
| } | ||||
|  | ||||
| Camera :: rl.Camera2D | ||||
|  | ||||
| get_half_screen :: proc() -> AreaSize { | ||||
| 	state := get_state(); using state | ||||
| 	return { | ||||
| 		f32(screen_width)  / 2, | ||||
| 		f32(screen_height) / 2, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| Bounds2 :: struct { | ||||
| 	bottom_left, top_right : Vec2 | ||||
| } | ||||
|  | ||||
| AreaSize :: struct { | ||||
| 	width, height : f32 | ||||
| } | ||||
| @@ -3,7 +3,7 @@ package sectr | ||||
| import    "core:unicode/utf8" | ||||
| import rl "vendor:raylib" | ||||
|  | ||||
| debug_text :: proc( content : string, x, y : f32, size : f32 = 16.0, color : rl.Color = rl.WHITE, font : rl.Font = {} ) | ||||
| debug_text :: proc( content : string, pos : Vec2, size : f32 = 16.0, color : rl.Color = rl.WHITE, font : rl.Font = {} ) | ||||
| { | ||||
| 	if len( content ) == 0 { | ||||
| 		return | ||||
| @@ -17,7 +17,7 @@ debug_text :: proc( content : string, x, y : f32, size : f32 = 16.0, color : rl. | ||||
|  | ||||
| 	rl.DrawTextCodepoints( font, | ||||
| 		raw_data(runes), cast(i32) len(runes), | ||||
| 		position = rl.Vector2 { x, y }, | ||||
| 		position = transmute(rl.Vector2) pos, | ||||
| 		fontSize = size, | ||||
| 		spacing  = 0.0, | ||||
| 		tint     = color ); | ||||
|   | ||||
							
								
								
									
										85
									
								
								code/tick_render.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								code/tick_render.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| package sectr | ||||
|  | ||||
| import "core:fmt" | ||||
|  | ||||
| import rl "vendor:raylib" | ||||
|  | ||||
| render :: proc() | ||||
| { | ||||
| 	state  := get_state(); using state | ||||
| 	replay := & memory.replay | ||||
|  | ||||
| 	half_screen_width  := f32(screen_width)  / 2 | ||||
| 	half_screen_height := f32(screen_height) / 2 | ||||
|  | ||||
| 	rl.BeginDrawing() | ||||
| 	rl.ClearBackground( Color_BG ) | ||||
| 	rl.BeginMode2D( project.workspace.cam ) | ||||
| 	// rl.BeginMode3D( project.workspace.cam ) | ||||
| 	defer { | ||||
| 		fps_msg := fmt.tprint( "FPS:", rl.GetFPS() ) | ||||
| 		debug_text( fps_msg, { -half_screen_width, -half_screen_height }, color = rl.GREEN ) | ||||
|  | ||||
| 		rl.EndMode2D() | ||||
| 		// rl.EndMode3D() | ||||
| 		rl.EndDrawing() | ||||
| 		// Note(Ed) : Polls input as well. | ||||
| 	} | ||||
|  | ||||
| 	// Frame 1 | ||||
| 	{ | ||||
| 		frame_1 := & project.workspace.frame_1 | ||||
| 		rect := get_rect( frame_1 ) | ||||
| 		rect.width  = points_to_pixels( rect.width ) | ||||
| 		rect.height = points_to_pixels( rect.height ) | ||||
| 		rect.x      = points_to_pixels( rect.x ) | ||||
| 		rect.y      = points_to_pixels( rect.y ) | ||||
|  | ||||
| 		rl.DrawRectangleRec( rect, frame_1.color ) | ||||
| 		// rl.DrawRectangleV( frame_1.position, { frame_1.width, frame_1.height }, frame_1.color ) | ||||
| 		// rl.DrawRectanglePro( rect, frame_1.position, 0, frame_1.color ) | ||||
| 	} | ||||
|  | ||||
| 	debug_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 | ||||
| 	} | ||||
|  | ||||
| 	// Debug Text | ||||
| 	{ | ||||
| 		debug_draw_text( "Screen Width : %v", rl.GetScreenWidth () ) | ||||
| 		debug_draw_text( "Screen Height: %v", rl.GetScreenHeight() ) | ||||
| 		if replay.mode == ReplayMode.Record { | ||||
| 			debug_draw_text( "Recording Input") | ||||
| 		} | ||||
| 		if replay.mode == ReplayMode.Playback { | ||||
| 			debug_draw_text( "Replaying Input") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if debug.mouse_vis { | ||||
| 		width : f32 = 32 | ||||
| 		pos   := debug.mouse_pos | ||||
|  | ||||
| 		debug_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 | ||||
| } | ||||
							
								
								
									
										134
									
								
								code/tick_update.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								code/tick_update.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| package sectr | ||||
|  | ||||
| import "core:fmt" | ||||
|  | ||||
| import rl "vendor:raylib" | ||||
|  | ||||
| DebugActions :: struct { | ||||
| 	load_project   : b32, | ||||
| 	save_project   : b32, | ||||
| 	pause_renderer : b32, | ||||
|  | ||||
| 	load_auto_snapshot : b32, | ||||
| 	record_replay      : b32, | ||||
| 	play_replay        : b32, | ||||
|  | ||||
| 	show_mouse_pos : b32, | ||||
|  | ||||
| 	cam_move_up    : b32, | ||||
| 	cam_move_left  : b32, | ||||
| 	cam_move_down  : b32, | ||||
| 	cam_move_right : b32, | ||||
| } | ||||
|  | ||||
| poll_debug_actions :: proc( actions : ^ DebugActions, input : ^ InputState ) | ||||
| { | ||||
| 	using actions | ||||
| 	using input | ||||
|  | ||||
| 	load_project = keyboard.left_control.ended_down && pressed( keyboard.O ) | ||||
| 	save_project = keyboard.left_control.ended_down && pressed( keyboard.S ) | ||||
|  | ||||
| 	base_replay_bind := keyboard.right_alt.ended_down && pressed( keyboard.L) | ||||
| 	record_replay     = base_replay_bind &&   keyboard.right_shift.ended_down | ||||
| 	play_replay       = base_replay_bind && ! keyboard.right_shift.ended_down | ||||
|  | ||||
| 	show_mouse_pos = keyboard.right_alt.ended_down && pressed(keyboard.M) | ||||
|  | ||||
| 	cam_move_up    = keyboard.W.ended_down | ||||
| 	cam_move_left  = keyboard.A.ended_down | ||||
| 	cam_move_down  = keyboard.S.ended_down | ||||
| 	cam_move_right = keyboard.D.ended_down | ||||
| } | ||||
|  | ||||
| update :: proc( delta_time : f64 ) -> 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 ) | ||||
|  | ||||
| 	// Saving & Loading | ||||
| 	{ | ||||
| 		if debug_actions.save_project { | ||||
| 			project_save( & project ) | ||||
| 		} | ||||
| 		if debug_actions.load_project { | ||||
| 			project_load( fmt.tprint( project.path, project.name, ".sectr_proj", sep = "" ), & project ) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// 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 = { input.mouse.X, input.mouse.Y } | ||||
|  | ||||
| 	// Camera Manual Nav | ||||
| 	{ | ||||
| 		move_speed        : f32 = 200.0 | ||||
| 		zoom_sensitiviity : f32 = 3.5 | ||||
|  | ||||
| 		cam := & project.workspace.cam | ||||
| 		cam.zoom *= 1 + input.mouse.vertical_wheel * zoom_sensitiviity * f32(delta_time) | ||||
| 		cam.zoom  = clamp( cam.zoom, 0.05, 10.0 ) | ||||
|  | ||||
| 		move_velocity : Vec2 = { | ||||
| 			- cast(f32) i32(debug_actions.cam_move_left) + cast(f32) i32(debug_actions.cam_move_right), | ||||
| 		  - cast(f32) i32(debug_actions.cam_move_up)   + cast(f32) i32(debug_actions.cam_move_down), | ||||
| 		} | ||||
| 		move_velocity *= move_speed * f32(delta_time) | ||||
| 		cam.target    += move_velocity | ||||
| 	} | ||||
|  | ||||
| 	should_shutdown : b32 = ! cast(b32) rl.WindowShouldClose() | ||||
| 	return should_shutdown | ||||
| } | ||||
		Reference in New Issue
	
	Block a user