From 0f5f9c18b167d23b25e210be3ccc07a61dab10b7 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sat, 1 Feb 2025 09:29:31 -0500 Subject: [PATCH] Update readme, build scripts Add incremental build check for stb truetype lib --- .gitignore | 4 ++-- Readme.md | 16 +++++++++------- scripts/build.ps1 | 21 ++++++++++++--------- scripts/update_deps.ps1 | 11 ++++++++--- thirdparty/stb/lib/stb_truetype.lib | Bin 380536 -> 380638 bytes 5 files changed, 31 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 257aa8c..6a640b8 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,5 @@ Sectr.sublime-project Sectr.sublime-workspace ols.json .vscode/settings.json -# thirdparty -# toolchain +thirdparty +toolchain diff --git a/Readme.md b/Readme.md index 1b9d6b7..733f76c 100644 --- a/Readme.md +++ b/Readme.md @@ -22,16 +22,19 @@ The dependencies are: * Remove implicit assignments for container allocators in the Base and Core packages * I did not enjoy bug hunting a memory corruption because I mistakenly didn't properly initialize a core container with their designated initiatizer: new, make, or init. * See fork Readme for which procedures were changed.. -* Odin repo's base, core, and vendor(raylib) libaries -* An ini parser +* Odin repo's base, core, and some of vendor +* [VEFontCache-Odin](https://github.com/Ed94/VEFontCache-Odin): Text rendering & shaping library created for this prototype +* [stb_truetype-odin](https://github.com/Ed94/stb_truetype-odin): Variant of the stb/truetype package in odin's vendor collection made for VEFontCache-Odin +* [harfbuzz-odin](https://github.com/Ed94/harfbuzz-odin): Custom repo with tailor made bindings for VEFontCache-Odin +* [sokol-odin (Sectr Fork)](https://github.com/Ed94/sokol-odin) +* [sokol-tools](https://github.com/floooh/sokol-tools) +* Powershell (if you want to use my build scripts) * backtrace (not used yet) * freetype (not used yet) -* harfbuzz -* sokol -* sokol-tools -* Powershell (if you want to use my build scripts) +* Eventually some config parser (maybe I'll use metadesk, or [ini](https://github.com/laytan/odin-ini-parser)) The project is so far in a "codebase boostrapping" phase. Most the work being done right now is setting up high performance linear zoom rendering for text and UI. +Text has recently hit sufficient peformance targets, and now inital UX has become the focus. The project's is organized into 2 runtime modules sectr_host & sectr. The host module loads the main module & its memory. Hot-reloading it's dll when it detects a change. @@ -43,7 +46,6 @@ Codebase organization: * Has the following definitions: startup, shutdown, reload, tick, clean_frame (which host hooks up to when managing the client dll) * Will handle async ops. * Font Provider: Manages fonts. - * Bulk of visualization must be able to render text effectively * Bulk of implementation maintained as a separate library: [VEFontCache-Odin](https://github.com/Ed94/VEFontCache-Odin) * 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. diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 8e1151e..40c9055 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -141,22 +141,25 @@ push-location $path_root $path_font = join-path $path_code 'font' - $module_scripts = $PSScriptRoot - $package_grime = join-path $path_code 'grime' - $package_VEFontCache = join-path $path_font 'VEFontCache' - $module_host = join-path $path_code 'host' - $module_sectr = join-path $path_code 'sectr' + $module_scripts = $PSScriptRoot + $package_grime = join-path $path_code 'grime' + $package_VEFontCache = join-path $path_font 'VEFontCache' + $package_stb_truetype = join-path $path_thirdparty 'stb' + $module_host = join-path $path_code 'host' + $module_sectr = join-path $path_code 'sectr' if ($force){ mark-ModuleDirty $module_scripts mark-ModuleDirty $package_VEFontCache + mark-ModuleDirty $package_stb_truetype mark-ModuleDirty $package_grime mark-ModuleDirty $module_sectr mark-ModuleDirty $module_host } - $module_scripts_dirty = check-ModuleForChanges $module_scripts - $pkg_VEFontCache_dirty = check-ModuleForChanges $package_VEFontCache - $pkg_grime_dirty = check-ModuleForChanges $package_grime + $module_scripts_dirty = check-ModuleForChanges $module_scripts + $pkg_VEFontCache_dirty = check-ModuleForChanges $package_VEFontCache + $pkg_stb_truetype_dirty = check-ModuleForChanges $package_stb_truetype + $pkg_grime_dirty = check-ModuleForChanges $package_grime $pkg_collection_codebase = 'codebase=' + $path_code $pkg_collection_thirdparty = 'thirdparty=' + $path_thirdparty @@ -174,7 +177,7 @@ push-location $path_root function build-sectr { - $should_build = (check-ModuleForChanges $module_sectr) -or $pkg_grime_dirty -or $pkg_VEFontCache_dirty -or $module_scripts_dirty + $should_build = (check-ModuleForChanges $module_sectr) -or $pkg_grime_dirty -or $pkg_VEFontCache_dirty -or $pkg_stb_truetype_dirty -or $module_scripts_dirty if ( -not( $should_build)) { write-host 'Skipping sectr build, module up to date' return $module_unchanged diff --git a/scripts/update_deps.ps1 b/scripts/update_deps.ps1 index f69aad3..985e623 100644 --- a/scripts/update_deps.ps1 +++ b/scripts/update_deps.ps1 @@ -77,8 +77,13 @@ $path_devshell = join-path $path_helpers 'devshell.ps1' $path_stb = join-path $path_thirdparty 'stb' $path_stb_src = join-path $path_stb 'src' -push-location $path_stb_src +$pkg_stb_truetype_dirty = check-ModuleForChanges $path_stb -& '.\build.bat' +if ( $pkg_stb_truetype_dirty) +{ + push-location $path_stb_src -pop-location + & '.\build.bat' + + pop-location +} diff --git a/thirdparty/stb/lib/stb_truetype.lib b/thirdparty/stb/lib/stb_truetype.lib index f645f2e098eaae858f91b7c7481a7f9130409f2c..715881fab2067308862d014c71962aa8ed745ff0 100644 GIT binary patch delta 17513 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 M*J|~{Gor))0c@&ci~s-t delta 17440 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 TzsVu0@*>>F8Xv3G4+{SeE*>5P