Started to do manual control of the frame timing (no longer using raylib)
This commit is contained in:
parent
191d5076ea
commit
4b026c379a
34
Readme.md
34
Readme.md
@ -2,11 +2,41 @@
|
||||
|
||||
This prototype aims to flesh out ideas I've wanted to explore futher when it came to code editing and tools for code in general.
|
||||
|
||||
The things to explore:
|
||||
|
||||
* 2D canvas for laying out code visualized in various types of ASTs
|
||||
* WYSIWYG frontend ASTs
|
||||
* Making AST editing as versatile as text editing.
|
||||
* High-performance generating a large amount of UI widget boxes with proper auto-layout & no perceptible rendering-lag or input lag for interactions (framtimes stable).
|
||||
|
||||
|
||||
The project is so far in a "codebase boostrapping" phase.
|
||||
|
||||
The code is organized into 2 modules sectr_host & sectr.
|
||||
The project's is organized into 2 modules sectr_host & sectr.
|
||||
The host module loads the main module & its memory. Hot-reloading it's dll when it detects a change.
|
||||
|
||||
The main module only depends on libraries provided by odin repo's base, core, or vendor related packages, and a ini-parsing library.
|
||||
The dependencies are:
|
||||
|
||||
* Odin Compiler
|
||||
* Odin repo's base, core, and vendor(raylib) libaries
|
||||
* An ini parser
|
||||
|
||||
The client(sectr) module's organization is relatively flat due to the nature of odin's package management not allowing for cyclic dependencies across modules, and modules can only be in one directory.
|
||||
|
||||
Even so the notatble groups are:
|
||||
|
||||
* API : Provides the overarching interface of the app's general behavior. Host uses this to provide the client its necessary data and exection env.
|
||||
* Has the following definitions: startup, shutdown, reload, tick, clean_frame
|
||||
* Grime : Name speaks for itself, stuff not directly related to the target features to iterate upon for the prototype.
|
||||
* Defining dependency aliases or procedure overload tables, rolling own allocator, data structures, etc.
|
||||
* Font Provider : Manages fonts.
|
||||
* When loading fonts, the provider currently uses raylib to generate bitmap glyth sheets for a range of font sizes at once.
|
||||
* Goal is to eventually render using SDF shaders.
|
||||
* Input : Standard input pooling and related features. Platform abstracted via raylib for now.
|
||||
* Parser : AST generation, editing, and serialization. A 1/3 of this prototype will most likely be this alone.
|
||||
* UI : AST visualzation & editing, backend visualization, project organizationa via workspaces (2d cavnases)
|
||||
* Will most likely be the bulk of this prototype.
|
||||
* PIMGUI (Persistent Immediate Mode User Interface);
|
||||
* Auto-layout with heavy procedural generation of box widgets
|
||||
|
||||
|
||||
|
@ -8,6 +8,7 @@ import "core:mem/virtual"
|
||||
import "core:os"
|
||||
import "core:slice"
|
||||
import "core:strings"
|
||||
import "core:time"
|
||||
import rl "vendor:raylib"
|
||||
|
||||
Path_Assets :: "../assets/"
|
||||
@ -28,6 +29,8 @@ ModuleAPI :: struct {
|
||||
@export
|
||||
startup :: proc( persistent_mem, frame_mem, transient_mem, files_buffer_mem : ^VArena, host_logger : ^ Logger )
|
||||
{
|
||||
startup_tick := time.tick_now()
|
||||
|
||||
logger_init( & Memory_App.logger, "Sectr", host_logger.file_path, host_logger.file )
|
||||
context.logger = to_odin_logger( & Memory_App.logger )
|
||||
|
||||
@ -41,6 +44,7 @@ startup :: proc( persistent_mem, frame_mem, transient_mem, files_buffer_mem : ^V
|
||||
|
||||
context.allocator = persistent_allocator()
|
||||
context.temp_allocator = transient_allocator()
|
||||
// TODO(Ed) : Put on the transient allocator a slab allocator (transient slab)
|
||||
}
|
||||
|
||||
state := new( State, persistent_allocator() )
|
||||
@ -94,9 +98,14 @@ startup :: proc( persistent_mem, frame_mem, transient_mem, files_buffer_mem : ^V
|
||||
cam_zoom_sensitivity_digital = 0.2
|
||||
cam_zoom_sensitivity_smooth = 4.0
|
||||
|
||||
engine_refresh_hz = 30
|
||||
|
||||
ui_resize_border_width = 20
|
||||
}
|
||||
|
||||
Desired_OS_Scheduler_MS :: 1
|
||||
sleep_is_granular = set__scheduler_granularity( Desired_OS_Scheduler_MS )
|
||||
|
||||
// rl.Odin_SetMalloc( RL_MALLOC )
|
||||
|
||||
rl.SetConfigFlags( {
|
||||
@ -122,7 +131,7 @@ startup :: proc( persistent_mem, frame_mem, transient_mem, files_buffer_mem : ^V
|
||||
// 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 )
|
||||
rl.SetTargetFPS( 60 * 24 )
|
||||
log( str_fmt_tmp( "Set target FPS to: %v", monitor_refresh_hz ) )
|
||||
|
||||
// Basic Font Setup
|
||||
@ -166,6 +175,14 @@ startup :: proc( persistent_mem, frame_mem, transient_mem, files_buffer_mem : ^V
|
||||
ui_startup( & workspace.ui, cache_allocator = general_slab_allocator() )
|
||||
}
|
||||
}
|
||||
|
||||
startup_ms := duration_ms( time.tick_lap_time( & startup_tick))
|
||||
log( str_fmt_tmp("Startup time: %v ms", startup_ms) )
|
||||
|
||||
// Make sure to cleanup transient before continuing...
|
||||
// From here on, tarnsinet usage has to be done with care.
|
||||
// For most cases, the frame allocator should be more than enough.
|
||||
free_all( transient_allocator() )
|
||||
}
|
||||
|
||||
// For some reason odin's symbols conflict with native foreign symbols...
|
||||
@ -220,17 +237,60 @@ swap :: proc( a, b : ^ $Type ) -> ( ^ Type, ^ Type ) {
|
||||
}
|
||||
|
||||
@export
|
||||
tick :: proc( delta_time : f64, delta_ns : Duration ) -> b32
|
||||
tick :: proc( host_delta_time : f64, host_delta_ns : Duration ) -> b32
|
||||
{
|
||||
client_tick := time.tick_now()
|
||||
|
||||
context.allocator = frame_allocator()
|
||||
context.temp_allocator = transient_allocator()
|
||||
state := get_state(); using state
|
||||
|
||||
state := get_state()
|
||||
state.frametime_delta_ns = delta_ns
|
||||
state.frametime_delta_seconds = delta_time
|
||||
rl.PollInputEvents()
|
||||
|
||||
result := update( delta_time )
|
||||
result := update( host_delta_time )
|
||||
render()
|
||||
|
||||
rl.SwapScreenBuffer()
|
||||
|
||||
config.engine_refresh_hz = uint(monitor_refresh_hz)
|
||||
frametime_target_ms = 1.0 / f64(config.engine_refresh_hz) * S_To_MS
|
||||
sub_ms_granularity_required := frametime_target_ms <= Frametime_High_Perf_Threshold_MS
|
||||
|
||||
frametime_delta_ns = time.tick_lap_time( & client_tick )
|
||||
frametime_delta_ms = duration_ms( frametime_delta_ns )
|
||||
frametime_delta_seconds = duration_seconds( frametime_delta_ns )
|
||||
frametime_elapsed_ms = frametime_delta_ms + host_delta_time
|
||||
|
||||
if frametime_elapsed_ms < frametime_target_ms
|
||||
{
|
||||
sleep_ms := frametime_target_ms - frametime_elapsed_ms
|
||||
pre_sleep_tick := time.tick_now()
|
||||
|
||||
if sleep_ms > 0 {
|
||||
thread_sleep( cast(Duration) sleep_ms * MS_To_NS )
|
||||
// thread__highres_wait( sleep_ms )
|
||||
}
|
||||
|
||||
sleep_delta_ns := time.tick_lap_time( & pre_sleep_tick)
|
||||
sleep_delta_ms := duration_ms( sleep_delta_ns )
|
||||
|
||||
if sleep_delta_ms < sleep_ms {
|
||||
// log( str_fmt_tmp("frametime sleep was off by: %v ms", sleep_delta_ms - sleep_ms ))
|
||||
}
|
||||
|
||||
frametime_elapsed_ms += sleep_delta_ms
|
||||
for ; frametime_elapsed_ms < frametime_target_ms; {
|
||||
sleep_delta_ns = time.tick_lap_time( & pre_sleep_tick)
|
||||
sleep_delta_ms = duration_ms( sleep_delta_ns )
|
||||
|
||||
frametime_elapsed_ms += sleep_delta_ms
|
||||
}
|
||||
}
|
||||
|
||||
if frametime_elapsed_ms > 60.0 {
|
||||
log( str_fmt_tmp("Big tick! %v ms", frametime_elapsed_ms), LogLevel.Warning )
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
35
code/chrono.odin
Normal file
35
code/chrono.odin
Normal file
@ -0,0 +1,35 @@
|
||||
package sectr
|
||||
|
||||
Nanosecond_To_Microsecond :: 1.0 / (1000.0)
|
||||
Nanosecond_To_Millisecond :: 1.0 / (1000.0 * 1000.0)
|
||||
Nanosecond_To_Second :: 1.0 / (1000.0 * 1000.0 * 1000.0)
|
||||
|
||||
Microsecond_To_Nanosecond :: 1000.0
|
||||
Microsecond_To_Millisecond :: 1.0 / 1000.0
|
||||
Microsecond_To_Second :: 1.0 / (1000.0 * 1000.0)
|
||||
|
||||
Millisecond_To_Nanosecond :: 1000.0 * 1000.0
|
||||
Millisecond_To_Microsecond :: 1000.0
|
||||
Millisecond_To_Second :: 1.0 / 1000.0
|
||||
|
||||
Second_To_Nanosecond :: 1000.0 * 1000.0 * 1000.0
|
||||
Second_To_Microsecnd :: 1000.0 * 1000.0
|
||||
Second_To_Millisecond :: 1000.0
|
||||
|
||||
NS_To_MS :: Nanosecond_To_Millisecond
|
||||
NS_To_US :: Nanosecond_To_Microsecond
|
||||
NS_To_S :: Nanosecond_To_Second
|
||||
|
||||
US_To_NS :: Microsecond_To_Nanosecond
|
||||
US_To_MS :: Microsecond_To_Millisecond
|
||||
US_To_S :: Microsecond_To_Second
|
||||
|
||||
MS_To_NS :: Millisecond_To_Nanosecond
|
||||
MS_To_US :: Millisecond_To_Microsecond
|
||||
MS_To_S :: Millisecond_To_Second
|
||||
|
||||
S_To_NS :: Second_To_Nanosecond
|
||||
S_To_US :: Second_To_Microsecnd
|
||||
S_To_MS :: Second_To_Millisecond
|
||||
|
||||
Frametime_High_Perf_Threshold_MS :: 1 / 240.0
|
@ -126,6 +126,8 @@ AppConfig :: struct {
|
||||
cam_zoom_sensitivity_smooth : f32,
|
||||
cam_zoom_sensitivity_digital : f32,
|
||||
|
||||
engine_refresh_hz : uint,
|
||||
|
||||
ui_resize_border_width : uint,
|
||||
}
|
||||
|
||||
@ -148,11 +150,14 @@ State :: struct {
|
||||
monitor_id : i32,
|
||||
monitor_refresh_hz : i32,
|
||||
|
||||
engine_refresh_hz : i32,
|
||||
engine_refresh_target : i32,
|
||||
sleep_is_granular : b32,
|
||||
|
||||
frametime_delta_seconds : f64,
|
||||
frametime_delta_ns : Duration,
|
||||
frametime_delta_seconds : f64,
|
||||
frametime_delta_ms : f64,
|
||||
frametime_delta_ns : Duration,
|
||||
frametime_target_ms : f64,
|
||||
|
||||
frametime_elapsed_ms : f64,
|
||||
|
||||
font_firacode : FontID,
|
||||
font_squidgy_slimes : FontID,
|
||||
@ -195,12 +200,24 @@ Project :: struct {
|
||||
workspace : Workspace,
|
||||
}
|
||||
|
||||
Frame :: struct
|
||||
{
|
||||
pos : Vec2,
|
||||
size : Vec2,
|
||||
|
||||
ui : ^UI_Box,
|
||||
}
|
||||
|
||||
Workspace :: struct {
|
||||
name : string,
|
||||
|
||||
cam : Camera,
|
||||
zoom_target : f32,
|
||||
|
||||
frames : Array(Frame),
|
||||
|
||||
test_frame : Frame,
|
||||
|
||||
// TODO(Ed) : The workspace is mainly a 'UI' conceptually...
|
||||
ui : UI_State,
|
||||
}
|
||||
@ -223,8 +240,4 @@ DebugData :: struct {
|
||||
draggable_box_pos : Vec2,
|
||||
draggable_box_size : Vec2,
|
||||
box_original_size : Vec2,
|
||||
box_resize_started : b32,
|
||||
|
||||
ui_drag_delta : Vec2,
|
||||
ui_drag_start : Vec2,
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import "core:hash"
|
||||
import fmt_io "core:fmt"
|
||||
str_fmt :: fmt_io.printf
|
||||
str_fmt_tmp :: fmt_io.tprintf
|
||||
str_fmt_alloc :: fmt_io.aprintf
|
||||
str_fmt_builder :: fmt_io.sbprintf
|
||||
str_fmt_buffer :: fmt_io.bprintf
|
||||
str_to_file_ln :: fmt_io.fprintln
|
||||
@ -67,7 +68,10 @@ import "core:path/filepath"
|
||||
import str "core:strings"
|
||||
str_builder_to_string :: str.to_string
|
||||
import "core:time"
|
||||
Duration :: time.Duration
|
||||
Duration :: time.Duration
|
||||
duration_seconds :: time.duration_seconds
|
||||
duration_ms :: time.duration_milliseconds
|
||||
thread_sleep :: time.sleep
|
||||
import "core:unicode"
|
||||
is_white_space :: unicode.is_white_space
|
||||
import "core:unicode/utf8"
|
||||
|
@ -219,7 +219,7 @@ varena_allocator_proc :: proc(
|
||||
|
||||
old_memory_offset := uintptr(old_memory) + uintptr(old_size)
|
||||
current_offset := uintptr(arena.reserve_start) + uintptr(arena.commit_used)
|
||||
verify( old_memory_offset != current_offset, "Cannot resize existing allocation in vitual arena to a larger size unless it was the last allocated" )
|
||||
verify( old_memory_offset == current_offset, "Cannot resize existing allocation in vitual arena to a larger size unless it was the last allocated" )
|
||||
|
||||
new_region : []byte
|
||||
new_region, alloc_error = varena_alloc( arena, size - old_size, alignment, (mode != .Resize_Non_Zeroed), location )
|
||||
@ -228,7 +228,7 @@ varena_allocator_proc :: proc(
|
||||
return
|
||||
}
|
||||
|
||||
data := byte_slice( old_memory, size )
|
||||
data = byte_slice( old_memory, size )
|
||||
return
|
||||
|
||||
case .Query_Features:
|
||||
|
@ -1,52 +0,0 @@
|
||||
/* Windows Virtual Memory
|
||||
Windows is the only os getting special vmem definitions
|
||||
since I want full control of it for debug purposes.
|
||||
*/
|
||||
package sectr
|
||||
|
||||
import core_virtual "core:mem/virtual"
|
||||
import win32 "core:sys/windows"
|
||||
|
||||
when ODIN_OS == OS_Type.Windows {
|
||||
|
||||
WIN32_ERROR_INVALID_ADDRESS :: 487
|
||||
WIN32_ERROR_COMMITMENT_LIMIT :: 1455
|
||||
|
||||
@(require_results)
|
||||
virtual__reserve ::
|
||||
proc "contextless" ( base_address : uintptr, size : uint ) -> ( vmem : VirtualMemoryRegion, alloc_error : AllocatorError )
|
||||
{
|
||||
header_size :: cast(uint) size_of(VirtualMemoryRegion)
|
||||
|
||||
result := win32.VirtualAlloc( rawptr(base_address), header_size + size, win32.MEM_RESERVE, win32.PAGE_READWRITE )
|
||||
if result == nil {
|
||||
alloc_error = .Out_Of_Memory
|
||||
return
|
||||
}
|
||||
result = win32.VirtualAlloc( rawptr(base_address), header_size, win32.MEM_COMMIT, win32.PAGE_READWRITE )
|
||||
if result == nil
|
||||
{
|
||||
switch err := win32.GetLastError(); err
|
||||
{
|
||||
case 0:
|
||||
alloc_error = .Invalid_Argument
|
||||
return
|
||||
|
||||
case WIN32_ERROR_INVALID_ADDRESS, WIN32_ERROR_COMMITMENT_LIMIT:
|
||||
alloc_error = .Out_Of_Memory
|
||||
return
|
||||
}
|
||||
|
||||
alloc_error = .Out_Of_Memory
|
||||
return
|
||||
}
|
||||
|
||||
vmem.base_address = cast(^VirtualMemoryRegionHeader) result
|
||||
vmem.reserve_start = memory_after_header(vmem.base_address)
|
||||
vmem.reserved = size
|
||||
vmem.committed = header_size
|
||||
alloc_error = .None
|
||||
return
|
||||
}
|
||||
|
||||
} // END: ODIN_OS == runtime.Odin_OS_Type.Windows
|
112
code/grime_windows.odin
Normal file
112
code/grime_windows.odin
Normal file
@ -0,0 +1,112 @@
|
||||
package sectr
|
||||
|
||||
import "core:c"
|
||||
import "core:c/libc"
|
||||
import "core:fmt"
|
||||
import core_virtual "core:mem/virtual"
|
||||
import "core:strings"
|
||||
import win32 "core:sys/windows"
|
||||
|
||||
when ODIN_OS == OS_Type.Windows {
|
||||
|
||||
thread__highres_wait :: proc( desired_ms : f64, loc := #caller_location ) -> b32
|
||||
{
|
||||
// label_backing : [1 * Megabyte]u8
|
||||
// label_arena : Arena
|
||||
// arena_init( & label_arena, slice_ptr( & label_backing[0], len(label_backing)) )
|
||||
// label_u8 := str_fmt_tmp( "SECTR: WAIT TIMER")//, allocator = arena_allocator( &label_arena) )
|
||||
// label_u16 := win32.utf8_to_utf16( label_u8, context.temp_allocator) //arena_allocator( & label_arena) )
|
||||
|
||||
timer := win32.CreateWaitableTimerExW( nil, nil, win32.CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, win32.TIMER_ALL_ACCESS )
|
||||
if timer == nil {
|
||||
msg := str_fmt_tmp("Failed to create win32 timer - ErrorCode: %v", win32.GetLastError() )
|
||||
log( msg, LogLevel.Warning, loc)
|
||||
return false
|
||||
}
|
||||
|
||||
due_time := win32.LARGE_INTEGER(desired_ms * MS_To_NS)
|
||||
result := win32.SetWaitableTimerEx( timer, & due_time, 0, nil, nil, nil, 0 )
|
||||
if ! result {
|
||||
msg := str_fmt_tmp("Failed to set win32 timer - ErrorCode: %v", win32.GetLastError() )
|
||||
log( msg, LogLevel.Warning, loc)
|
||||
return false
|
||||
}
|
||||
|
||||
WAIT_ABANDONED : win32.DWORD : 0x00000080
|
||||
WAIT_IO_COMPLETION : win32.DWORD : 0x000000C0
|
||||
WAIT_OBJECT_0 : win32.DWORD : 0x00000000
|
||||
WAIT_TIMEOUT : win32.DWORD : 0x00000102
|
||||
WAIT_FAILED : win32.DWORD : 0xFFFFFFFF
|
||||
|
||||
wait_result := win32.WaitForSingleObjectEx( timer, win32.INFINITE, win32.BOOL(true) )
|
||||
switch wait_result
|
||||
{
|
||||
case WAIT_ABANDONED:
|
||||
msg := str_fmt_tmp("Failed to wait for win32 timer - Error: WAIT_ABANDONED" )
|
||||
log( msg, LogLevel.Error, loc)
|
||||
return false
|
||||
|
||||
case WAIT_IO_COMPLETION:
|
||||
msg := str_fmt_tmp("Waited for win32 timer: Ended by APC queued to the thread" )
|
||||
log( msg, LogLevel.Error, loc)
|
||||
return false
|
||||
|
||||
case WAIT_OBJECT_0:
|
||||
msg := str_fmt_tmp("Waited for win32 timer- Reason : WAIT_OBJECT_0" )
|
||||
log( msg, loc = loc)
|
||||
return false
|
||||
|
||||
case WAIT_FAILED:
|
||||
msg := str_fmt_tmp("Waited for win32 timer failed - ErrorCode: $v", win32.GetLastError() )
|
||||
log( msg, LogLevel.Error, loc)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
set__scheduler_granularity :: proc "contextless" ( desired_ms : u32 ) -> b32 {
|
||||
return win32.timeBeginPeriod( desired_ms ) == win32.TIMERR_NOERROR
|
||||
}
|
||||
|
||||
WIN32_ERROR_INVALID_ADDRESS :: 487
|
||||
WIN32_ERROR_COMMITMENT_LIMIT :: 1455
|
||||
|
||||
@(require_results)
|
||||
virtual__reserve ::
|
||||
proc "contextless" ( base_address : uintptr, size : uint ) -> ( vmem : VirtualMemoryRegion, alloc_error : AllocatorError )
|
||||
{
|
||||
header_size :: cast(uint) size_of(VirtualMemoryRegion)
|
||||
|
||||
result := win32.VirtualAlloc( rawptr(base_address), header_size + size, win32.MEM_RESERVE, win32.PAGE_READWRITE )
|
||||
if result == nil {
|
||||
alloc_error = .Out_Of_Memory
|
||||
return
|
||||
}
|
||||
result = win32.VirtualAlloc( rawptr(base_address), header_size, win32.MEM_COMMIT, win32.PAGE_READWRITE )
|
||||
if result == nil
|
||||
{
|
||||
switch err := win32.GetLastError(); err
|
||||
{
|
||||
case 0:
|
||||
alloc_error = .Invalid_Argument
|
||||
return
|
||||
|
||||
case WIN32_ERROR_INVALID_ADDRESS, WIN32_ERROR_COMMITMENT_LIMIT:
|
||||
alloc_error = .Out_Of_Memory
|
||||
return
|
||||
}
|
||||
|
||||
alloc_error = .Out_Of_Memory
|
||||
return
|
||||
}
|
||||
|
||||
vmem.base_address = cast(^VirtualMemoryRegionHeader) result
|
||||
vmem.reserve_start = memory_after_header(vmem.base_address)
|
||||
vmem.reserved = size
|
||||
vmem.committed = header_size
|
||||
alloc_error = .None
|
||||
return
|
||||
}
|
||||
|
||||
} // END: ODIN_OS == runtime.Odin_OS_Type.Windows
|
@ -293,18 +293,19 @@ main :: proc()
|
||||
|
||||
delta_ns : Duration
|
||||
|
||||
host_tick := time.tick_now()
|
||||
|
||||
// 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.tick( duration_seconds( delta_ns ), delta_ns )
|
||||
sectr_api.clean_frame()
|
||||
|
||||
delta_ns = time.tick_lap_time( & start_tick )
|
||||
delta_ns = time.tick_lap_time( & host_tick )
|
||||
host_tick = time.tick_now()
|
||||
}
|
||||
|
||||
// Determine how the run_cyle completed, if it failed due to an error,
|
||||
@ -318,5 +319,7 @@ main :: proc()
|
||||
|
||||
log("Succesfuly closed")
|
||||
file_close( logger.file )
|
||||
file_rename( logger.file_path, path_logger_finalized )
|
||||
// TODO(Ed) : Add string interning!!!!!!!!!
|
||||
// file_rename( logger.file_path, path_logger_finalized )
|
||||
file_rename( str_fmt_tmp( "%s/sectr.log", Path_Logs), path_logger_finalized )
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ render :: proc()
|
||||
render_mode_2d()
|
||||
//region Render Screenspace
|
||||
{
|
||||
fps_msg := str_fmt_tmp( "FPS: %v", rl.GetFPS() )
|
||||
fps_msg := str_fmt_tmp( "FPS: %f", 1 / (frametime_elapsed_ms * MS_To_S) )
|
||||
fps_msg_width := measure_text_size( fps_msg, default_font, 16.0, 0.0 ).x
|
||||
fps_msg_pos := screen_get_corners().top_right - { fps_msg_width, 0 }
|
||||
debug_draw_text( fps_msg, fps_msg_pos, 16.0, color = rl.GREEN )
|
||||
@ -43,15 +43,18 @@ render :: proc()
|
||||
position.y += debug.draw_debug_text_y
|
||||
|
||||
content := str_fmt_buffer( draw_text_scratch[:], format, ..args )
|
||||
debug_draw_text( content, position, 16.0 )
|
||||
debug_draw_text( content, position, 14.0 )
|
||||
|
||||
debug.draw_debug_text_y += 16
|
||||
debug.draw_debug_text_y += 14
|
||||
}
|
||||
|
||||
// Debug Text
|
||||
{
|
||||
debug_text( "Screen Width : %v", rl.GetScreenWidth () )
|
||||
debug_text( "Screen Height: %v", rl.GetScreenHeight() )
|
||||
debug_text( "frametime_target_ms : %f ms", frametime_target_ms )
|
||||
debug_text( "frametime : %f ms", frametime_delta_ms )
|
||||
debug_text( "frametime_last_elapsed_ms : %f ms", frametime_elapsed_ms )
|
||||
if replay.mode == ReplayMode.Record {
|
||||
debug_text( "Recording Input")
|
||||
}
|
||||
@ -70,10 +73,6 @@ render :: proc()
|
||||
rl.DrawCircleV( cursor_pos, 10, Color_White_A125 )
|
||||
}
|
||||
|
||||
debug_text( "ui_drag_start : %v", debug.ui_drag_start )
|
||||
debug_text( "ui_drag_delta : %v", debug.ui_drag_delta )
|
||||
debug_text( "Draggable Box Pos: %v", debug.draggable_box_pos )
|
||||
|
||||
debug.draw_debug_text_y = 50
|
||||
}
|
||||
//endregion Render Screenspace
|
||||
|
Loading…
Reference in New Issue
Block a user