Compare commits

..

281 commits
Chat ... master

Author SHA1 Message Date
Шурупов Илья Викторович
0f15c37c2e tmp
Some checks failed
Windows / build (push) Has been cancelled
CMake on a single platform / build (push) Has been cancelled
CMake / build (push) Has been cancelled
2025-11-24 18:24:00 +03:00
Шурупов Илья Викторович
a7b9feaedc add simple ring buffer 2025-11-24 12:34:19 +03:00
Шурупов Илья Викторович
35a2297ab2 version bump 2025-11-24 12:26:32 +03:00
Ilya Shurupov
44bc283f4f tweaks 2024-12-13 13:33:49 +03:00
IlyaShurupov
822c60d839 3D Editor treaks 2024-11-24 22:41:15 +03:00
IlyaShurupov
0b279163de Raster render updates 2024-11-24 22:41:15 +03:00
IlyaShurupov
543534bf61 Tunes 2024-11-24 22:41:15 +03:00
Ilya Shurupov
ba10834602 Update LICENSE 2024-11-24 22:41:15 +03:00
Ilya Shurupov
49c2cadb0a add setBuff method to Buffer2D 2024-11-24 22:41:15 +03:00
IlyaShurupov
e10a494223 Widgets Additions and sketch3d new gui 2024-11-24 22:41:15 +03:00
Ilya Shurupov
afad2c80e5 Windows update 2024-11-24 22:41:15 +03:00
IlyaShurupov
c41dc20132 Replace Old Widgets 2024-11-24 22:41:15 +03:00
IlyaShurupov
03da5e41d6 Slider widget 2024-11-24 22:41:15 +03:00
IlyaShurupov
b1ba1c2975 Widget Fixes 2024-11-24 22:41:15 +03:00
IlyaShurupov
8c4ba37e59 Scrolling layout 2024-11-24 22:41:15 +03:00
IlyaShurupov
c7496c7b42 Focus locking and popups 2024-11-24 22:41:15 +03:00
IlyaShurupov
96b293d1b5 Refactor Layout Manager 2024-11-24 22:41:15 +03:00
IlyaShurupov
e00dec67ba Reorganize code in widgets 2024-11-24 22:41:15 +03:00
IlyaShurupov
837d8dc507 Refactor done 2024-11-24 22:41:15 +03:00
IlyaShurupov
d6025bc4e0 Refactor idea done unstable 2024-11-24 22:41:15 +03:00
IlyaShurupov
0ebbe75b6e Refactor layout and size policies - dirty 2024-11-24 22:41:15 +03:00
IlyaShurupov
5de5dbba23 Update Master 2024-11-24 22:41:15 +03:00
IlyaShurupov
c94f5144e7 Sizing fixes 2024-11-24 22:41:15 +03:00
IlyaShurupov
a36386cc20 Fix sizing issues and others 2024-11-24 22:41:15 +03:00
IlyaShurupov
0b73f8037b Initial size handling 2024-11-24 22:41:15 +03:00
IlyaShurupov
9f9dcd5882 Refactor fixes 2024-11-24 22:41:15 +03:00
IlyaShurupov
164359f6aa Refactor in a good state 2024-11-24 22:41:14 +03:00
IlyaShurupov
4b6e7da994 Refactor 2024-11-24 22:41:14 +03:00
IlyaShurupov
279cf58dff WidgetsNew Initial 2024-11-24 22:41:14 +03:00
IlyaShurupov
3f49ee11ae Lovelly bug in Interval Tree 2024-11-24 22:41:14 +03:00
IlyaShurupov
5e3f5594b8 Fixes and improvements to the graphics module 2024-11-24 22:41:14 +03:00
IlyaShurupov
860474654a Update global time interface 2024-11-24 22:41:14 +03:00
IlyaShurupov
3be2425665 Buffer erase functionality 2024-11-24 22:41:14 +03:00
IlyaShurupov
3b27fe17c1 Math tunes 2024-11-24 22:41:14 +03:00
IlyaShurupov
c3b563a032 fix floating widget 2024-11-24 22:41:14 +03:00
IlyaShurupov
aa141405c6 widgets tunes 2024-11-24 22:41:14 +03:00
IlyaShurupov
da6990ddc8 Cleanup widgets 2024-11-24 22:41:14 +03:00
IlyaShurupov
242cd93589 New DockspaceWidget Stable 2024-11-24 22:41:14 +03:00
IlyaShurupov
9cc4819524 dockspce widget initial 2024-11-24 22:41:14 +03:00
IlyaShurupov
fcd0209710 widgets cleanups 2024-11-24 22:41:14 +03:00
IlyaShurupov
4a557d7e5c gui updates 2024-11-24 22:41:14 +03:00
IlyaShurupov
a55a5ec5cc awidgets 2024-11-24 22:41:14 +03:00
IlyaShurupov
c87e5a25d5 dirty 2024-11-24 22:41:14 +03:00
IlyaShurupov
285ca80b4b new widgets 2024-11-24 22:41:14 +03:00
Ilya Shurupov
5cc982fa00 Update cmake-single-platform.yml 2024-11-24 22:41:14 +03:00
Ilya Shurupov
2bc06cdd5a Update cmake-single-platform.yml 2024-11-24 22:41:14 +03:00
Ilya Shurupov
25236f82c3 Update cmake-single-platform.yml 2024-11-24 22:41:14 +03:00
Ilya Shurupov
22e6967ae2 Update cmake-single-platform.yml 2024-11-24 22:41:14 +03:00
Ilya Shurupov
aa7bf32940 Update cmake-single-platform.yml 2024-11-24 22:41:14 +03:00
IlyaShurupov
8b54ca0216 add oidn 2024-11-24 22:41:14 +03:00
IlyaShurupov
351a5d842e fix ray tracer projection plane 2024-11-24 22:41:14 +03:00
IlyaShurupov
39c3d88f7a update todo 2024-11-24 22:41:14 +03:00
IlyaShurupov
5ac4d56d32 3D editor stable with path tracer 2024-11-24 22:41:14 +03:00
IlyaShurupov
8bec5d1ab7 Editor multyrender initial 2024-11-24 22:41:14 +03:00
IlyaShurupov
e32e5e77d1 3D scene stable 2024-11-24 22:41:14 +03:00
IlyaShurupov
938616d989 clean up 2024-11-24 22:41:14 +03:00
IlyaShurupov
3bc43612ef Use scene module in editor 2024-11-24 22:41:14 +03:00
IlyaShurupov
5c90192c9f 3D Scene initial 2024-11-24 22:41:14 +03:00
IlyaShurupov
805c891557 Update TODO regargin 3d framework 2024-11-24 22:41:14 +03:00
IlyaShurupov
3cc8dbc102 Add albedo output to the raytracer 2024-11-24 22:41:14 +03:00
IlyaShurupov
8bfe44b3cd Resize frame buffer method added 2024-11-24 22:41:14 +03:00
IlyaShurupov
bc29860385 use x11 as windowing platform with glfw for now 2024-11-24 22:41:14 +03:00
Ilya Shurupov
b206e4444e Update cmake-single-platform.yml 2024-11-24 22:41:14 +03:00
Ilya Shurupov
60b5f08f65 Update cmake-single-platform.yml 2024-11-24 22:41:14 +03:00
Ilya Shurupov
1ec84044be Update cmake-single-platform.yml 2024-11-24 22:41:14 +03:00
elushaX
6b77faced8 Windows update 2024-11-24 22:41:14 +03:00
IlyaShurupov
19f492dff1 updating submodule 2024-11-24 22:41:14 +03:00
IlyaShurupov
0f8fb5c580 Update widgets 2024-11-24 22:41:14 +03:00
IlyaShurupov
35cb553ecb update widgets 2024-11-24 22:41:14 +03:00
IlyaShurupov
1767b65c7e update todo 2024-11-24 22:41:14 +03:00
IlyaShurupov
90244934d9 Update widgets module. Raster example initial. 2024-11-24 22:41:14 +03:00
Ilya Shurupov
aa10424fbb Update TODO 2024-11-24 22:41:14 +03:00
IlyaShurupov
0192d58fa4 profiling avl 2024-11-24 22:41:14 +03:00
IlyaShurupov
db1a6b35ef AVL Tree refactor 2024-11-24 22:41:14 +03:00
Ilya Shurupov
92d8b04cf8 Update TODO 2024-11-24 22:41:14 +03:00
IlyaShurupov
fc00a83f2e dont copy node data in tree delete operation - just swap nodes 2024-11-24 22:41:14 +03:00
IlyaShurupov
13bcbcb23f update numeric key interface 2024-11-24 22:41:14 +03:00
IlyaShurupov
3148e2c020 remove extra layer of redirection in avl tree 2024-11-24 22:41:14 +03:00
IlyaShurupov
4d381d62e4 Tree. remove redunant function 2024-11-24 22:41:14 +03:00
IlyaShurupov
715175085e Method object refactor 2024-11-24 22:41:14 +03:00
IlyaShurupov
714bdaef12 remove initializer callbacks from method object 2024-11-24 22:41:14 +03:00
IlyaShurupov
88b78d907a clean up null object 2024-11-24 22:41:14 +03:00
IlyaShurupov
24f9d8acae Separate objects context and interface 2024-11-24 22:41:14 +03:00
IlyaShurupov
cf3f8dbc9c new object creation interface 2024-11-24 22:41:14 +03:00
IlyaShurupov
ca1ae75b07 fix typos 2024-11-24 22:41:14 +03:00
IlyaShurupov
9e2e7f5809 remove macros use in objects mofule 2024-11-24 22:41:14 +03:00
IlyaShurupov
c6260f7c48 fix warnings 2024-11-24 22:41:14 +03:00
IlyaShurupov
f8c82b7e29 clean up object module 2024-11-24 22:41:14 +03:00
IlyaShurupov
e78885d452 dont use NULL macro 2024-11-24 22:41:14 +03:00
IlyaShurupov
9d01ba2c8a Apply cpp naming to files 2024-11-24 22:41:14 +03:00
IlyaShurupov
89eec0e329 remove objects readme 2024-11-24 22:41:14 +03:00
IlyaShurupov
9054ed9f4a Restore buildbot status 2024-11-24 22:41:14 +03:00
IlyaShurupov
f10f04bac2 leak fix 2024-11-24 22:41:14 +03:00
IlyaShurupov
04f5ec30bc Update TODO 2024-11-24 22:41:14 +03:00
IlyaShurupov
1756ca026d RIP tp::Strings 2024-11-24 22:41:14 +03:00
IlyaShurupov
fa2d0aaa92 see ya later allocator 2024-11-24 22:41:14 +03:00
elushaX
57d5591d4a Update README.MD 2024-11-24 22:41:14 +03:00
elushaX
26cf35807d Create LICENSE 2024-11-24 22:41:14 +03:00
elushaX
e6e88193c2 Delete LICENSE 2024-11-24 22:41:14 +03:00
IlyaShurupov
9972960556 update readme 2024-11-24 22:41:14 +03:00
IlyaShurupov
ee805fd3d7 update readme 2024-11-24 22:41:14 +03:00
IlyaShurupov
ad6581cc18 add Oscript showcase 2024-11-24 22:41:14 +03:00
IlyaShurupov
9486cf0bee Edit readme 2024-11-24 22:41:14 +03:00
elushaX
6d8c64ac33 Add color sliders to sketch3d 2024-11-24 22:41:14 +03:00
IlyaShurupov
689bee9afc Updating README 2024-11-24 22:41:14 +03:00
IlyaShurupov
8451c56e93 Graphics refactor finished 2024-11-24 22:41:14 +03:00
IlyaShurupov
bfbdd0e33b osg stable 2024-11-24 22:41:14 +03:00
IlyaShurupov
5c18a10d11 Widget Example added 2024-11-24 22:41:14 +03:00
elushaX
a46a2167ba stable 2024-11-24 22:41:14 +03:00
Ilusha
6d02137dca tmp 2024-11-24 22:41:14 +03:00
Ilusha
fb374e71e4 graphics frame rate fixed 2024-11-24 22:41:14 +03:00
Ilusha
16af8dc809 tmp 2024-11-24 22:41:14 +03:00
IlyaShurupov
25fd52294f tmp 2024-11-24 22:41:14 +03:00
IlyaShurupov
84046e89be Graphics Example Stable 2024-11-24 22:41:14 +03:00
IlyaShurupov
e331fc1a34 Graphics Refactor Initial 2024-11-24 22:41:14 +03:00
IlyaShurupov
e0f92b32dc Adding new gui to Sketch3d 2024-11-24 22:41:14 +03:00
IlyaShurupov
8eae09591d Map invalid iterator fix 2024-11-24 22:41:14 +03:00
IlyaShurupov
9fd3183961 Small cleanup 2024-11-24 22:41:14 +03:00
IlyaShurupov
e065dc736b Fix bugs. Sketch3D stable. 2024-11-24 22:41:13 +03:00
Ilusha
cd8feaf2c0 Unstable & with drawing restored 2024-11-24 22:41:13 +03:00
Ilusha
1155067b26 A little clean up 2024-11-24 22:41:13 +03:00
Ilusha
3b389bdc17 CCompiled and runed with working visuals 2024-11-24 22:41:13 +03:00
Ilusha
2455f90550 trying to compile 2024-11-24 22:41:13 +03:00
Ilusha
f8c38a8a37 Sketch ini 2024-11-24 22:41:13 +03:00
IlyaShurupov
8866290d29 Linux fixes 2024-11-24 22:41:13 +03:00
Ilusha
0eaf22cc46 fix raytracer 2024-11-24 22:41:13 +03:00
Ilusha
69a17a609e tmp 2024-11-24 22:41:13 +03:00
Ilusha
afab59eb21 tmp 2024-11-24 22:41:13 +03:00
Ilusha
b8bcf58a29 Use UnitTest-Cpp library for testing 2024-11-24 22:41:13 +03:00
Ilusha
79d018ffb4 Recovering from github accound ban 2024-11-24 22:41:13 +03:00
Ilusha
5c7ee99d43 tmp 2024-11-24 22:41:13 +03:00
Ilusha
101ef375ef new testing framework 2024-11-24 22:41:13 +03:00
Ilusha
b56829ea26 tmp 2024-11-24 22:41:13 +03:00
Ilusha
0b3f780ec7 tmp 2024-11-24 22:41:13 +03:00
Ilusha
0494bf05af add parser chech for precedence in arithmetic expressions 2024-11-24 22:41:13 +03:00
Ilusha
8cc5f2f9f7 Fixing lalr on windows 2024-11-24 22:41:13 +03:00
Ilusha
69db2b82a4 Update cmake.yml 2024-11-24 22:41:13 +03:00
Ilusha
72e034ca32 try clang 14 2024-11-24 22:41:13 +03:00
Ilusha
06f70f3d2f try clang 16 in buildbot 2024-11-24 22:41:13 +03:00
Ilusha
f5dbbc1330 Update cmake.yml 2024-11-24 22:41:13 +03:00
Ilusha
d2dde03efb Adding windows build information 2024-11-24 22:41:13 +03:00
Ilusha
93266715c0 Edit todo and status texts 2024-11-24 22:41:13 +03:00
Ilusha
0f455dd33b Fix interval tree 2024-11-24 22:41:13 +03:00
Ilusha
3eadb0d726 stable 2024-11-24 22:41:13 +03:00
IlyaShurupov
6c92be58cd tmp 2024-11-24 22:41:13 +03:00
IlyaShurupov
2484ea9d9c parser error handling 2024-11-24 22:41:13 +03:00
IlyaShurupov
d4c85a3d86 Parser done implementing 2024-11-24 22:41:13 +03:00
IlyaShurupov
87fb15ed13 tmp 2024-11-24 22:41:13 +03:00
IlyaShurupov
b647271081 grammar done 2024-11-24 22:41:13 +03:00
IlyaShurupov
505b77da3f tmp 2024-11-24 22:41:13 +03:00
IlyaShurupov
8dc73bc1d5 tmp 2024-11-24 22:41:13 +03:00
Ilusha
1293136343 Replace object parser with lalr library 2024-11-24 22:41:13 +03:00
IlyaShurupov
8f87c3bc33 small fix 2024-11-24 22:41:13 +03:00
IlyaShurupov
30d4f194ba parsing loop closed 2024-11-24 22:41:13 +03:00
IlyaShurupov
aaeb6438a1 fix compile errors 2024-11-24 22:41:13 +03:00
IlyaShurupov
b2a1883369 cfg automata ini 2024-11-24 22:41:13 +03:00
IlyaShurupov
7a685e0634 cfg accepting 2024-11-24 22:41:13 +03:00
IlyaShurupov
2ebf650381 refactor regular automata 2024-11-24 22:41:13 +03:00
IlyaShurupov
b883f0029c CFG compiler ini 2024-11-24 22:41:13 +03:00
IlyaShurupov
70b6bf4d77 tmp 2024-11-24 22:41:13 +03:00
IlyaShurupov
6279323a84 tmp 2024-11-24 22:41:13 +03:00
IlyaShurupov
226c62f40b reg automata fixes 2024-11-24 22:41:13 +03:00
IlyaShurupov
7121917a5d tmp 2024-11-24 22:41:13 +03:00
Ilusha
dbd53719b0 tmp 2024-11-24 22:41:13 +03:00
IlyaShurupov
8f38095bec refactor and reuse Automatas. TODO : add test for automatas 2024-11-24 22:41:13 +03:00
IlyaShurupov
184f8dd1fe tmp 2024-11-24 22:41:13 +03:00
IlyaShurupov
fb8202f385 tmp 2024-11-24 22:41:13 +03:00
IlyaShurupov
56d63f2f18 Reuse Regular Automata functionality 2024-11-24 22:41:13 +03:00
IlyaShurupov
b3e5bf0941 Make parser template class 2024-11-24 22:41:13 +03:00
IlyaShurupov
419ebb43d1 TODO : Make RE Grammar template independent. Difine Unified grammar format. 2024-11-24 22:41:13 +03:00
IlyaShurupov
53b690dad9 tmp 2024-11-24 22:41:13 +03:00
IlyaShurupov
aecad978ec Adding implementation comments to Language 2024-11-24 22:41:13 +03:00
IlyaShurupov
b8f2380c60 Language Initial 2024-11-24 22:41:13 +03:00
IlyaShurupov
73897f11df Fix avl tree destructor 2024-11-24 22:41:13 +03:00
IlyaShurupov
94d1bb7f41 Adding more tests for interval tree 2024-11-24 22:41:13 +03:00
IlyaShurupov
782a041ba8 Interval Tree added 2024-11-24 22:41:13 +03:00
IlyaShurupov
8955a02d05 Update ImGui 2024-11-24 22:41:13 +03:00
IlyaShurupov
36efa46848 Refactor lib view 2024-11-24 22:41:13 +03:00
Ilusha
5106cc3b71 ini 2024-11-24 22:41:13 +03:00
Ilusha
466c0c36bd Update WindowsPlatform.yml 2024-11-24 22:41:13 +03:00
Ilusha
1a5d2934ae Update WindowsPlatform.yml 2024-11-24 22:41:13 +03:00
Ilusha
c34c41d0f5 Create WindowsPlatform.yml 2024-11-24 22:41:13 +03:00
Ilusha
0b63045503 Remove mutex class and use std 2024-11-24 22:41:13 +03:00
Ilusha
b26310439d Small fixes from windows 2024-11-24 22:41:13 +03:00
Ilusha
420bb37039 Adding support for windows and fixing some errors 2024-11-24 22:41:13 +03:00
IlyaShurupov
7660d58f26 Fix build errors 2024-11-24 22:41:13 +03:00
IlyaShurupov
1d48d390d3 Exclude glew from manual build duo to errors. Using precompiled packages. 2024-11-24 22:41:13 +03:00
Ilusha
5a3e07f4f3 Update cmake.yml change alsa package name 2024-11-24 22:41:12 +03:00
Ilusha
d5a08acf6d Update cmake.yml add alsa dep 2024-11-24 22:41:12 +03:00
IlyaShurupov
cd451d1c2a Refactor! 2024-11-24 22:41:12 +03:00
IlyaShurupov
cb09a6f5de Filtering 2024-11-24 22:41:12 +03:00
IlyaShurupov
98b5e4d182 Neet fixes 2024-11-24 22:41:12 +03:00
IlyaShurupov
b74c5bc5e5 Adding Music Playback 2024-11-24 22:41:12 +03:00
IlyaShurupov
a233b6a214 Side panel added 2024-11-24 22:41:12 +03:00
IlyaShurupov
dd71eba0ec LibraryViewer 2024-11-24 22:41:12 +03:00
IlyaShurupov
f6ba86aff8 CMake fixes 2024-11-24 22:41:12 +03:00
IlyaShurupov
fa72355799 Num Rec app and save & loading 2024-11-24 22:41:12 +03:00
IlyaShurupov
ee8027055e Number recognition Tuning 2024-11-24 22:41:12 +03:00
IlyaShurupov
4804e51ad7 NumRec Fixes 2024-11-24 22:41:12 +03:00
IlyaShurupov
90ce453b60 BackProp Fixes 2024-11-24 22:41:12 +03:00
IlyaShurupov
7e17b32a81 BackProp Initial 2024-11-24 22:41:12 +03:00
IlyaShurupov
91fb72bd49 Apply formating to all files. CLeanup 2024-11-24 22:41:08 +03:00
IlyaShurupov
b4ae5dde77 Complex toy classes & DataAnalysis initial 2024-11-24 22:38:04 +03:00
IlyaShurupov
e9daedd6ea RT Multisampling 2024-11-24 22:38:04 +03:00
IlyaShurupov
97a99f84f5 Save multiple buffers from RayTracer 2024-11-24 22:38:04 +03:00
IlyaShurupov
15c5576273 Adding simple test for RT 2024-11-24 22:38:04 +03:00
IlyaShurupov
4d00ef1296 Adding progress bar for rt application 2024-11-24 22:38:04 +03:00
IlyaShurupov
77db3f4ab5 Primitive sampling 2024-11-24 22:38:04 +03:00
IlyaShurupov
368ae81251 Adding normals 2024-11-24 22:38:04 +03:00
IlyaShurupov
a84cfabd60 RT Todo 2024-11-24 22:38:04 +03:00
IlyaShurupov
a3a79c87da Fix issue with submodule mapping for lua 2024-11-24 22:38:04 +03:00
IlyaShurupov
a62e665623 Adding scene files 2024-11-24 22:38:04 +03:00
IlyaShurupov
bb2b0b926f Adding lua scene description 2024-11-24 22:38:03 +03:00
IlyaShurupov
d6c326b83d tmp 2024-11-24 22:38:03 +03:00
IlyaShurupov
eb133745f9 Simple Normals Rendering 2024-11-24 22:38:03 +03:00
IlyaShurupov
b2fa4c4266 Bug fixes 2024-11-24 22:38:03 +03:00
IlyaShurupov
15b56a876a RayTracer Initial Framework setup 2024-11-24 22:38:03 +03:00
IlyaShurupov
25b66804a4 Update Clang Format 2024-11-24 22:38:03 +03:00
IlushaShurupov
74aaf9a0a1 Adding outdated source code into master 2024-11-24 22:38:03 +03:00
IlushaShurupov
be206950f0 Updated TODO 2024-11-24 22:38:03 +03:00
IlushaShurupov
7b276e1005 LR(1) Parser Initial 2024-11-24 22:38:03 +03:00
IlushaShurupov
0e4f4228de Checking for non productive rules and loops in cfg 2024-11-24 22:38:03 +03:00
IlushaShurupov
16115b483a CFG remove unused rules 2024-11-24 22:38:03 +03:00
IlushaShurupov
2c8151ec3e Adding simple test fot cf grammar 2024-11-24 22:38:03 +03:00
IlushaShurupov
24d554abc3 Fixing list copy and grammar sentence generation 2024-11-24 22:38:03 +03:00
IlushaShurupov
ffb533ec9a Improve module initialization log 2024-11-24 22:38:03 +03:00
IlushaShurupov
d9ffb61712 Fixin cfg 2024-11-24 22:38:03 +03:00
IlushaShurupov
f5e9b041cd Fixin map 2024-11-24 22:38:03 +03:00
IlushaShurupov
259bf5a485 Generate sentences from cf grammar. Fix list initialization from copy constructor 2024-11-24 22:38:03 +03:00
IlushaShurupov
92e772cde1 Fixing tokenizer bug 2024-11-24 22:38:03 +03:00
IlushaShurupov
a938bf9bb1 CF Grammar improvements 2024-11-24 22:38:03 +03:00
IlushaShurupov
8feeb3d1c1 CF Grammar Initial 2024-11-24 22:38:03 +03:00
IlushaShurupov
42ee676bc9 Parser Initial 2024-11-24 22:38:03 +03:00
IlushaShurupov
cef0db6fb1 Adding some tokinizer checks for strings and comments 2024-11-24 22:38:03 +03:00
IlushaShurupov
4825d61486 Editing TODO 2024-11-24 22:38:03 +03:00
Ilusha
64960c6aff Update cmake.yml - sudo apt-get update before installing pacages 2024-11-24 22:38:03 +03:00
IlushaShurupov
17ad239692 Adding objects GUI initial. Changing TODO. Some fixes along side 2024-11-24 22:38:03 +03:00
IlushaShurupov
f579a969ce "Added new test 'Complex' and improved error debugging"
This revision adds a complex test to the 'TestInterpreter.cpp' file to test functionalities such as classes, variable initializations, loops, conditionals and methods in the interpreter. The token parser has also been updated with a reset method in the 'parser.cpp' file for cleaning up any previous state before parsing a new script. This ensures the parser starts fresh for each new parse request. It also improves the debugging process in 'function.cpp' by printing the description of parser errors. Few completed tasks are removed from the TODO list.
2024-11-24 22:38:03 +03:00
IlushaShurupov
3f4f2caf1f Load and destroy methods revised for proper reference counting
The update enhances object management by involving scope-based reference counting. The change affects loading and destruction operations in the Object and several other classes, ensuring the release or retention of objects adhere to their usage context. A function for logging type data has also been introduced to provide better clarity during debugging. Also, tests in script & interpreter have been altered to run in separate module initializations to avoid cross-test interference. Overall, it provides better memory management and dependable tests.
2024-11-24 22:38:03 +03:00
IlushaShurupov
ab0edfc302 Add Interpreter tests and improve Parser error logging
A set of tests for the InterpreterObject has been added to enhance its reliability and maintainability. The tests check the essential functionalities such as its creation, execution, saving, loading, and destruction. Furthermore, the error logging for the Parser has been improved, now providing more precise location of detected errors. The changes improve the robustness and debugability of the code.
2024-11-24 22:38:03 +03:00
IlushaShurupov
e0eb6e138d Refactor save size calculation with SaveSizeCounter
SaveSizeCounter is introduced and used for calculating the save size of objects. The previous method of calculating save size directly in each class was replaced with a call to the SaveSizeCounter's calc method. This results in a cleaner, more maintainable code as the size calculation logic is now centralized in one class. It is more efficient and scalable as any changes to the calculation can be made in one place and will be reflected everywhere.
2024-11-24 22:38:03 +03:00
IlushaShurupov
a679ab1c4b Objects adding dict test & fixes 2024-11-24 22:38:03 +03:00
IlushaShurupov
63029e6083 Adding Simple Objest test. Fixes some bugs 2024-11-24 22:38:03 +03:00
IlushaShurupov
edf0548046 Objects Compiled 2024-11-24 22:38:03 +03:00
IlyaShurupov
31e420b311 Archiver Initial 2024-11-24 22:38:03 +03:00
IlushaShurupov
4a5877784b Generating permutations and small buffer checks 2024-11-24 22:38:03 +03:00
IlushaShurupov
d3df3dde09 Objects Initial 2024-11-24 22:38:01 +03:00
IlushaShurupov
94057d2a66 Objects Initial 2024-11-24 22:36:45 +03:00
IlushaShurupov
0f639ba3b1 Freeze on no memory available 2024-11-24 22:36:45 +03:00
IlushaShurupov
41f7d978a9 Graphics Animations & Renaming 2024-11-24 22:36:45 +03:00
Ilusha
1e2ca13a15 Update cmake.yml to build Graphics 2024-11-24 22:36:45 +03:00
IlushaShurupov
8df79328cd Reorganize a little 2024-11-24 22:36:45 +03:00
IlushaShurupov
c375472bbe Adding nanovg 2024-11-24 22:36:45 +03:00
IlushaShurupov
aaa08e4495 New placement header 2024-11-24 22:36:45 +03:00
IlushaShurupov
f52b351cac Graphics module Initial (And some more fixes embedded) 2024-11-24 22:36:45 +03:00
Ilusha
98132ca2f5 Update cmake.yml - checkout submodules 2024-11-24 22:36:45 +03:00
IlushaShurupov
e50cb9f0e2 Small changes 2024-11-24 22:36:45 +03:00
IlushaShurupov
8c600a1cdb Restructure Storage Module -> Connection module 2024-11-24 22:36:45 +03:00
IlushaShurupov
f60e73fc32 Restructure 2024-11-24 22:36:45 +03:00
IlushaShurupov
58db6fe058 Command Line INterpreter with fixes 2024-11-24 22:36:45 +03:00
IlushaShurupov
32c7512b69 Fix File test 2024-11-24 22:36:45 +03:00
IlushaShurupov
038e6c58cf Networking Initial 2024-11-24 22:36:45 +03:00
IlushaShurupov
d5dfb1c304 Storage initial 2024-11-24 22:36:45 +03:00
IlushaShurupov
bd1a6a44db Fixed bug in map 2024-11-24 22:36:45 +03:00
IlushaShurupov
f5cab30f21 CommandLine parser initial 2024-11-24 22:36:45 +03:00
IlushaShurupov
3846b91662 Adding Strings tests 2024-11-24 22:36:45 +03:00
Ilusha
e08f961707 Update cmake.yml 2024-11-24 22:36:45 +03:00
Ilusha
29ab5fa8a6 Update cmake.yml 2024-11-24 22:36:45 +03:00
Ilusha
54c44dbd6a Try coverage cmake.yml 2024-11-24 22:36:45 +03:00
IlushaShurupov
53aa0e34a8 Fixes 2024-11-24 22:36:45 +03:00
IlushaShurupov
f91b45643d Update Todo 2024-11-24 22:36:45 +03:00
IlushaShurupov
1aece0c617 Tokenizer Test 2024-11-24 22:36:45 +03:00
IlushaShurupov
6248c294b8 Tokenizer (No tests) 2024-11-24 22:36:45 +03:00
IlushaShurupov
f676e84521 Remove Cmd Arg parser for now 2024-11-24 22:36:45 +03:00
IlushaShurupov
1310bb78ad Tokenizer Initial 2024-11-24 22:36:45 +03:00
IlushaShurupov
0ec44ee2d1 Buffer 2d (No tests) 2024-11-24 22:36:45 +03:00
IlushaShurupov
ffa90323a4 Remove old testing 2024-11-24 22:36:45 +03:00
IlushaShurupov
f46ea7e0fb Testing 2024-11-24 22:36:45 +03:00
IlushaShurupov
b7560534c1 Removing TextEditor from strings for now 2024-11-24 22:36:45 +03:00
IlushaShurupov
eae8852832 Strings Initial 2024-11-24 22:36:45 +03:00
IlyaShurupov
2dff05d412 Update README.MD (#1) 2024-11-24 22:36:10 +03:00
540 changed files with 280533 additions and 56027 deletions

View file

@ -0,0 +1,21 @@
project(Widgets)
### ---------------------- Static Library --------------------- ###
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
file(GLOB HEADERS "./public/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
target_link_libraries(${PROJECT_NAME} PUBLIC Math Graphics Imgui)
### -------------------------- Applications -------------------------- ###
add_executable(SimpleGui examples/SimpleGUI.cpp)
target_link_libraries(SimpleGui ${PROJECT_NAME} ${GLEW_LIB})
target_include_directories(SimpleGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
add_executable(ChatGui examples/ChatGUI.cpp)
target_link_libraries(ChatGui ${PROJECT_NAME} ${GLEW_LIB})
target_include_directories(ChatGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
file(COPY "examples/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")

View file

@ -0,0 +1,34 @@
#include "ChatGUI.hpp"
#include "GraphicApplication.hpp"
using namespace tp;
class ExampleGUI : public Application {
public:
ExampleGUI() = default;
void processFrame(EventHandler* eventHandler, halnf delta) override {
auto rec = RectF({ 0, 0 }, mWindow->getSize());
mGui.updateConfigWrapper(mWidgetManager);
mGui.setArea(rec);
mGui.setVisible(true);
mGui.procWrapper(*eventHandler, rec);
}
void drawFrame(Canvas* canvas) override { mGui.drawWrapper(*canvas); }
private:
WidgetManager mWidgetManager;
ComplexWidget mGui;
};
int main() {
{
ExampleGUI gui;
gui.run();
}
}

View file

@ -0,0 +1,256 @@
#pragma once
#include "Widgets.hpp"
namespace tp {
class UserWidget : public Widget {
public:
UserWidget() = default;
void eventDraw(Canvas& canvas) override {
if (this->isFocus()) canvas.rect(this->mArea, mAccentColor, mRounding);
else canvas.rect(this->mArea, mBaseColor, mRounding);
canvas.text(mUser.c_str(), this->mArea, mFontSize, Canvas::CC, mPadding, mUserColor);
}
public:
void eventUpdateConfiguration(WidgetManager& wm) override {
wm.setActiveId("UserWidget");
mBaseColor = wm.getColor("Base", "Base");
mFontSize = wm.getNumber("Size", "FontSize");
mPadding = wm.getNumber("Padding", "Padding");
mUserColor = wm.getColor("ColUser", "Front");
mAccentColor = wm.getColor("Accent", "Accent");
mRounding = wm.getNumber("Rounding", "Rounding");
}
public:
std::string mUser = "UserName";
bool mIsHover = false;
RGBA mBaseColor;
RGBA mUserColor;
RGBA mAccentColor;
halnf mPadding = 0;
halnf mFontSize = 0;
halnf mRounding = 0;
};
class MessageWidget : public Widget {
public:
MessageWidget() = default;
void eventDraw(Canvas& canvas) override {
if (this->isFocus()) canvas.rect(this->mArea, mBaseColor, mRounding);
auto userName = this->mArea;
userName.w = 25;
auto content = this->mArea;
content.y = userName.y + userName.w;
content.w = this->mArea.w - userName.w;
canvas.text(mContent.c_str(), content, mFontSize, Canvas::LC, mPadding, mUserColorDim);
canvas.text(mUser.c_str(), userName, mFontSizeDim, Canvas::LC, mPadding, mUserColor);
}
void eventUpdateConfiguration(WidgetManager& wm) override {
wm.setActiveId("MessageWidget");
mBaseColor = wm.getColor("Base", "Base");
mFontSize = wm.getNumber("Size", "FontSize");
mFontSizeDim = wm.getNumber("SizeUser", "FontSizeDim");
mPadding = wm.getNumber("Padding", "Padding");
mUserColor = wm.getColor("UserColor", "Front");
mUserColorDim = wm.getColor("UserColorDim", "FrontDim");
mRounding = wm.getNumber("Rounding", "Rounding");
}
public:
std::string mContent = "Message Content";
std::string mUser = "UserName";
bool mIsHover = false;
RGBA mBaseColor;
RGBA mUserColor;
RGBA mUserColorDim;
halnf mPadding = 0;
halnf mFontSize = 0;
halnf mFontSizeDim = 0;
halnf mRounding = 0;
};
class LoginWidget : public Widget {
public:
explicit LoginWidget() {
mPass.mId = "pass";
mUser.mId = "user";
mButton.mLabel.mLabel = "Login";
this->mChildWidgets.pushBack(&mPass);
this->mChildWidgets.pushBack(&mUser);
this->mChildWidgets.pushBack(&mButton);
}
void eventProcess(const Events& events) override {
mLogged = false;
const auto xval = this->mArea.z / 2 - 100;
mUser.setArea({ xval, 10, 200, 30 });
mPass.setArea({ xval, 50, 200, 30 });
mButton.setArea({ xval, 90, 200, 30 });
if (mButton.isFired()) {
mLogged = true;
}
}
void eventDraw(Canvas& canvas) override { canvas.rect(this->mArea, mBGColor); }
public:
void eventUpdateConfiguration(WidgetManager& wm) override {
wm.setActiveId("LoginWidget");
mBGColor = wm.getColor("Back", "Base");
}
public:
TextInputWidget mUser;
TextInputWidget mPass;
ButtonWidget mButton;
bool mLogged = false;
RGBA mBGColor;
};
class ActiveChatWidget : public Widget {
public:
ActiveChatWidget() {
mSend.mLabel.mLabel = "Send";
mMessage.mId = "Message";
this->mChildWidgets.pushBack(&mHistoryView);
this->mChildWidgets.pushBack(&mMessage);
this->mChildWidgets.pushBack(&mSend);
}
void eventProcess(const Events& events) override {
auto history = this->mArea;
history.w -= 50;
auto input = this->mArea;
input.y = history.w + 10;
input.w = 40 - mPadding;
input.x += mPadding;
input.z -= mPadding;
auto inputMessage = input;
inputMessage.z -= 100;
auto inputSend = input;
inputSend.x = inputMessage.x + inputMessage.z + mPadding;
inputSend.z = 100 - mPadding * 2;
mSend.setArea(inputSend);
mMessage.setArea(inputMessage);
mHistoryView.setArea(history);
}
void eventDraw(Canvas& canvas) override { canvas.rect(this->mArea, mBGColor); }
void eventUpdateConfiguration(WidgetManager& wm) override {
wm.setActiveId("ActiveChat");
mBGColor = wm.getColor("Back", "Background");
mPadding = wm.getNumber("Padding", "Padding");
}
public:
Buffer<MessageWidget> mMessages;
ScrollableWindow mHistoryView;
TextInputWidget mMessage;
ButtonWidget mSend;
RGBA mBGColor;
halnf mPadding = 0;
};
class ChattingWidget : public DockWidget {
public:
ChattingWidget() {
// todo : fetch code
mUsers.append(UserWidget());
mUsers.append(UserWidget());
mUsers.append(UserWidget());
mUsers[0].mArea = { 0, 0, 100, 100 };
mUsers[1].mArea = { 0, 0, 100, 100 };
mUsers[2].mArea = { 0, 0, 100, 100 };
for (auto message : mUsers) {
mSideView.addWidget(&message.data());
}
mActive.mMessages.append(MessageWidget());
mActive.mMessages.append(MessageWidget());
mActive.mMessages.append(MessageWidget());
mActive.mMessages[0].mArea = { 0, 0, 100, 50 };
mActive.mMessages[1].mArea = { 0, 0, 100, 50 };
mActive.mMessages[2].mArea = { 0, 0, 100, 50 };
for (auto message : mActive.mMessages) {
mActive.mHistoryView.addWidget(&message.data());
}
addSideWidget(&mSideView, DockWidget::RIGHT);
setCenterWidget(&mActive);
}
void eventUpdateConfiguration(WidgetManager& wm) override {
wm.setActiveId("ChattingWidget");
mBGColor = wm.getColor("Back", "Background");
}
public:
Buffer<UserWidget> mUsers;
ScrollableWindow mSideView;
ActiveChatWidget mActive;
RGBA mBGColor;
};
class ComplexWidget : public Widget {
public:
ComplexWidget() {
this->mChildWidgets.pushBack(&mLogin);
this->mChildWidgets.pushBack(&mChatting);
}
void eventProcess(const Events& events) override {
mLogged = mLogin.mLogged;
mLogin.setEnable(!mLogged);
mChatting.setEnable(mLogged);
mLogin.setArea(this->mArea);
mChatting.setArea(this->mArea);
}
void eventDraw(Canvas& canvas) override { canvas.rect(this->mArea, mBGColor); }
void eventUpdateConfiguration(WidgetManager& wm) override {
wm.setActiveId("ChatGui");
mBGColor = wm.getColor("Back", "Background");
}
private:
bool mLogged = false;
LoginWidget mLogin;
ChattingWidget mChatting;
RGBA mBGColor;
};
}

Binary file not shown.

View file

@ -0,0 +1,40 @@
#include "SimpleGUI.hpp"
#include "GraphicApplication.hpp"
using namespace tp;
class SimpleGUI : public Application {
public:
SimpleGUI() {
// mGui.mPreview = true;
}
void processFrame(EventHandler* eventHandler, halnf) override {
const auto rec = RectF({ 0, 0 }, mWindow->getSize());
mGui.setArea(rec);
mGui.updateConfigWrapper(mWidgetManager);
mGui.procWrapper(*eventHandler, rec);
}
void drawFrame(Canvas* canvas) override {
canvas->rect(mGui.mArea, { 0.1f, 0.1f, 0.1f, 1.f });
mGui.drawWrapper(*canvas);
}
private:
WidgetManager mWidgetManager;
// DockSpaceWidget mGui;
SimpleWidget3 mGui;
};
int main() {
{
SimpleGUI gui;
gui.run();
}
}

View file

@ -0,0 +1,69 @@
#include "Widgets.hpp"
namespace tp {
class SimpleWidget : public CollapsableMenu {
public:
SimpleWidget() {
this->addWidgetToMenu(&mSlider);
this->addWidgetToMenu(&mInMenuButton1);
this->addWidgetToMenu(&mInMenuButton2);
this->addWidgetToMenu(&mLabel);
mInMenuButton1.mLabel.mLabel = "Button1";
mInMenuButton1.mCallback = []() {
printf("asd\n");
};
mInMenuButton2.mLabel.mLabel = "Button2";
}
private:
ButtonWidget mInMenuButton1;
ButtonWidget mInMenuButton2;
LabelWidget mLabel;
NamedSliderWidget mSlider;
};
class SimpleWidget3 : public WorkspaceWidget {
public:
SimpleWidget3() {
mDockSpace.addSideWidget(&mButtons[0], DockWidget::BOTTOM);
mDockSpace.addSideWidget(&mButtons[1], DockWidget::RIGHT);
mDockSpace.removeSideWidget(DockWidget::BOTTOM);
mDockSpace.addSideWidget(&mButtons[0], DockWidget::TOP);
mDockSpace.addSideWidget(&mButtons[2], DockWidget::LEFT);
mDockSpace.removeSideWidget(DockWidget::TOP);
mDockSpace.addSideWidget(&mButtons[0], DockWidget::BOTTOM);
mDockSpace.addSideWidget(&mButtons[3], DockWidget::TOP);
mDockSpace.setCenterWidget(&mButtons[4]);
/*
mButtons[4].mCallback = [&]() { mDockSpace.toggleHiddenState(DockSpaceWidget::BOTTOM); };
mButtons[0].mCallback = [&]() { mDockSpace.toggleHiddenState(DockSpaceWidget::TOP); };
mButtons[2].mCallback = [&]() { mDockSpace.toggleHiddenState(DockSpaceWidget::RIGHT); };
mButtons[3].mCallback = [&]() { mDockSpace.toggleHiddenState(DockSpaceWidget::LEFT); };
*/
mButtons[0].addWidgetToMenu(&mWidget);
mButtons[1].addWidgetToMenu(&mWidget2);
}
private:
FloatingWidget mButtons[5];
SimpleWidget mWidget;
SimpleWidget mWidget2;
SimpleWidget mWidget3;
};
}

View file

@ -12,19 +12,19 @@ halnf AnimValue::interpolate() const {
auto dt = gCurrentTime - mTimeStart; auto dt = gCurrentTime - mTimeStart;
if (dt > mTimeAnim) dt = mTimeAnim; if (dt > mTimeAnim) dt = mTimeAnim;
auto t = (halnf)dt / (halnf)mTimeAnim; auto t = (halnf) dt / (halnf) mTimeAnim;
t = (halnf)(0.511 + atan((t - 0.36) * 28) / 2.9); t = (halnf) (0.511 + atan((t - 0.36) * 28) / 2.9);
t = clamp(t, 0.f, 1.f); t = clamp(t, 0.f, 1.f);
auto out = mValPrev + (mVal - mValPrev) * t; auto out = mValPrev + (mVal - mValPrev) * t;
return out; return out;
} }
AnimValue::AnimValue() = default; AnimValue::AnimValue() {
mTimeStart = gCurrentTime;
void AnimValue::setAnimTime(halni time) {
mTimeAnim = time;
} }
void AnimValue::setAnimTime(halni time) { mTimeAnim = time; }
AnimValue::AnimValue(halnf val) { AnimValue::AnimValue(halnf val) {
mVal = val; mVal = val;
mValPrev = mVal; mValPrev = mVal;
@ -41,37 +41,36 @@ void AnimValue::set(halnf val) {
if (val == mVal) return; if (val == mVal) return;
mValPrev = get(); mValPrev = get();
mVal = val; mVal = val;
if (!inTransition()) mTimeStart = (halni)gCurrentTime; if (!inTransition()) {
mTimeStart = gCurrentTime;
}
} }
halnf AnimValue::getTarget() const { halnf AnimValue::getTarget() const { return mVal; }
return mVal;
}
void AnimValue::setNoTransition(halnf val) { void AnimValue::setNoTransition(halnf val) {
mValPrev = val; mValPrev = val;
mVal = val; mVal = val;
mTimeStart -= mTimeStart; mTimeStart = gCurrentTime - mTimeAnim;
} }
halnf AnimValue::get() const { halnf AnimValue::get() const {
if (inTransition()) { if (inTransition()) {
gInTransition = true; gInTransition = true;
}
return interpolate(); return interpolate();
}
return mVal;
} }
AnimValue::operator halnf() const { void AnimValue::operator=(halnf val) {
return get(); setNoTransition(val);
} }
RectF AnimRect::get() const { AnimValue::operator halnf() const { return get(); }
return { x.get(), y.get() , z.get(), w.get() };
}
RectF AnimRect::getTarget() const { RectF AnimRect::get() const { return { x.get(), y.get(), z.get(), w.get() }; }
return { x.getTarget(), y.getTarget() , z.getTarget(), w.getTarget() };
} RectF AnimRect::getTarget() const { return { x.getTarget(), y.getTarget(), z.getTarget(), w.getTarget() }; }
void AnimRect::setNoTransition(RectF rec) { void AnimRect::setNoTransition(RectF rec) {
x.setNoTransition(rec.x); x.setNoTransition(rec.x);
@ -94,11 +93,11 @@ void AnimRect::set(const RectF& in) {
w.set(in.w); w.set(in.w);
} }
AnimColor::AnimColor() : mColor() {}
RGBA AnimColor::get() const { RGBA AnimColor::get() const {
auto col = mColor.get(); auto col = mColor.get();
return {col.x, col.y, col.z, col.w}; return { col.x, col.y, col.z, col.w };
} }
void AnimColor::set(const RGBA& col) { void AnimColor::set(const RGBA& col) { mColor.set(RectF(col.r, col.g, col.b, col.a)); }
mColor.set(RectF(col.r, col.g, col.b, col.a));
}

View file

@ -0,0 +1,46 @@
#include "ButtonWidget.hpp"
using namespace tp;
ButtonWidget::ButtonWidget() {
this->setArea({ 0, 0, 100, 30 });
this->mChildWidgets.pushBack(&mLabel);
}
ButtonWidget::ButtonWidget(const std::string& label, const tp::RectF& aArea) {
this->setArea(aArea);
mLabel.mLabel = label;
this->mChildWidgets.pushBack(&mLabel);
}
bool ButtonWidget::isFired() { return this->isReleased(); }
void ButtonWidget::eventProcess(const Events&) {
mLabel.setArea(this->mArea);
if (isFired()) {
mCallback();
}
}
void ButtonWidget::eventDraw(Canvas& canvas) {
if (this->isHolding()) {
canvas.rect(this->mArea, pressedColor, rounding);
} else if (this->isFocus()) {
canvas.rect(this->mArea, hoveredColor, rounding);
} else {
canvas.rect(this->mArea, accentColor, rounding);
}
}
void ButtonWidget::setLabel(const std::string& string) { mLabel.mLabel = string; }
void ButtonWidget::eventUpdateConfiguration(WidgetManager& wm) {
wm.setActiveId("Button");
pressedColor = wm.getColor("Pressed", "Action");
hoveredColor = wm.getColor("Hovered", "Interaction");
accentColor = wm.getColor("Default", "Accent");
rounding = wm.getNumber("Rounding", "Rounding");
}

View file

@ -0,0 +1,96 @@
#include "CollapsableMenu.hpp"
using namespace tp;
CollapsableMenu::CollapsableMenu() {
this->mChildWidgets.pushBack(&mHeader);
this->mChildWidgets.pushBack(&mBody);
}
void CollapsableMenu::eventProcess(const Events&) {
if (mHeader.isReleased()) {
toggleCollapsed();
}
updateGeometry();
}
void CollapsableMenu::eventDraw(Canvas& canvas) {
if (mBorders) {
canvas.rect(this->mArea, mBorderColor, rounding);
canvas.rect(this->mArea.shrink(mBorderSize), mMenuColor, rounding);
} else {
canvas.rect(this->mArea, mMenuColor, rounding);
}
}
void CollapsableMenu::addWidgetToMenu(Widget* widget) {
mBody.addWidget(widget);
EventHandler ev;
mBody.procWrapper(ev, this->mArea);
updateGeometry();
}
void CollapsableMenu::setLabel(const std::string& string) { mHeader.mLabel = string; }
void CollapsableMenu::toggleCollapsed() { setCollapsed(!getCollapsed()); }
void CollapsableMenu::setCollapsed(bool collapsed) {
if (mLocked) return;
if (collapsed && !mCollapsed) mPrevHeight = this->mArea.size.y;
if (!collapsed && mCollapsed) this->mArea.size.y = mPrevHeight;
mCollapsed = collapsed;
}
bool CollapsableMenu::getCollapsed() const { return mCollapsed; }
void CollapsableMenu::updateGeometry() {
mHeader.setArea(getHeaderRect());
mBody.mEnable = !mCollapsed;
if (mCollapsed) {
this->mArea.size.y = headerHeight;
} else {
if (mAdjustHeight) {
this->mArea.size.y = headerHeight + getBodyRect().size.y + mPadding * 2;
}
mBody.setArea(getBodyRect());
}
}
RectF CollapsableMenu::getHeaderRect() {
RectF out = { this->mArea.pos, { this->mArea.size.x, headerHeight } };
if (mBorders) out = out.shrink(mPadding);
return out;
}
RectF CollapsableMenu::getBodyRect() {
RectF out = { Vec2F{ this->mArea.pos.x, this->mArea.pos.y + headerHeight },
Vec2F{ this->mArea.size.x, this->mArea.size.y - headerHeight - mPadding } };
out.size.y -= mBorderSize * 2;
if (mAdjustHeight) out.size.y = mBody.getContentSize();
if (mBody.getContentSize() && mBorders) {
out = out.shrink(mPadding);
out.size.y += mPadding * 2 + 1;
}
return out;
}
void CollapsableMenu::eventUpdateConfiguration(WidgetManager& wm) {
wm.setActiveId("CollapsableMenu");
headerHeight = wm.getNumber("HeaderHeight", 35);
mMenuColor = wm.getColor("MenuColor", RGBA(0, 0, 0, 1.f));
rounding = wm.getNumber("Rounding", "Rounding");
mBorderColor = wm.getColor("BorderColor", RGBA(0.16, 0.16, 0.16, 1.f));
mBorderSize = wm.getNumber("BorderSize", 2.f);
mPadding = wm.getNumber("Padding", "Padding");
}

View file

@ -0,0 +1,47 @@
#include "FloatingLayoutWidget.hpp"
using namespace tp;
FloatingLayoutWidget::FloatingLayoutWidget() = default;
void FloatingLayoutWidget::eventProcess(const tp::Events& events) {
updateActiveWindow(events);
}
void FloatingLayoutWidget::updateActiveWindow(const tp::Events& events) {
mIsPassThrough = true;
for (auto childNode = this->mChildWidgets.firstNode(); childNode; childNode = childNode->next) {
auto child = childNode->data;
if (child->mArea.isInside(events.getPointer())) {
mIsPassThrough = false;
}
}
if (events.isPressed(InputID::MOUSE1)) {
Widget* activeChild = nullptr;
for (auto childNode = this->mChildWidgets.firstNode(); childNode; childNode = childNode->next) {
auto child = childNode->data;
if (child->mArea.isInside(events.getPointer())) {
mChildWidgets.detach(childNode);
mChildWidgets.pushFront(childNode);
child->mHandlesEvents = true;
activeChild = child;
break;
}
}
if (activeChild) {
for (auto child : this->mChildWidgets) {
if (activeChild != child.data() && !child->mIsDocked) child->mHandlesEvents = false;
}
}
}
}
bool FloatingLayoutWidget::handlesEvent() const { return !mIsPassThrough; }

View file

@ -0,0 +1,89 @@
#include "FloatingWidget.hpp"
using namespace tp;
FloatingWidget::FloatingWidget() {
this->mArea = { 0, 0, 300, 300 };
this->mAdjustHeight = false;
}
void FloatingWidget::eventProcess(const Events& events) {
mActionStartRelativePos = events.getPointerPrev() - this->mArea.pos;
checkFloating(events);
if (mResizable) checkResizing(events);
CollapsableMenu::eventProcess(events);
}
void FloatingWidget::eventDraw(Canvas& canvas) {
CollapsableMenu::eventDraw(canvas);
if (!this->getCollapsed() && mResizable) {
auto rect = getResizeHandle();
canvas.rect(rect, mResizeHandleColor, 0);
canvas.circle(rect.pos - this->mBorderSize, rect.w, this->mMenuColor);
}
}
void FloatingWidget::eventUpdateConfiguration(WidgetManager& wm) {
CollapsableMenu::eventUpdateConfiguration(wm);
wm.setActiveId("FloatingWidget");
mResizeHandleSize = wm.getNumber("ResizeHandleSize", 15);
mResizeHandleColor = wm.getColor("ResizeHandleColor", RGBA(0.16, 0.16, 0.16, 1.f));
}
void FloatingWidget::checkFloating(const Events& events) {
mDropped = false;
if (this->mHeader.isHolding() && events.getPointerDelta().length2() > 4) {
mFloating = true;
}
if (mFloating && this->mHeader.isReleased()) {
mFloating = false;
this->mHeader.clearEvents();
mDropped = true;
}
if (mFloating) {
auto relativePos = events.getPointer() - this->mArea.pos;
this->mArea.pos += relativePos - mActionStartRelativePos;
}
}
void FloatingWidget::checkResizing(const Events& events) {
if (this->getCollapsed()) return;
if (events.isPressed(InputID::MOUSE1) && getResizeHandle().isInside(events.getPointer())) {
mResizing = true;
}
if (events.isReleased(InputID::MOUSE1)) {
mResizing = false;
}
if (mResizing) {
auto relativePos = events.getPointer() - this->mArea.pos;
this->mArea.size += relativePos - mActionStartRelativePos;
}
if (!this->mCollapsed) {
this->mArea.size.clamp(mMinSize, { FLT_MAX, FLT_MAX });
}
}
RectF FloatingWidget::getResizeHandle() {
auto size = Vec2F(mResizeHandleSize);
auto pos = this->mArea.pos + this->mArea.size - size;
return { pos, size };
}
bool FloatingWidget::isFloating() const { return mFloating; }
void FloatingWidget::stopFloating() {
mFloating = false;
}

View file

@ -0,0 +1,328 @@
#include "GridLayoutWidget.hpp"
using namespace tp;
DockWidget::DockWidget() {
mSideWidgets[0].side = LEFT;
mSideWidgets[1].side = TOP;
mSideWidgets[2].side = RIGHT;
mSideWidgets[3].side = BOTTOM;
}
void DockWidget::addSideWidget(Widget* widget, Side side) {
if (sideExists(side)) return;
auto& sideWidget = mSideWidgets[side];
sideWidget.widget = widget;
for (auto& order : mSideWidgets) {
if (order.order == -1) {
order.order = side;
break;
}
}
sideWidget.hidden = false;
mChildWidgets.pushBack(widget);
widget->mIsDocked = true;
}
void DockWidget::removeSideWidget(Side side) {
if (!sideExists(side)) return;
bool removed = false;
for (ualni i = 0; i < 3; i++) {
if (mSideWidgets[i].order == side) {
removed = true;
}
if (removed) {
swapV(mSideWidgets[i].order, mSideWidgets[i + 1].order);
}
}
mSideWidgets[3].order = -1;
auto widget = mSideWidgets[side].widget;
widget->mIsDocked = false;
mChildWidgets.removeNode(mChildWidgets.find(widget));
mSideWidgets[side].widget = nullptr;
}
void DockWidget::setCenterWidget(Widget* widget) {
mChildWidgets.removeNode(mChildWidgets.find(mCenterWidget));
mCenterWidget = widget;
mChildWidgets.pushBack(mCenterWidget);
}
void DockWidget::toggleHiddenState(DockWidget::Side side) {
if (!sideExists(side)) return;
mSideWidgets[side].hidden = !mSideWidgets[side].hidden;
}
void DockWidget::eventProcess(const tp::Events& events) {
calculateSideAreas();
calculateResizeHandles();
// calculateHeaderAreas();
handlePreview(events);
handleResizeEvents(events);
updateChildSideWidgets();
}
void DockWidget::eventDraw(Canvas& canvas) {
canvas.rect(this->mArea, mBackgroundColor, 0);
for (auto& sideWidget : mSideWidgets) {
if (!isSideVisible(sideWidget.side)) continue;
auto& handle = sideWidget.resizeHandle;
if (handle.active) {
canvas.rect(handle.area.shrink(mPadding / 1.5f), mResizeHandleColorActive, 0);
} else if (handle.hover) {
canvas.rect(handle.area.shrink(mPadding / 1.5f), mResizeHandleColorHovered, 0);
}
}
for (auto& sideWidget : mSideWidgets) {
if (!isSideVisible(sideWidget.side)) continue;
canvas.rect(sideWidget.headerArea, mResizeHandleColorActive, 0);
}
}
void DockWidget::eventDrawOver(Canvas& canvas) {
if (!mPreview) return;
if (mPreviewSide != NONE) canvas.rect(mPreviewArea.shrink(mPadding * 2), mPreviewColor, mRounding);
for (auto& sideWidget : mSideWidgets) {
if (sideWidget.widget) continue;
canvas.rect(sideWidget.previewHandleArea, mPreviewColor, mRounding);
}
}
void DockWidget::calculateSideAreas() {
auto startArea = this->mArea;
for (auto& sideWidget : mSideWidgets) {
const auto side = sideWidget.order;
if (side == -1) break;
if (!isSideVisible(Side(side))) continue;
bool vertical = side == TOP || side == BOTTOM;
bool opposite = side == BOTTOM || side == RIGHT;
auto& sideSize = mSideWidgets[side].absoluteSize;
auto factor = sideSize / startArea.size[vertical];
if (opposite) factor = factor * -1 + 1;
auto& area = mSideWidgets[side].area;
if (!vertical) {
const auto first = startArea.splitByFactorHL(factor);
const auto second = startArea.splitByFactorHR(factor);
area = side == LEFT ? first : second;
startArea = side == LEFT ? second : first;
} else {
const auto first = startArea.splitByFactorVT(factor);
const auto second = startArea.splitByFactorVB(factor);
area = side == TOP ? first : second;
startArea = side == TOP ? second : first;
}
area = area.shrink(mPadding);
}
mCenterArea = startArea.shrink(mPadding);
}
void DockWidget::calculateResizeHandles() {
RectF rec;
if (isSideVisible(LEFT)) {
auto& side = mSideWidgets[LEFT];
rec = { side.area.p4(), { mPadding * 2, side.area.size.y } };
side.resizeHandle = { rec, 0, mCenterArea.p3().x };
}
if (isSideVisible(RIGHT)) {
auto& side = mSideWidgets[RIGHT];
rec = { side.area.p1(), { mPadding * 2, side.area.size.y } };
rec.x -= mPadding * 2;
side.resizeHandle = { rec, 0, (this->mArea.p3() - mCenterArea.p1()).x };
}
if (isSideVisible(TOP)) {
auto& side = mSideWidgets[TOP];
rec = { side.area.p2(), { side.area.size.x, mPadding * 2 } };
side.resizeHandle = { rec, 0, mCenterArea.p2().y };
}
if (isSideVisible(BOTTOM)) {
auto& side = mSideWidgets[BOTTOM];
rec = { side.area.p1(), { side.area.size.x, mPadding * 2 } };
rec.y -= mPadding * 2;
side.resizeHandle = { rec, 0, (this->mArea.p3() - mCenterArea.p1()).y };
}
}
void DockWidget::handleResizeEvents(const Events& events) {
for (auto& sideWidget : mSideWidgets) {
auto& sideSize = sideWidget.absoluteSize;
auto& resizeHandle = sideWidget.resizeHandle;
if (resizeHandle.end < mSideSizePadding * 2) {
sideSize = resizeHandle.end / 2.f;
} else {
sideSize = clamp(sideSize, resizeHandle.start + mSideSizePadding, resizeHandle.end - mSideSizePadding);
}
}
for (auto& sideWidget : mSideWidgets) {
sideWidget.resizeHandle.hover = false;
if (sideWidget.resizeHandle.area.isInside(events.getPointerPrev())) {
sideWidget.resizeHandle.hover = true;
}
}
for (auto& sideWidget : mSideWidgets) {
sideWidget.resizeHandle.active = false;
}
if (mPreview) return;
auto resizeSideWidget = [&events](SideWidgetData& sideWidget, Vec2F deltaVec) {
halnf delta = deltaVec[(sideWidget.side == TOP || sideWidget.side == BOTTOM)];
if (sideWidget.side == BOTTOM || sideWidget.side == RIGHT) delta *= -1;
sideWidget.absoluteSize += delta;
sideWidget.resizeHandle.active = true;
};
if (events.isDown(InputID::MOUSE1)) {
for (auto& sideWidget : mSideWidgets) {
if (sideWidget.resizeHandle.area.isInside(events.getPointerPrev())) {
resizeSideWidget(sideWidget, events.getPointerDelta());
}
}
}
if (events.isDown(InputID::LEFT_ALT)) {
const auto pointer = events.getPointerPrev();
if (!mCenterArea.isInside(pointer)) return;
if (events.isPressed(InputID::MOUSE1)) {
for (auto i : { 0, 1 }) {
const auto step = mCenterArea.size[i] / 3.f;
const auto rec1 = mCenterArea.pos[i];
const auto pos = pointer[i];
if (pos > rec1 && pos < rec1 + step) resizeType[i] = 0;
if (pos > rec1 + step && pos < rec1 + step * 2) resizeType[i] = 1;
if (pos > rec1 + step * 2) resizeType[i] = 2;
}
} else if (events.isDown(InputID::MOUSE1)) {
const auto deltaVec = events.getPointerDelta();
if (resizeType[0] == 0) resizeSideWidget(mSideWidgets[LEFT], deltaVec);
if (resizeType[1] == 0) resizeSideWidget(mSideWidgets[TOP], deltaVec);
if (resizeType[0] == 2) resizeSideWidget(mSideWidgets[RIGHT], deltaVec);
if (resizeType[1] == 2) resizeSideWidget(mSideWidgets[BOTTOM], deltaVec);
}
}
}
void DockWidget::updateChildSideWidgets() {
// Update Child Widgets
{
for (ualni i = 0; i < 4; i++) {
if (!sideExists(Side(i))) continue;
auto widget = mSideWidgets[i].widget;
if (!isSideVisible(Side(i))) {
widget->mEnable = false;
} else {
widget->setArea(mSideWidgets[i].area);
widget->mEnable = true;
}
}
if (mCenterWidget) mCenterWidget->setArea(mCenterArea);
}
// update depth order
/*
if (mChildWidgets.size() > 1) {
for (auto sideChild : mSideWidgets) {
if (!sideChild) continue;
for (auto childNode = mChildWidgets.firstNode(); childNode; childNode = childNode->next) {
if (childNode->data == sideChild) {
mChildWidgets.detach(childNode);
mChildWidgets.pushBack(childNode);
break;
}
}
}
}
*/
}
void DockWidget::calculateHeaderAreas() {
for (ualni i = 0; i < 4; i++) {
if (!isSideVisible(Side(i))) continue;
auto& area = mSideWidgets[i].area;
const auto factor = mHeaderSize / area.size.y;
mSideWidgets[i].headerArea = area.splitByFactorVT(factor);
area = area.splitByFactorVB(factor);
mSideWidgets[i].headerArea.size.y -= mPadding;
}
}
bool DockWidget::isSideVisible(DockWidget::Side side) {
return sideExists(side) && !mSideWidgets[side].hidden;
}
bool DockWidget::sideExists(DockWidget::Side side) { return mSideWidgets[side].widget; }
ualni DockWidget::getVisibleSidesSize() {
ualni out = 0;
for (ualni i = 0; i < 4; i++) {
if (isSideVisible(Side(i))) out++;
}
return out;
}
DockWidget::Side DockWidget::getPreviewSide() { return mPreviewSide; }
void DockWidget::handlePreview(const Events& events) {
if (!mPreview) {
mPreviewSide = NONE;
return;
}
const halnf factor = 0.3;
const halnf handleFactor = 0.1;
const auto handleSize = min(mCenterArea.size.x, mCenterArea.size.y) * handleFactor;
for (auto& sideWidget : mSideWidgets) {
if (sideWidget.widget) continue;
switch (sideWidget.side) {
case TOP: sideWidget.area = mCenterArea.splitByFactorVT(factor); break;
case BOTTOM: sideWidget.area = mCenterArea.splitByFactorVB(1 - factor); break;
case LEFT: sideWidget.area = mCenterArea.splitByFactorHL(factor); break;
case RIGHT: sideWidget.area = mCenterArea.splitByFactorHR(1 - factor); break;
default: break;
}
sideWidget.area = sideWidget.area.shrink(mPadding * 2);
sideWidget.previewHandleArea = sideWidget.area.getSizedFromCenter({ handleSize, handleSize });
}
mPreviewArea = {};
mPreviewSide = NONE;
for (auto& sideWidget : mSideWidgets) {
if (sideWidget.widget) continue;
if (sideWidget.previewHandleArea.isInside(events.getPointer())) {
mPreviewArea = sideWidget.area;
mPreviewSide = sideWidget.side;
}
}
}

View file

@ -0,0 +1,17 @@
#include "LabelWidget.hpp"
using namespace tp;
LabelWidget::LabelWidget() { this->mArea = { 0, 0, 100, 30 }; }
void LabelWidget::eventDraw(Canvas& canvas) {
canvas.text(mLabel.c_str(), this->mArea, fontSize, Canvas::LC, padding, fontColor);
}
void LabelWidget::eventUpdateConfiguration(WidgetManager& wm) {
wm.setActiveId("Label");
fontSize = wm.getNumber("Size", "FontSize");
padding = wm.getNumber("Padding", "Padding");
fontColor = wm.getColor("Default", "Front");
}

View file

@ -0,0 +1,179 @@
#include "ScrollableWidget.hpp"
#include "../../WidgetsNew/public/widgets/ScrollableWidget.hpp"
using namespace tp;
ScrollBarWidget::ScrollBarWidget() = default;
void ScrollBarWidget::eventProcess(const Events& events) {
auto area = getHandle();
mHovered = getHandleHandle().isInside(events.getPointer());
if (mSizeFraction > 1.f) {
mPositionFraction = 0;
return;
}
if (events.getScrollY() != 0 && mArea.isInside(events.getPointer())) {
auto offset = events.getScrollY() < 0 ? 1.0f : -1.0f;
mPositionFraction += mSizeFraction * offset * 0.3f;
mPositionFraction = tp::clamp(mPositionFraction, 0.f, 1.f - mSizeFraction);
}
if (events.isPressed(InputID::MOUSE1) && area.isInside(events.getPointer())) {
mIsScrolling = true;
} else if (events.isReleased(InputID::MOUSE1)) {
mIsScrolling = false;
}
if (mIsScrolling) {
tp::halnf pos = events.getPointer().y;
pos = (pos - area.y - mSizeFraction * area.w / 2.f) / area.w;
mPositionFraction = tp::clamp(pos, 0.f, 1.f - mSizeFraction);
}
mPositionFraction = tp::clamp(mPositionFraction, 0.f, 1.f - mSizeFraction);
}
void ScrollBarWidget::eventDraw(Canvas& canvas) {
auto area = getHandle();
if (mSizeFraction > 1.f) return;
// if (!areaParent.isOverlap(getHandle())) return;
tp::RGBA col = mHandleColor;
if (mIsScrolling) {
col = mScrollingColor;
} else if (mHovered) {
col = mHoveredColor;
}
canvas.rect(area, mDefaultColor, mRounding);
canvas.rect(getHandleHandle(), col, mRounding);
}
RectF ScrollBarWidget::getHandleHandle() const {
auto area = getHandle();
auto sliderSize = tp::clamp(area.w * mSizeFraction, mMinSize * 2, area.w);
auto diffSize = sliderSize - area.w * mSizeFraction;
return { area.x, area.y + (area.w - diffSize) * mPositionFraction, area.z, sliderSize };
}
RectF ScrollBarWidget::getViewport() const {
if (mSizeFraction > 1.f) {
return this->mArea;
}
return { this->mArea.x, this->mArea.y, this->mArea.z - mHandleSize, this->mArea.w };
}
RectF ScrollBarWidget::getHandle() const {
return { this->mArea.x + this->mArea.z - mHandleSize + mPadding,
this->mArea.y + mPadding,
mHandleSize - mPadding * 2,
this->mArea.w - mPadding * 2 };
}
void ScrollBarWidget::eventUpdateConfiguration(WidgetManager& wm) {
wm.setActiveId("Scrollbar");
mDefaultColor = wm.getColor("Default", "Base");
mHandleColor = wm.getColor("Handle", "Accent");
mHoveredColor = wm.getColor("Hovered", "Interaction");
mScrollingColor = wm.getColor("Scrolling", "Action");
mPadding = wm.getNumber("Padding", "Padding");
mHandleSize = wm.getNumber("HandleSize", 20.f);
mMinSize = wm.getNumber("MinSize", 20.f);
mRounding = wm.getNumber("Rounding", "Rounding");
}
ScrollableWindow::ScrollableWindow() {
this->mChildWidgets.pushBack(&mScroller);
this->mChildWidgets.pushBack(&mContentWidget);
}
ScrollableWindow::~ScrollableWindow() = default;
void ScrollableWindow::eventProcess(const Events& events) {
List<Widget*>& content = mContentWidget.mChildWidgets;
// to account all changed geometry of child widgets
for (auto widget : content) {
widget->procWrapper(events, mContentWidget.mVisibleArea);
}
updateContents(content);
updateContentSize(content);
const auto padding = mPadding;
mScroller.mSizeFraction = mContentWidget.mArea.w / mContentSize;
mScroller.setArea(this->mArea);
mContentWidget.setArea(mScroller.getViewport());
if (mScroller.mSizeFraction > 1.f) {
setOffset(content, 0);
} else {
setOffset(content, (-mScroller.mPositionFraction) * mContentSize);
}
for (auto widget : content) {
widget->setArea({ mContentWidget.mArea.x + padding,
mContentWidget.mArea.y + widget->mArea.y,
mScroller.getViewport().z - padding * 2,
widget->mArea.w });
}
}
void ScrollableWindow::addWidget(Widget* widget) {
mContentWidget.mChildWidgets.pushBack(widget);
List<Widget*>& content = mContentWidget.mChildWidgets;
updateContents(content);
updateContentSize(content);
}
void ScrollableWindow::clearContent() { mContentWidget.mChildWidgets.removeAll(); }
List<Widget*>& ScrollableWindow::getContent() { return mContentWidget.mChildWidgets; }
void ScrollableWindow::eventUpdateConfiguration(WidgetManager& wm) {
wm.setActiveId("ScrollableWidget");
mPadding = wm.getNumber("Padding", "Padding");
}
[[nodiscard]] halnf ScrollableWindow::getContentSize() const { return mContentSize; }
void ScrollableWindow::updateContents(List<Widget*>& contentWidgets) {
if (!contentWidgets.size()) {
return;
}
const halnf offset = contentWidgets.first()->mArea.y + mPadding;
halnf start = 0;
for (auto widget : contentWidgets) {
widget->mArea.y = start;
start += widget->mArea.w + mPadding;
}
for (auto widget : contentWidgets) {
widget->mArea.y += offset;
}
}
void ScrollableWindow::updateContentSize(List<Widget*>& contentWidgets) {
mContentSize = 0;
if (contentWidgets.size()) {
mContentSize = contentWidgets.last()->mArea.y - contentWidgets.first()->mArea.y;
mContentSize += contentWidgets.last()->mArea.w;
mContentSize += 2 * mPadding;
}
}
void ScrollableWindow::setOffset(List<Widget*>& contentWidgets, const halnf offset) {
if (!contentWidgets.size()) return;
auto newOffset = offset - contentWidgets.first()->mArea.y + mPadding;
for (auto widget : contentWidgets) {
widget->mArea.y += newOffset;
}
}

View file

@ -0,0 +1,62 @@
#include "SliderWidget.hpp"
using namespace tp;
SliderWidget::SliderWidget() = default;
void SliderWidget::eventProcess(const Events& events) {
if (this->isPressed()) {
mIsSliding = true;
} else if (events.isReleased(InputID::MOUSE1)) {
mIsSliding = false;
}
if (mIsSliding) {
mFactor = (events.getPointer().x - this->mArea.x - handleSize / 2.f) / (this->mArea.z - handleSize);
}
mFactor = tp::clamp(mFactor, 0.f, 1.f);
}
void SliderWidget::eventDraw(Canvas& canvas) {
canvas.rect(this->mArea, handleColor, rounding);
canvas.rect(this->mArea.shrink(borderSize), defaultColor, rounding);
canvas.rect(getHandle(), handleColor, rounding);
}
RectF SliderWidget::getHandle() const {
const auto left = this->mArea.x + (this->mArea.z - handleSize) * mFactor;
return { left, this->mArea.y, handleSize, this->mArea.w };
}
void SliderWidget::eventUpdateConfiguration(WidgetManager& wm) {
wm.setActiveId("Slider");
defaultColor = wm.getColor("Default", "Base");
handleColor = wm.getColor("Handle", RGBA(0.3f, 0.3f, 0.3f, 1.f));
borderSize = wm.getNumber("BorderSize", 2);
handleSize = wm.getNumber("HandleSize", 15.f);
rounding = wm.getNumber("Rounding", "Rounding");
}
NamedSliderWidget::NamedSliderWidget(const char* name) {
mLabel.mLabel = name;
this->mArea = { 0, 0, 100, 30 };
this->mChildWidgets.pushBack(&mSlider);
this->mChildWidgets.pushBack(&mLabel);
}
void NamedSliderWidget::eventProcess(const Events& events) {
const auto widthFirst = this->mArea.z * mFactor;
const auto widthSecond = this->mArea.z * (1.f - mFactor);
RectF rec = this->mArea;
rec.size.x = widthFirst;
mLabel.setArea(rec);
rec.pos.x += widthFirst;
rec.size.x = widthSecond;
mSlider.setArea(rec);
}

View file

@ -0,0 +1,57 @@
#include "TextInputWidget.hpp"
#include "imgui.h"
#include "imgui_internal.h"
using namespace tp;
TextInputWidget::TextInputWidget() = default;
void TextInputWidget::eventDraw(Canvas&) {
nChanged = false;
const auto col = mAccentColor;
const auto colSel = mHoveredColor;
ImGui::GetStyle().Colors[ImGuiCol_FrameBg] = { col.r, col.g, col.b, col.a };
ImGui::GetStyle().Colors[ImGuiCol_TextSelectedBg] = { colSel.r, colSel.g, colSel.b, colSel.a };
ImGui::SetNextWindowPos({ this->mArea.x, this->mArea.y });
ImGui::SetNextWindowSize({ this->mArea.z, this->mArea.w });
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0, 0 });
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, mRounding * 1.5f);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { mPadding, mPadding });
// ImGui::PushID((int) alni(this));
ImGui::Begin(
mId.c_str(),
0,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_NoResize
);
if (mMultiline) {
if (ImGui::InputTextMultiline("input", mBuff, mMaxBufferSize, { this->mArea.z, this->mArea.w })) {
mValue = mBuff;
nChanged = true;
}
} else {
if (ImGui::InputTextEx("input", mId.c_str(), mBuff, mMaxBufferSize, { this->mArea.z, this->mArea.w }, 0)) {
mValue = mBuff;
nChanged = true;
}
}
ImGui::End();
ImGui::PopStyleVar(3);
}
void TextInputWidget::eventUpdateConfiguration(WidgetManager& wm) {
wm.setActiveId("TextInput");
mAccentColor = wm.getColor("Accent", "Accent");
mBaseColor = wm.getColor("Base", "Base");
mRounding = wm.getNumber("Rounding", "Rounding");
mHoveredColor = wm.getColor("Hovered", "Accent");
mPadding = wm.getNumber("Padding", "Padding");
}

View file

@ -0,0 +1,140 @@
#include "WidgetBase.hpp"
using namespace tp;
Widget::Widget() { mArea = { 0, 0, 100, 100 }; }
Widget::~Widget() = default;
void Widget::procWrapper(const Events& events, const RectF& parentArea) {
if (!mEnable) return;
checkVisibility(events, parentArea);
if (!mVisible) return;
checkFocus(events);
checkClicked(events);
if (mHandlesEvents) {
for (auto child : mChildWidgets) {
child->procWrapper(events, mVisibleArea);
}
eventProcess(events);
}
}
void Widget::drawWrapper(Canvas& canvas) {
if (!mEnable || !mVisible) return;
eventDraw(canvas);
// draw child widgets
canvas.pushClamp(this->mArea);
for (auto child = mChildWidgets.lastNode(); child; child = child->prev) {
child->data->drawWrapper(canvas);
}
canvas.popClamp();
eventDrawOver(canvas);
}
void Widget::updateConfigWrapper(WidgetManager& wm) {
wm.setActiveId("Global");
eventUpdateConfiguration(wm);
for (auto child : mChildWidgets) {
child->updateConfigWrapper(wm);
}
}
void Widget::eventProcess(const Events& events) {}
void Widget::eventDraw(Canvas& canvas) {}
void Widget::eventDrawOver(Canvas& canvas) {}
void Widget::eventUpdateConfiguration(WidgetManager& wm) {}
void Widget::eventVisible(const Events& events) {}
void Widget::eventNotVisible(const Events& events) {}
void Widget::eventFocusEnter(const Events& events) {}
void Widget::eventFocusLeave(const Events& events) {}
void Widget::eventPressed(const Events& events) {}
void Widget::eventReleased(const Events& events) {}
void Widget::checkVisibility(const Events& events, const RectF& parentArea) {
const bool currentVisibility = parentArea.isOverlap(getArea());
parentArea.calcIntersection(mArea, mVisibleArea);
if (currentVisibility != mVisible) {
if (currentVisibility) eventVisible(events);
else eventNotVisible(events);
}
mVisible = currentVisibility;
if (!mVisible) {
mHolding = false;
mPressed = false;
mReleased = false;
}
}
void Widget::checkFocus(const Events& events) {
const bool currentFocus = mVisibleArea.isInside(events.getPointerPrev());
if (currentFocus != mInFocus) {
if (currentFocus) eventFocusEnter(events);
else eventFocusLeave(events);
}
mInFocus = currentFocus;
if (!mInFocus) {
mHolding = false;
mPressed = false;
mReleased = false;
}
}
void Widget::checkClicked(const Events& events) {
mPressed = false;
mReleased = false;
if (!mInFocus) return;
if (mHolding) {
if (events.isReleased(InputID::MOUSE1)) {
eventReleased(events);
mReleased = true;
mHolding = false;
}
} else {
if (events.isPressed(InputID::MOUSE1) && mVisibleArea.isInside(events.getPointer())) {
eventPressed(events);
mHolding = true;
mPressed = true;
}
}
}
void Widget::setEnable(bool enable) { mEnable = enable; }
void Widget::setVisible(bool visible) { mVisible = visible; }
void Widget::setArea(const RectF& area) { mArea = area; }
const RectF& Widget::getArea() const { return mArea; }
bool Widget::isFocus() const { return mInFocus; }
bool Widget::isPressed() const { return mPressed; }
bool Widget::isReleased() const { return mReleased; }
bool Widget::isHolding() const { return mHolding; }
void Widget::clearEvents() {
mReleased = false;
mPressed = false;
mHolding = false;
}

View file

@ -0,0 +1,74 @@
#include "WidgetManager.hpp"
using namespace tp;
WidgetManager::WidgetManager() { initGlobalParameters(); }
WidgetManager::~WidgetManager() { mConfigurations.removeAll(); }
const RGBA& WidgetManager::getColor(const std::string& parameterId, const RGBA& defaultValue) {
WidgetConfig& config = getWidgetConfig(mActiveId);
Parameter& parameter = getParameter(config, parameterId, Parameter(defaultValue));
return parameter.color;
}
const RGBA& WidgetManager::getColor(const std::string& parameterId, const char* globalRef) {
WidgetConfig& config = getWidgetConfig(mActiveId);
Parameter& parameter = getParameter(config, parameterId, Parameter(globalRef, Parameter::COL));
return parameter.color;
}
halnf WidgetManager::getNumber(const std::string& parameterId, halnf defaultValue) {
WidgetConfig& config = getWidgetConfig(mActiveId);
Parameter& parameter = getParameter(config, parameterId, Parameter(defaultValue));
return parameter.value;
}
halnf WidgetManager::getNumber(const std::string& parameterId, const char* globalRef) {
WidgetConfig& config = getWidgetConfig(mActiveId);
Parameter& parameter = getParameter(config, parameterId, Parameter(globalRef, Parameter::VAL));
return parameter.value;
}
void WidgetManager::setActiveId(const std::string& id) { mActiveId = id; }
WidgetConfig& WidgetManager::getWidgetConfig(const std::string& id) {
auto idx = mConfigurations.presents(id);
if (idx) return mConfigurations.getSlotVal(idx);
mConfigurations.put(id, {});
return mConfigurations.get(id);
}
WidgetManager::Parameter& WidgetManager::getParameter(WidgetConfig& config, const std::string& id, const Parameter& defaultValue) {
auto idx = config.mParameters.presents(id);
if (!idx) {
config.mParameters.put(id, defaultValue);
}
Parameter& parameter = config.mParameters.get(id);
if (parameter.globalReference) {
return mGlobalConfig.mParameters.get(parameter.globalId);
} else {
return parameter;
}
}
void WidgetManager::initGlobalParameters() {
auto& params = mGlobalConfig.mParameters;
params.put("FontSize", Parameter(15.f));
params.put("FontSizeDim", Parameter(12.f));
params.put("Rounding", Parameter(5.f));
params.put("Padding", Parameter(5.f));
params.put("HandleSize", Parameter(5.f));
params.put("Background", Parameter(RGBA{ 0.03f, 0.03f, 0.03f, 1.f }));
params.put("Base", Parameter(RGBA{ 0.07f, 0.07f, 0.07f, 1.f }));
params.put("Accent", Parameter(RGBA{ 0.13f, 0.13f, 0.13f, 1.f }));
params.put("Interaction", Parameter(RGBA{ 0.33f, 0.33f, 0.3f, 1.f }));
params.put("Action", Parameter(RGBA{ 0.44f, 0.44f, 0.4f, 1.f }));
params.put("Front", Parameter(RGBA{ 1.f, 1.f, 1.f, 1.f }));
params.put("FrontDim", Parameter(RGBA{ 0.7f, 0.7f, 0.7f, 1.f }));
}

View file

@ -0,0 +1,73 @@
#include "WorkspaceWidget.hpp"
using namespace tp;
WorkspaceWidget::WorkspaceWidget() {
this->mChildWidgets.pushBack(&mFloatingLayer);
this->mChildWidgets.pushBack(&mDockSpace);
}
void WorkspaceWidget::eventProcess(const Events& events) {
mDockSpace.setArea(this->mArea);
mFloatingLayer.setArea(this->mArea);
mDockSpace.mPreview = false;
mDockSpace.mHandlesEvents = !mFloatingLayer.handlesEvent();
for (auto floatingChild : mFloatingLayer.mChildWidgets) {
auto widget = dynamic_cast<FloatingWidget*>(floatingChild.data());
if (!widget) continue;
if (widget->mDropped) {
auto side = mDockSpace.getPreviewSide();
if (side != DockWidget::NONE) {
mFloatingLayer.mChildWidgets.removeNode(mFloatingLayer.mChildWidgets.find(widget));
widget->setCollapsed(false);
widget->stopFloating();
mDockSpace.addSideWidget(widget, side);
}
}
if (widget->isFloating()) {
mDockSpace.mHandlesEvents = true;
mDockSpace.mPreview = true;
}
}
for (auto& dockedChild : mDockSpace.mSideWidgets) {
auto widget = dynamic_cast<FloatingWidget*>(dockedChild.widget);
if (!widget) continue;
if (widget->isFloating()) {
mDockSpace.removeSideWidget(dockedChild.side);
mFloatingLayer.mChildWidgets.pushBack(widget);
widget->mArea.pos = events.getPointer() - 20;
widget->mArea.size = mDefaultFloatSize;
widget->mResizable = true;
// widget->mBorders = true;
}
}
// toggle hide state
if (events.isDown(InputID::LEFT_ALT)) {
if (events.isPressed(InputID::N1)) {
mDockSpace.toggleHiddenState(DockWidget::LEFT);
} else if (events.isPressed(InputID::N2)) {
mDockSpace.toggleHiddenState(DockWidget::TOP);
} else if (events.isPressed(InputID::N3)) {
mDockSpace.toggleHiddenState(DockWidget::RIGHT);
} else if (events.isPressed(InputID::N4)) {
mDockSpace.toggleHiddenState(DockWidget::BOTTOM);
}
}
for (auto& dockedChild : mDockSpace.mSideWidgets) {
auto widget = dynamic_cast<FloatingWidget*>(dockedChild.widget);
if (!widget) continue;
widget->setCollapsed(false);
widget->mResizable = false;
// widget->mBorders = false;
}
}

View file

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "GraphicsCommon.hpp" #include "Color.hpp"
#include "Rect.hpp"
#include "Timing.hpp"
namespace tp { namespace tp {
@ -33,8 +35,8 @@ namespace tp {
class AnimRect : Rect<AnimValue> { class AnimRect : Rect<AnimValue> {
public: public:
AnimRect() { AnimRect() {
set({ 0, 0, 0, 0 });
setAnimTime(450); setAnimTime(450);
setNoTransition({ 0, 0, 0, 0 });
} }
[[nodiscard]] RectF get() const; [[nodiscard]] RectF get() const;
@ -45,8 +47,10 @@ namespace tp {
}; };
class AnimColor { class AnimColor {
AnimRect mColor;
public: public:
AnimColor();
AnimRect mColor;
[[nodiscard]] RGBA get() const; [[nodiscard]] RGBA get() const;
void set(const RGBA&); void set(const RGBA&);
}; };

View file

@ -0,0 +1,35 @@
#pragma once
#include "LabelWidget.hpp"
#include <functional>
namespace tp {
class ButtonWidget : public Widget {
public:
// enum State { NONE, ANTICIPATION, ACTIVATED, CONFIRMED };
public:
ButtonWidget();
ButtonWidget(const std::string& label, const tp::RectF& aArea);
bool isFired();
void eventProcess(const Events&) override;
void eventDraw(Canvas& canvas) override;
void setLabel(const std::string& string);
public:
void eventUpdateConfiguration(WidgetManager& wm) override;
public:
LabelWidget mLabel;
// State mStat = NONE;
RGBA pressedColor;
RGBA hoveredColor;
RGBA accentColor;
halnf rounding = 0;
std::function<void()> mCallback = [](){};
};
}

View file

@ -0,0 +1,51 @@
#pragma once
#include "ScrollableWidget.hpp"
#include "ButtonWidget.hpp"
namespace tp {
class CollapsableMenu : public Widget {
public:
CollapsableMenu();
void eventProcess(const Events&) override;
void eventDraw(Canvas& canvas) override;
public:
void addWidgetToMenu(Widget* widget);
void setLabel(const std::string& string);
void toggleCollapsed();
void setCollapsed(bool collapsed);
[[nodiscard]] bool getCollapsed() const;
void updateGeometry();
private:
RectF getHeaderRect();
RectF getBodyRect();
public:
void eventUpdateConfiguration(WidgetManager& wm) override;
protected:
ScrollableWindow mBody;
LabelWidget mHeader;
RGBA mMenuColor;
RGBA mBorderColor;
halnf headerHeight = 30;
halnf rounding = 0;
halnf mBorderSize = 0;
halnf mPadding = 0;
halnf mPrevHeight = 200;
bool mCollapsed = true;
bool mLocked = false;
bool mAdjustHeight = true;
public:
bool mBorders = true;
};
}

View file

@ -0,0 +1,18 @@
#include "FloatingWidget.hpp"
namespace tp {
class FloatingLayoutWidget : public Widget {
public:
FloatingLayoutWidget();
void eventProcess(const Events& events) override;
[[nodiscard]] bool handlesEvent() const;
private:
void updateActiveWindow(const tp::Events& events);
private:
bool mIsPassThrough = false;
};
}

View file

@ -0,0 +1,38 @@
#pragma once
#include "CollapsableMenu.hpp"
namespace tp {
class FloatingWidget : public CollapsableMenu {
public:
FloatingWidget();
void eventProcess(const Events& events) override;
void eventDraw(Canvas& canvas) override;
void eventUpdateConfiguration(WidgetManager& wm) override;
[[nodiscard]] bool isFloating() const;
void stopFloating();
private:
void checkFloating(const Events& events);
void checkResizing(const Events& events);
RectF getResizeHandle();
private:
Vec2F mMinSize = { 70, 70 };
halnf mResizeHandleSize = 10;
RGBA mResizeHandleColor = {};
bool mFloating = false;
bool mResizing = false;
Vec2F mActionStartRelativePos = {};
public:
bool mResizable = true;
bool mDropped = false;
};
}

View file

@ -0,0 +1,88 @@
#include "WidgetBase.hpp"
namespace tp {
class DockWidget : public Widget {
public:
enum Side { LEFT, TOP, RIGHT, BOTTOM, NONE };
private:
struct ResizeHandle {
RectF area{ 0, 0, 0, 0 };
halnf start{ 0 };
halnf end{ 0 };
bool active = false;
bool hover = false;
};
struct SideWidgetData {
Widget* widget = nullptr;
bool hidden = false;
halnf absoluteSize = 200;
alni order = -1;
Side side = { TOP };
RectF area = {};
RectF headerArea = {};
RectF previewHandleArea = {};
ResizeHandle resizeHandle;
};
public:
DockWidget();
void eventProcess(const Events& events) override;
void eventDraw(Canvas& canvas) override;
void eventDrawOver(Canvas& canvas) override;
void addSideWidget(Widget* widget, Side side);
void removeSideWidget(Side side);
void toggleHiddenState(Side side);
void setCenterWidget(Widget* widget);
Side getPreviewSide();
private:
void calculateSideAreas();
void calculateResizeHandles();
void handleResizeEvents(const Events& events);
void updateChildSideWidgets();
void calculateHeaderAreas();
bool isSideVisible(Side side);
bool sideExists(DockWidget::Side side);
ualni getVisibleSidesSize();
void handlePreview(const Events& events);
private:
RectF mPreviewArea = {};
Side mPreviewSide = NONE;
int resizeType[2] = { 0, 0 };
public:
SideWidgetData mSideWidgets[4];
private:
Widget* mCenterWidget = nullptr;
RectF mCenterArea {};
// Parameters
halnf mSideSizePadding = 150.f;
halnf mPadding = 4;
halnf mHeaderSize = 27;
halnf mRounding = 10;
Vec2F mPreviewHandleSize = { 50, 50 };
RGBA mResizeHandleColorHovered = RGBA(0.3, 0.3, 0.3, 1);
RGBA mResizeHandleColorActive = RGBA(0.6, 0.6, 0.6, 1);
RGBA mBackgroundColor = RGBA(0, 0, 0, 1);
RGBA mPreviewColor = RGBA(0.6, 0.6, 0.6, 1);
public:
bool mPreview = false;
};
}

View file

@ -0,0 +1,23 @@
#pragma once
#include "WidgetBase.hpp"
namespace tp {
class LabelWidget : public Widget {
public:
LabelWidget();
void eventDraw(Canvas& canvas) override;
public:
void eventUpdateConfiguration(WidgetManager& wm) override;
public:
std::string mLabel = "Label";
halnf fontSize = 10;
halnf padding = 0;
RGBA fontColor = { 1, 1, 1, 1 };
};
}

View file

@ -0,0 +1,71 @@
#pragma once
#include "WidgetBase.hpp"
#include "Buffer.hpp"
namespace tp {
class ScrollBarWidget : public Widget {
public:
ScrollBarWidget();
// takes whole area
void eventProcess(const Events& events) override;
void eventDraw(Canvas& canvas) override;
RectF getHandleHandle() const;
RectF getViewport() const;
RectF getHandle() const;
public:
void eventUpdateConfiguration(WidgetManager& wm) override;
public:
bool mIsScrolling = false;
halnf mSizeFraction = 1.f;
halnf mPositionFraction = 0.f;
bool mHovered = false;
RGBA mDefaultColor;
RGBA mHandleColor;
RGBA mHoveredColor;
RGBA mScrollingColor;
halnf mPadding = 0;
halnf mHandleSize = 10;
halnf mMinSize = 10;
halnf mRounding = 10;
};
class ScrollableWindow : public Widget {
public:
ScrollableWindow();
virtual ~ScrollableWindow();
// takes whole area
void eventProcess(const Events& events) override;
void addWidget(Widget* widget);
void clearContent();
List<Widget*>& getContent();
void eventUpdateConfiguration(WidgetManager& wm) override;
[[nodiscard]] halnf getContentSize() const;
private:
void updateContents(List<Widget*>& contentWidgets);
// ready content size
void updateContentSize(List<Widget*>& contentWidgets);
void setOffset(List<Widget*>& contentWidgets, const halnf offset);
private:
Widget mContentWidget;
ScrollBarWidget mScroller;
halnf mContentSize = 0;
halnf mPadding = 0;
};
}

View file

@ -0,0 +1,41 @@
#pragma once
#include "LabelWidget.hpp"
namespace tp {
class SliderWidget : public Widget {
public:
SliderWidget();
void eventProcess(const Events& events) override;
void eventDraw(Canvas& canvas) override;
RectF getHandle() const;
public:
void eventUpdateConfiguration(WidgetManager& wm) override;
public:
halnf mFactor = 0.f;
bool mIsSliding = false;
RGBA defaultColor;
RGBA handleColor;
halnf handleSize = 0;
halnf rounding = 0;
halnf borderSize = 2;
};
class NamedSliderWidget : public Widget {
public:
explicit NamedSliderWidget(const char* name = "Value");
void eventProcess(const Events& events) override;
public:
SliderWidget mSlider;
LabelWidget mLabel;
halnf mFactor = 0.5f;
};
}

View file

@ -0,0 +1,29 @@
#pragma once
#include "WidgetBase.hpp"
namespace tp {
class TextInputWidget : public Widget {
public:
TextInputWidget();
void eventDraw(Canvas&) override;
public:
void eventUpdateConfiguration(WidgetManager& wm) override;
public:
enum { mMaxBufferSize = 512 };
char mBuff[mMaxBufferSize] = "";
bool nChanged = false;
std::string mValue;
std::string mId = "id";
bool mMultiline = false;
RGBA mAccentColor;
RGBA mHoveredColor;
RGBA mBaseColor;
halnf mRounding = 0;
halnf mPadding = 0;
};
}

View file

@ -0,0 +1,78 @@
#pragma once
#include "Graphics.hpp"
#include "EventHandler.hpp"
#include "WidgetManager.hpp"
#include "List.hpp"
namespace tp {
using Events = EventHandler;
class Widget {
public:
Widget();
virtual ~Widget();
void procWrapper(const Events& events, const RectF& parentArea);
void drawWrapper(Canvas& canvas);
void updateConfigWrapper(WidgetManager& wm);
virtual void eventProcess(const Events& events);
// draws before child widgets
virtual void eventDraw(Canvas& canvas);
// draws overlay after child widgets
virtual void eventDrawOver(Canvas& canvas);
virtual void eventUpdateConfiguration(WidgetManager& wm);
virtual void eventVisible(const Events& events);
virtual void eventNotVisible(const Events& events);
virtual void eventFocusEnter(const Events& events);
virtual void eventFocusLeave(const Events& events);
virtual void eventPressed(const Events& events);
virtual void eventReleased(const Events& events);
public:
void setEnable(bool enable);
void setVisible(bool visible);
void setArea(const RectF& area);
[[nodiscard]] const RectF& getArea() const;
[[nodiscard]] bool isFocus() const;
[[nodiscard]] bool isPressed() const;
[[nodiscard]] bool isReleased() const;
[[nodiscard]] bool isHolding() const;
void clearEvents();
private:
void checkVisibility(const Events& events, const RectF& parentArea);
void checkFocus(const Events& events);
void checkClicked(const Events& events);
public:
RectF mArea;
RectF mVisibleArea;
List<Widget*> mChildWidgets;
bool mVisible = false;
bool mEnable = true;
bool mHandlesEvents = true;
bool mInFocus = false;
bool mHolding = false;
bool mPressed = false;
bool mReleased = false;
// docking
bool mIsDocked = false;
};
}

View file

@ -0,0 +1,89 @@
#pragma once
#include "Animations.hpp"
#include "Map.hpp"
#include "Rect.hpp"
#include "InputCodes.hpp"
#include "Buffer.hpp"
namespace tp {
struct WidgetConfig {
struct Shortcut {
struct Condition {
std::string name;
std::string state;
};
std::string callbackName;
Shortcut() = default;
Shortcut(const InitialierList<Condition>&) {}
};
struct Parameter {
enum Type { NONE, VAL, COL };
halnf value = 0.f;
RGBA color = {};
Type type = NONE;
bool globalReference = false;
std::string globalId;
Parameter() = default;
explicit Parameter(halnf val) {
type = VAL;
value = val;
}
explicit Parameter(const RGBA& val) {
type = COL;
color = val;
}
explicit Parameter(const std::string& id, const Type& referenceType) {
type = referenceType;
globalId = id;
globalReference = true;
}
};
Map<std::string, Parameter> mParameters;
Buffer<Shortcut> mShortcuts;
};
class WidgetManager {
public:
using Parameter = WidgetConfig::Parameter;
public:
WidgetManager();
~WidgetManager();
const RGBA& getColor(const std::string& parameterId, const RGBA& defaultValue);
const RGBA& getColor(const std::string& parameterId, const char* globalRef);
halnf getNumber(const std::string& parameterId, halnf defaultValue);
halnf getNumber(const std::string& parameterId, const char* globalRef);
void setActiveId(const std::string& id);
private:
WidgetConfig& getWidgetConfig(const std::string& id);
Parameter& getParameter(WidgetConfig& config, const std::string& id, const Parameter& defaultValue);
void initGlobalParameters();
private:
Map<std::string, WidgetConfig> mConfigurations;
WidgetConfig mGlobalConfig;
RGBA mErrorColor = { 0, 0, 0, 1 };
halnf mErrorNumber = 0;
std::string mActiveId;
};
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "Animations.hpp"
#include "ButtonWidget.hpp"
#include "LabelWidget.hpp"
#include "ScrollableWidget.hpp"
#include "TextInputWidget.hpp"
#include "SliderWidget.hpp"
#include "CollapsableMenu.hpp"
#include "FloatingWidget.hpp"
#include "FloatingLayoutWidget.hpp"
#include "GridLayoutWidget.hpp"
#include "WorkspaceWidget.hpp"

View file

@ -0,0 +1,19 @@
#pragma once
#include "Widgets.hpp"
namespace tp {
class WorkspaceWidget : public Widget {
public:
WorkspaceWidget();
void eventProcess(const Events& events) override;
protected:
DockWidget mDockSpace;
FloatingLayoutWidget mFloatingLayer;
// Parameters
Vec2F mDefaultFloatSize = { 200, 200 };
};
}

View file

@ -1,14 +1,14 @@
--- ---
BasedOnStyle: LLVM BasedOnStyle: LLVM
AccessModifierOffset: -2 AccessModifierOffset: -2
AlignAfterOpenBracket: Align AlignAfterOpenBracket: BlockIndent
AlignArrayOfStructures: Left AlignArrayOfStructures: None
AlignConsecutiveAssignments: AlignConsecutiveAssignments:
Enabled: false Enabled: false
AcrossEmptyLines: false AcrossEmptyLines: false
AcrossComments: false AcrossComments: false
AlignCompound: false AlignCompound: false
PadOperators: true PadOperators: false
AlignConsecutiveBitFields: AlignConsecutiveBitFields:
Enabled: false Enabled: false
AcrossEmptyLines: false AcrossEmptyLines: false
@ -22,23 +22,22 @@ AlignConsecutiveDeclarations:
AlignCompound: false AlignCompound: false
PadOperators: false PadOperators: false
AlignConsecutiveMacros: AlignConsecutiveMacros:
Enabled: true Enabled: false
AcrossEmptyLines: false AcrossEmptyLines: false
AcrossComments: false AcrossComments: false
AlignCompound: false AlignCompound: false
PadOperators: false PadOperators: false
AlignEscapedNewlines: Left AlignEscapedNewlines: Left
AlignOperands: Align AlignOperands: Align
AlignTrailingComments: AlignTrailingComments: true
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Always AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: true AllowShortCaseLabelsOnASingleLine: true
AllowShortEnumsOnASingleLine: true AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AllowShortLambdasOnASingleLine: All AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
@ -47,13 +46,13 @@ AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes AlwaysBreakTemplateDeclarations: Yes
AttributeMacros: AttributeMacros:
- __capability - __capability
BinPackArguments: true BinPackArguments: false
BinPackParameters: true BinPackParameters: false
BitFieldColonSpacing: Both BitFieldColonSpacing: Both
BraceWrapping: BraceWrapping:
AfterCaseLabel: false AfterCaseLabel: true
AfterClass: false AfterClass: true
AfterControlStatement: Never AfterControlStatement: Always
AfterEnum: false AfterEnum: false
AfterFunction: false AfterFunction: false
AfterNamespace: false AfterNamespace: false
@ -69,29 +68,28 @@ BraceWrapping:
SplitEmptyFunction: true SplitEmptyFunction: true
SplitEmptyRecord: true SplitEmptyRecord: true
SplitEmptyNamespace: true SplitEmptyNamespace: true
BreakAfterAttributes: Never
BreakAfterJavaFieldAnnotations: false BreakAfterJavaFieldAnnotations: false
BreakArrays: true
BreakBeforeBinaryOperators: None BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach BreakBeforeBraces: Attach
BreakBeforeConceptDeclarations: Always BreakBeforeConceptDeclarations: Always
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon BreakConstructorInitializers: AfterColon
BreakInheritanceList: BeforeColon BreakInheritanceList: BeforeColon
BreakStringLiterals: true BreakStringLiterals: true
ColumnLimit: 180 ColumnLimit: 120
CommentPragmas: "^ IWYU pragma:" CommentPragmas: "^ IWYU pragma:"
CompactNamespaces: false CompactNamespaces: false
ConstructorInitializerIndentWidth: 4 ConstructorInitializerAllOnOneLineOrOnePerLine: false
ContinuationIndentWidth: 4 ConstructorInitializerIndentWidth: 2
Cpp11BracedListStyle: true ContinuationIndentWidth: 2
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: false DerivePointerAlignment: false
DisableFormat: false DisableFormat: false
EmptyLineAfterAccessModifier: Never EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true FixNamespaceComments: false
ForEachMacros: ForEachMacros:
- foreach - foreach
- Q_FOREACH - Q_FOREACH
@ -117,28 +115,19 @@ IncludeIsMainSourceRegex: ""
IndentAccessModifiers: false IndentAccessModifiers: false
IndentCaseBlocks: true IndentCaseBlocks: true
IndentCaseLabels: true IndentCaseLabels: true
IndentExternBlock: Indent IndentExternBlock: AfterExternBlock
IndentGotoLabels: true IndentGotoLabels: true
IndentPPDirectives: BeforeHash IndentPPDirectives: None
IndentRequiresClause: true IndentRequiresClause: true
IndentWidth: 2 IndentWidth: 2
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
InsertBraces: true InsertBraces: false
InsertNewlineAtEOF: true
InsertTrailingCommas: None InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigits: 0
Decimal: 0
DecimalMinDigits: 0
Hex: 0
HexMinDigits: 0
JavaScriptQuotes: Leave JavaScriptQuotes: Leave
JavaScriptWrapImports: true JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature LambdaBodyIndentation: Signature
Language: Cpp Language: Cpp
LineEnding: DeriveLF
MacroBlockBegin: "" MacroBlockBegin: ""
MacroBlockEnd: "" MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
@ -149,7 +138,7 @@ ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true ObjCSpaceBeforeProtocolList: true
PPIndentWidth: -1 PPIndentWidth: -1
PackConstructorInitializers: CurrentLine PackConstructorInitializers: Never
PenaltyBreakAssignment: 2 PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300 PenaltyBreakComment: 300
@ -161,25 +150,23 @@ PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0 PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 60 PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left PointerAlignment: Left
QualifierAlignment: Custom QualifierAlignment: Leave
ReferenceAlignment: Pointer ReferenceAlignment: Pointer
ReflowComments: true ReflowComments: true
RemoveBracesLLVM: false RemoveBracesLLVM: false
RemoveSemicolon: true
RequiresClausePosition: OwnLine RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope SeparateDefinitionBlocks: Leave
SeparateDefinitionBlocks: Always ShortNamespaceLines: 1
ShortNamespaceLines: 1000 SortIncludes: Never
SortIncludes: CaseSensitive
SortJavaStaticImport: Before SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric SortUsingDeclarations: true
SpaceAfterCStyleCast: true SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: true SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements SpaceBeforeParens: ControlStatements
@ -214,15 +201,11 @@ StatementMacros:
- Q_UNUSED - Q_UNUSED
- QT_REQUIRE_VERSION - QT_REQUIRE_VERSION
TabWidth: 2 TabWidth: 2
UseTab: Never UseCRLF: false
UseTab: ForContinuationAndIndentation
WhitespaceSensitiveMacros: WhitespaceSensitiveMacros:
- BOOST_PP_STRINGIZE
- CF_SWIFT_NAME
- NS_SWIFT_NAME
- PP_STRINGIZE
- STRINGIZE - STRINGIZE
QualifierOrder: - PP_STRINGIZE
- inline - BOOST_PP_STRINGIZE
- static - NS_SWIFT_NAME
- const - CF_SWIFT_NAME
- type

16
.cproject Normal file
View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="org.eclipse.cdt.core.default.config.612128043">
<storageModule buildSystemId="org.eclipse.cdt.core.defaultConfigDataProvider" id="org.eclipse.cdt.core.default.config.612128043" moduleId="org.eclipse.cdt.core.settings" name="Configuration">
<externalSettings/>
<extensions/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.pathentry">
<pathentry excluding="**/CMakeFiles/**" kind="out" path="build"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
</cproject>

View file

@ -0,0 +1,428 @@
<mxfile host="Electron" modified="2023-10-29T20:02:24.324Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.0.3 Chrome/114.0.5735.289 Electron/25.8.4 Safari/537.36" etag="26yH0Gc3erZ3uKcA6DFE" version="22.0.3" type="device">
<diagram name="Page-1" id="8edUMiMEU_fADqxzhr4b">
<mxGraphModel dx="1062" dy="-128" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="850" pageHeight="1100" background="none" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="Knp0EVw5rfMEdcPhjhnq-158" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-22" target="Knp0EVw5rfMEdcPhjhnq-141" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<UserObject label="User Regular Language Rulles" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-22">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="380" y="1237" width="179" height="60" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-157" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-53" target="Knp0EVw5rfMEdcPhjhnq-146" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<UserObject label="User Context Free Language Rulles" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-53">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="482" y="1610" width="179" height="60" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-116" value="Compiler API Rulles To parse Regular grammar Rulles" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;startSize=23;" parent="1" vertex="1">
<mxGeometry x="175" y="1351" width="384" height="158" as="geometry">
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
</mxGeometry>
</mxCell>
<UserObject label="RE Compiler API Rulles" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-124">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-116" vertex="1">
<mxGeometry x="24" y="37.5" width="332" height="46.5" as="geometry" />
</mxCell>
</UserObject>
<UserObject label="CF Compiler API Rulles" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-125">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-116" vertex="1">
<mxGeometry x="24" y="98.5" width="336" height="46.5" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-126" value="CF Parser" style="swimlane;whiteSpace=wrap;html=1;startSize=23;" parent="1" vertex="1">
<mxGeometry x="2269" y="1405" width="999" height="823" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-13" value="Acceptor" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
<mxGeometry x="416" y="171" width="293" height="203" as="geometry">
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-34" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="Knp0EVw5rfMEdcPhjhnq-13" source="Knp0EVw5rfMEdcPhjhnq-14" target="Knp0EVw5rfMEdcPhjhnq-19" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-35" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="Knp0EVw5rfMEdcPhjhnq-13" source="Knp0EVw5rfMEdcPhjhnq-14" target="Knp0EVw5rfMEdcPhjhnq-18" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-36" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="Knp0EVw5rfMEdcPhjhnq-13" source="Knp0EVw5rfMEdcPhjhnq-14" target="Knp0EVw5rfMEdcPhjhnq-20" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<UserObject label="Automation" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-14">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-13" vertex="1">
<mxGeometry x="92" y="81.5" width="120" height="60" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-18" value="SymbolStream" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-13" vertex="1">
<mxGeometry x="103.5" y="42" width="97" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-19" value="AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-13" vertex="1">
<mxGeometry x="131.5" y="159" width="41" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-20" value="Tables" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-13" vertex="1">
<mxGeometry x="15" y="98.5" width="53" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-54" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-37" target="Knp0EVw5rfMEdcPhjhnq-13" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-55" value="Get Symbol" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="Knp0EVw5rfMEdcPhjhnq-54" vertex="1" connectable="0">
<mxGeometry x="-0.5956" y="-1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-137" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-37" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="953.4782608695655" y="398.6521739130435" as="targetPoint" />
<Array as="points">
<mxPoint x="563" y="733" />
<mxPoint x="919" y="733" />
<mxPoint x="919" y="399" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-37" value="Acceptor" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
<mxGeometry x="416" y="490" width="293" height="203" as="geometry">
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-38" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="Knp0EVw5rfMEdcPhjhnq-37" source="Knp0EVw5rfMEdcPhjhnq-41" target="Knp0EVw5rfMEdcPhjhnq-43" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-39" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="Knp0EVw5rfMEdcPhjhnq-37" source="Knp0EVw5rfMEdcPhjhnq-41" target="Knp0EVw5rfMEdcPhjhnq-42" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-40" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="Knp0EVw5rfMEdcPhjhnq-37" source="Knp0EVw5rfMEdcPhjhnq-41" target="Knp0EVw5rfMEdcPhjhnq-44" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<UserObject label="Automation" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-41">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-37" vertex="1">
<mxGeometry x="92" y="81.5" width="120" height="60" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-42" value="SymbolStream" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-37" vertex="1">
<mxGeometry x="103.5" y="42" width="97" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-43" value="AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-37" vertex="1">
<mxGeometry x="131.5" y="159" width="41" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-44" value="Tables" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-37" vertex="1">
<mxGeometry x="15" y="98.5" width="53" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-59" value="Finate State Automation" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
<mxGeometry x="721" y="175.5" width="146" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-60" value="Push Down Automation" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
<mxGeometry x="726" y="490" width="143" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-131" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-82" target="Knp0EVw5rfMEdcPhjhnq-37" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-134" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-82" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="24.947368421052943" y="591.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-82" value="CFG Compiler" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
<mxGeometry x="93" y="448.5" width="281" height="286" as="geometry">
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-88" value="CF Comp Rules" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-82" vertex="1">
<mxGeometry x="7" y="130" width="103" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-90" value="Tables" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-82" vertex="1">
<mxGeometry x="210" y="132.5" width="53" height="26" as="geometry" />
</mxCell>
<UserObject label="LL" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-91">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-82" vertex="1">
<mxGeometry x="116" y="51.75" width="83" height="46.5" as="geometry" />
</mxCell>
</UserObject>
<UserObject label="Canonical" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-92">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-82" vertex="1">
<mxGeometry x="116" y="119.75" width="83" height="46.5" as="geometry" />
</mxCell>
</UserObject>
<UserObject label="LALR" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-93">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-82" vertex="1">
<mxGeometry x="116" y="187.75" width="83" height="46.5" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-132" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-94" target="Knp0EVw5rfMEdcPhjhnq-13" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-133" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-94" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="24.947368421052943" y="272.5" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-94" value="RE Compiler" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;startSize=23;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
<mxGeometry x="122" y="228.25" width="260" height="88.5" as="geometry">
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-95" value="RE Compiler Rulles" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-94" vertex="1">
<mxGeometry x="13" y="33.75" width="123" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-96" value="Tables" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-94" vertex="1">
<mxGeometry x="187" y="39.5" width="53" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-154" value="Sentence" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="Knp0EVw5rfMEdcPhjhnq-126" vertex="1">
<mxGeometry x="21" y="149.5" width="69" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-56" style="edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;" parent="Knp0EVw5rfMEdcPhjhnq-126" source="Knp0EVw5rfMEdcPhjhnq-13" target="Knp0EVw5rfMEdcPhjhnq-154" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="94" y="166" as="targetPoint" />
<Array as="points">
<mxPoint x="626" y="104" />
<mxPoint x="281" y="104" />
<mxPoint x="281" y="166" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-57" value="Get Symbol" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="Knp0EVw5rfMEdcPhjhnq-56" vertex="1" connectable="0">
<mxGeometry x="-0.0483" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-127" value="Compiler API Rulles To parse Regular grammar Rulles" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;startSize=23;" parent="1" vertex="1">
<mxGeometry x="285" y="1720" width="385" height="158" as="geometry">
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
</mxGeometry>
</mxCell>
<UserObject label="RE Compiler API Rulles" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-128">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-127" vertex="1">
<mxGeometry x="24" y="37.5" width="340" height="46.5" as="geometry" />
</mxCell>
</UserObject>
<UserObject label="CF Compiler API Rulles" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-129">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-127" vertex="1">
<mxGeometry x="24" y="98.5" width="340" height="46.5" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-162" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-130" target="Knp0EVw5rfMEdcPhjhnq-151" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<UserObject label="User Sentence" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-130">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="1063" y="1056" width="120" height="60" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-138" value="CF Parser" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="622" y="1273" width="337" height="173" as="geometry">
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-139" value="CF AST Rulles for Tokenizer" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-138" vertex="1">
<mxGeometry x="19" y="80" width="168" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-140" value="CF AST Rulles for an acceptor" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-138" vertex="1">
<mxGeometry x="19" y="125" width="180" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-141" value="CF Sentence" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-138" vertex="1">
<mxGeometry x="19" y="37" width="88" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-142" value="AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-138" vertex="1">
<mxGeometry x="265" y="73.5" width="41" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-143" value="CF Parser" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="714" y="1645" width="337" height="173" as="geometry">
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-144" value="CF AST Rulles for Tokenizer" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-143" vertex="1">
<mxGeometry x="19" y="80" width="168" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-145" value="CF AST Rulles for an acceptor" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-143" vertex="1">
<mxGeometry x="19" y="125" width="180" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-146" value="CF Sentence" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-143" vertex="1">
<mxGeometry x="19" y="37" width="88" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-147" value="AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-143" vertex="1">
<mxGeometry x="265" y="73.5" width="41" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-148" value="CF Parser" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="1391" y="1401" width="337" height="173" as="geometry">
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-149" value="RE Compiler API Rulles for FSA" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-148" vertex="1">
<mxGeometry x="36" y="79.75" width="189" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-150" value="CF Compiler API Rulles for an PDA acceptor" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-148" vertex="1">
<mxGeometry x="36" y="124" width="255" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-151" value="CF Sentence" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-148" vertex="1">
<mxGeometry x="19" y="37" width="88" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-152" value="Sentence AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" parent="Knp0EVw5rfMEdcPhjhnq-148" vertex="1">
<mxGeometry x="229" y="35" width="95" height="26" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-155" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-129" target="Knp0EVw5rfMEdcPhjhnq-145" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-156" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-128" target="Knp0EVw5rfMEdcPhjhnq-144" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-159" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-124" target="Knp0EVw5rfMEdcPhjhnq-139" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-160" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-125" target="Knp0EVw5rfMEdcPhjhnq-140" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-165" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" parent="1" source="B2JnEC1cqt8830IlIT0b-3" target="Knp0EVw5rfMEdcPhjhnq-149" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-166" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" parent="1" source="B2JnEC1cqt8830IlIT0b-1" target="Knp0EVw5rfMEdcPhjhnq-150" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Knp0EVw5rfMEdcPhjhnq-167" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" parent="1" source="Knp0EVw5rfMEdcPhjhnq-152" target="Knp0EVw5rfMEdcPhjhnq-168" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1909.9999999999995" y="1483" as="targetPoint" />
</mxGeometry>
</mxCell>
<UserObject label="User AST" treeRoot="1" id="Knp0EVw5rfMEdcPhjhnq-168">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
<mxGeometry x="1977" y="1190" width="120" height="60" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="B2JnEC1cqt8830IlIT0b-2" value="" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="Knp0EVw5rfMEdcPhjhnq-147" target="B2JnEC1cqt8830IlIT0b-1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1020" y="1732" as="sourcePoint" />
<mxPoint x="1408" y="1535" as="targetPoint" />
</mxGeometry>
</mxCell>
<UserObject label="AST to CF Compiler API" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-1">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" vertex="1" parent="1">
<mxGeometry x="1117" y="1613" width="197" height="46.5" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="B2JnEC1cqt8830IlIT0b-4" value="" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="Knp0EVw5rfMEdcPhjhnq-142" target="B2JnEC1cqt8830IlIT0b-3">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1032" y="1311" as="sourcePoint" />
<mxPoint x="1408" y="1490" as="targetPoint" />
</mxGeometry>
</mxCell>
<UserObject label="AST to RE Compiler API" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-3">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" vertex="1" parent="1">
<mxGeometry x="1107" y="1470.5" width="197" height="46.5" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="B2JnEC1cqt8830IlIT0b-41" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-42" target="B2JnEC1cqt8830IlIT0b-56">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<UserObject label="Language Grammar &lt;br&gt;(CF RE United Format)" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-42">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="422" y="2209" width="179" height="60" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="B2JnEC1cqt8830IlIT0b-45" value="Grammar For CF RE United Grammar Format" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;startSize=23;" vertex="1" parent="1">
<mxGeometry x="253" y="2439" width="384" height="158" as="geometry">
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
</mxGeometry>
</mxCell>
<UserObject label="RE Compiler API Rulles" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-46">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-45">
<mxGeometry x="24" y="37.5" width="332" height="46.5" as="geometry" />
</mxCell>
</UserObject>
<UserObject label="CF Compiler API Rulles" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-47">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-45">
<mxGeometry x="24" y="98.5" width="336" height="46.5" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="B2JnEC1cqt8830IlIT0b-51" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-52" target="B2JnEC1cqt8830IlIT0b-66">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<UserObject label="User Sentence" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-52">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="422" y="2132" width="180" height="60" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="B2JnEC1cqt8830IlIT0b-53" value="CF Parser" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" vertex="1" parent="1">
<mxGeometry x="700" y="2361" width="337" height="173" as="geometry">
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-54" value="CF AST Rulles for Tokenizer" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-53">
<mxGeometry x="19" y="80" width="168" height="26" as="geometry" />
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-55" value="CF AST Rulles for an acceptor" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-53">
<mxGeometry x="19" y="125" width="180" height="26" as="geometry" />
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-56" value="CF Sentence" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-53">
<mxGeometry x="19" y="37" width="88" height="26" as="geometry" />
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-57" value="AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-53">
<mxGeometry x="265" y="73.5" width="41" height="26" as="geometry" />
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-63" value="CF Parser" style="swimlane;rounded=0;swimlaneLine=0;fontColor=default;fontSize=14;" vertex="1" parent="1">
<mxGeometry x="1415" y="2271" width="337" height="173" as="geometry">
<mxRectangle x="453" y="256" width="50" height="44" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-64" value="RE Compiler API Rulles for FSA" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-63">
<mxGeometry x="36" y="79.75" width="189" height="26" as="geometry" />
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-65" value="CF Compiler API Rulles for an PDA acceptor" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-63">
<mxGeometry x="36" y="124" width="255" height="26" as="geometry" />
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-66" value="CF Sentence" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-63">
<mxGeometry x="19" y="37" width="88" height="26" as="geometry" />
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-67" value="Sentence AST" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;rounded=0;" vertex="1" parent="B2JnEC1cqt8830IlIT0b-63">
<mxGeometry x="229" y="35" width="95" height="26" as="geometry" />
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-70" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-46" target="B2JnEC1cqt8830IlIT0b-54">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-71" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;startArrow=none;endArrow=none;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-47" target="B2JnEC1cqt8830IlIT0b-55">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-72" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-79" target="B2JnEC1cqt8830IlIT0b-64">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-73" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-77" target="B2JnEC1cqt8830IlIT0b-65">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="B2JnEC1cqt8830IlIT0b-74" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-67" target="B2JnEC1cqt8830IlIT0b-75">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1933.9999999999995" y="2353" as="targetPoint" />
</mxGeometry>
</mxCell>
<UserObject label="User AST" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-75">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
<mxGeometry x="2001" y="2060" width="120" height="60" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="B2JnEC1cqt8830IlIT0b-76" value="" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-57" target="B2JnEC1cqt8830IlIT0b-77">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1044" y="2601.5" as="sourcePoint" />
<mxPoint x="1432" y="2405" as="targetPoint" />
</mxGeometry>
</mxCell>
<UserObject label="AST to CF Compiler API" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-77">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" vertex="1" parent="1">
<mxGeometry x="1141" y="2483" width="197" height="46.5" as="geometry" />
</mxCell>
</UserObject>
<mxCell id="B2JnEC1cqt8830IlIT0b-78" value="" style="edgeStyle=elbowEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;" edge="1" parent="1" source="B2JnEC1cqt8830IlIT0b-57" target="B2JnEC1cqt8830IlIT0b-79">
<mxGeometry relative="1" as="geometry">
<mxPoint x="1056" y="2181" as="sourcePoint" />
<mxPoint x="1432" y="2360" as="targetPoint" />
</mxGeometry>
</mxCell>
<UserObject label="AST to RE Compiler API" treeRoot="1" id="B2JnEC1cqt8830IlIT0b-79">
<mxCell style="whiteSpace=wrap;html=1;align=center;treeFolding=1;treeMoving=1;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;startArrow&quot;:&quot;none&quot;,&quot;endArrow&quot;:&quot;none&quot;};labelBackgroundColor=none;rounded=0;" vertex="1" parent="1">
<mxGeometry x="1151" y="2371" width="197" height="46.5" as="geometry" />
</mxCell>
</UserObject>
</root>
</mxGraphModel>
</diagram>
</mxfile>

BIN
.docs/Gallery/Oscript.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
.docs/Gallery/RayTracer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
.docs/Gallery/Sketch3D.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

16
.docs/Gallery/oscript.txt Normal file
View file

@ -0,0 +1,16 @@
method myLogFunction(value) {
print value;
}
myLogFunction("hello");
var i = 10;
if (i == 10) {
while (i > 0) {
print i;
i = i - 1;
}
} else {
print "still doin' heavy calculations...";
}

17
.github/workflows/WindowsPlatform.yml vendored Normal file
View file

@ -0,0 +1,17 @@
name: Windows
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: self-hosted
steps:
- uses: actions/checkout@v3
#- name: Build
#run: echo hello

View file

@ -0,0 +1,62 @@
# This starter workflow is for a CMake project running on a single platform. There is a different starter workflow if you need cross-platform coverage.
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml
name: CMake on a single platform
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
# You can convert this to a matrix build if you need cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Sutup Dependencies
run: |
sudo apt-get update
sudo apt-get install python3 python-is-python3
sudo apt-get install -y libx11-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev
sudo apt-get install -y clang-15
sudo apt-get install -y libasound2-dev libglew-dev
sudo apt-get install -y portaudio19-dev
sudo apt-get install -y libwayland-dev libxkbcommon-dev
- name: install OpenImageDenoise
run: |
sudo snap install ispc
sudo apt-get install -y libtbb-dev
git clone --recursive https://github.com/RenderKit/oidn.git
cd oidn
mkdir build; cd build; cmake ..; make -j;
sudo make install
- name: Update repository
run: |
git submodule update --init --recursive
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -- -j$(nproc)
- name: Test
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}}

View file

@ -20,39 +20,45 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Setup externals - name: Setup
shell: bash shell: bash
run: | run: |
# If your submodules are configured to use SSH instead of HTTPS please uncomment the following line # If your submodules are configured to use SSH instead of HTTPS please uncomment the following line
# git config --global url."https://github.com/".insteadOf "git@github.com:" # git config --global url."https://github.com/".insteadOf "git@github.com:"
auth_header="$(git config --local --get http.https://github.com/.extraheader)" auth_header="$(git config --local --get http.https://github.com/.extraheader)"
git submodule sync --recursive git submodule sync --recursive
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
sudo apt-get update sudo apt-get update
sudo apt-get install python3 python-is-python3 sudo apt-get install python3 python-is-python3
sudo apt-get install -y libx11-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev sudo apt-get install -y libx11-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev
sudo apt-get install -y clang-15
sudo apt-get install -y libasound2-dev libglew-dev
sudo apt-get install -y portaudio19-dev
#cd Externals/glew/
#make extensions
sudo apt update
cd Externals/glew/ #- name: Set LLVM Toolchain
make extensions #run: |
# sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 10
- name: Set LLVM Toolchain # sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 20
run: |
sudo apt-get install -y llvm
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 10
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 20
- name: Configure CMake - name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} run: |
gcc -v
clang++-15 -v
CC=clang-15 CXX=clang++-15 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build - name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} run: CC=clang CXX=clang++ cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} -v -j
- name: Test - name: Test
working-directory: ${{github.workspace}}/build working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration. # Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}} run: ctest -j -C ${{env.BUILD_TYPE}}

5
.gitignore vendored
View file

@ -2,6 +2,11 @@
*tmp* *tmp*
bin bin
build* build*
*build*
lib lib
install install
.vscode .vscode
out
.vs
*.bkp
*.$*

37
.gitmodules vendored
View file

@ -1,15 +1,30 @@
[submodule "Externals/asio"]
path = Externals/asio
url = https://github.com/IlyaShurupov/asio.git
[submodule "Externals/glfw"]
path = Externals/glfw
url = https://github.com/IlyaShurupov/glfw.git
[submodule "Externals/imgui"] [submodule "Externals/imgui"]
path = Externals/imgui path = Externals/imgui
url = https://github.com/IlyaShurupov/imgui.git url = https://github.com/elushaX/imgui.git
[submodule "Externals/glew"] [submodule "Externals/lua"]
path = Externals/glew path = Externals/lua
url = https://github.com/IlyaShurupov/glew.git url = https://github.com/elushaX/lua.git
[submodule "Externals/unittest-cpp"]
path = Externals/unittest-cpp
url = https://github.com/elushaX/unittest-cpp.git
[submodule "Externals/glfw"]
path = Externals/glfw
url = https://github.com/elushaX/glfw.git
[submodule "Externals/nanovg"] [submodule "Externals/nanovg"]
path = Externals/nanovg path = Externals/nanovg
url = https://github.com/IlyaShurupov/nanovg.git url = https://github.com/elushaX/nanovg.git
[submodule "Externals/lalr"]
path = Externals/lalr
url = https://github.com/elushaX/lalr.git
[submodule "Externals/asio"]
path = Externals/asio
url = https://github.com/elushaX/asio.git
[submodule "Externals/implot"]
path = Externals/implot
url = https://github.com/epezent/implot.git
[submodule "Externals/googletest"]
path = Externals/googletest
url = https://github.com/google/googletest.git
[submodule "Externals/benchmark"]
path = Externals/benchmark
url = https://github.com/google/benchmark.git

View file

@ -1,53 +0,0 @@
#pragma once
#include "rect.h"
#include "color.h"
namespace tp {
namespace glw {
extern bool gInTransition;
struct AnimValue {
halnf mValPrev = 0;
halnf mVal = 0;
time_ms mTimeStart = 0;
halni mTimeAnim = 250;
halnf interpolate() const;
AnimValue();
AnimValue(halnf val);
halnf prev() { return mValPrev; }
void set(halnf val);
void setNoTransition(halnf);
void setAnimTime(halni time);
halnf get() const;
halnf getTarget() const;
bool inTransition() const;
explicit operator halnf() const;
void operator=(halnf val);
};
struct AnimRect : rect<AnimValue> {
AnimRect() {
set({ 0, 0, 0, 0 });
setAnimTime(450);
}
rectf get() const;
rectf getTarget() const;
void setNoTransition(rectf);
void set(const rectf&);
void setAnimTime(halni time_ms);
};
struct AnimColor {
AnimRect mColor;
rgba get() const;
void set(const rgba&);
};
};
};

View file

@ -1,84 +0,0 @@
#pragma once
#include "stringt.h"
#include "fbuffer.h"
namespace tp {
namespace glw {
class Canvas {
typedef rectf Rect;
typedef vec2f Vec2;
typedef rgba Col;
typedef tp::halnf Val;
Col mColorPrimary;
Col mColorSecondary;
void* mCtx = NULL;
tp::halnf mDpmm = 1;
tp::halnf mUIScale = 1;
public:
Rect mClamping;
Rect mVieport;
enum Align : uint4 {
LEFT = 1 << 0, // Default, horizontally to left.
CENTER = 1 << 1, // horizontally to center.
RIGHT = 1 << 2, // horizontally to right.
TOP = 1 << 3, // vertically to top.
MIDDLE = 1 << 4, // vertically to middle.
BOTTOM = 1 << 5, // vertically to bottom.
BASELINE = 1 << 6, // Default, vertically to baseline.
CENTER_MIDDLE = CENTER | MIDDLE,
LEFT_MIDDLE = LEFT | MIDDLE,
};
Canvas();
Val& convert2pxls(Val&);
Rect& convert2pxls(Rect&);
Vec2& convert2pxls(Vec2&);
Val as2pxls(Val);
// Canvas Manipulation
void beginDraw(Rect viewport, tp::halnf dpmm, tp::halnf uiscale);
void clear(Col color = 0);
void endDraw();
void setClamping(Rect rec);
void resetViewport();
// Params control
void setCol1(const Col& col);
void setCol2(const Col& col);
// Shapes
void rect(Rect rec, halnf rounding = 0, halnf borders = 0);
void circle(Vec2 rec, halnf radius, halnf borders = 0);
void trig(Vec2 p1, Vec2 p2, Vec2 p3);
void line(Vec2 p1, Vec2 p2, halnf thikness = 2);
// Text
void text(const string text, Rect rec, halnf size, Align align = Align::CENTER_MIDDLE);
void text(const char* start, const char* end, Rect rec, halnf size, Align align = Align::CENTER_MIDDLE);
void drawColorwheel(Rect rec, const rgb& col);
// image
struct ImageHandle {
halni mId = NULL;
void createFromBuff(glw::fbuffer* buff, Canvas* drawer);
void free(Canvas* drawer);
~ImageHandle();
};
void drawImage(Rect rec, ImageHandle* image, halnf angle = 0.f, halnf alpha = 1.f, halnf rounding = 0.f);
~Canvas();
};
};
};

View file

@ -1,48 +0,0 @@
#include "window.h"
namespace ImGui {
bool SubMenuBegin(const char* desc, int level);
void SubMenuEnd(int level);
void ToolTip(const char* desc);
struct PopupData {
bool opened = false;
bool ishovered = false;
tp::vec2f p1 = 0;
tp::vec2f p2 = 0;
operator bool() {
return opened;
}
};
PopupData HoverPopupBeginButton(const char* id, tp::vec2f butsize = 200, tp::vec2f popupsize = 200);
PopupData HoverPopupBegin(const char* id, tp::vec2f size = 200, tp::vec2f pos = -1, int flags = 0);
void HoverPopupEnd(PopupData& in);
void ApplyStyle(tp::halnf dpmm, float font_size_mm = 5, float ui_scale = 1);
};
namespace tp {
namespace glw {
typedef void (DebugUiDrawCallBack)(void* cd);
struct DebugUI {
tp::halnf mDPMM = 1;
tp::halnf mFontSizeMM = 3;
tp::halnf mUIScale = 1;
DebugUiDrawCallBack* cb = NULL;
void* cd = NULL;
struct DebugUiInternalContext* mCtx = NULL;
DebugUI(Window& window, DebugUiDrawCallBack* acb, void* acd);
void drawDebugUI(tp::halnf dpmm);
~DebugUI();
};
};
};

View file

@ -1,40 +0,0 @@
#pragma once
#include "rect.h"
#include "color.h"
namespace tp {
namespace glw {
class fbuffer {
uint4 mFrameBufferID = 0; // regroups 0, 1, or more textures, and 0 or 1 depth buffer.
uint4 mTextureId = 0; // texture we're going to render to ( colour attachement #0 )
uint4 mDepthBufferID = 0;
uint4 mDrawBuffers[1];
vec2f mSize;
public:
rgba mClearCol = 0.f;
fbuffer(const vec2f& size);
fbuffer(const vec2f& size, tp::uint1 samples);
void beginDraw();
void setViewport(const rectf& viewport);
void clear();
void endDraw();
uint4 texId() const;
uint4 buffId() const;
const vec2f& getSize() const;
uhalni sizeAllocatedMem() const;
uhalni sizeUsedMem() const;
~fbuffer();
};
};
};

View file

@ -1,36 +0,0 @@
#pragma once
namespace tp {
namespace glw {
class shader {
uint4 programm;
uint4 VertexShaderID;
uint4 FragmentShaderID;
uint4 GeometryShaderID;
public:
bool compile_shader(const char* ShaderCode, uint4 ShaderID);
void load(const char* vert, const char* geom, const char* frag, bool paths);
shader();
void vert_bind_source(const char* vert_src);
void frag_bind_source(const char* frag_src);
void geom_bind_source(const char* geom_src);
void compile();
shader(const char* vertid, const char* geomid, const char* fragid, bool paths = true);
void bind();
uint4 getu(const char* uid);
void unbind();
~shader();
alni sizeAllocatedMem();
alni sizeUsedMem();
};
};
};

View file

@ -1,71 +0,0 @@
#pragma once
#include "window.h"
#include "canvas.h"
#include "animations.h"
namespace tp {
namespace glw {
class WindowSimpleInputs {
enum class Mouse : uint1 { NONE, PRESSED, HOLD, RELEASED } mMouse;
enum class Move : uint1 { NONE, LEFT, RIGHT, UP, DOWN } mMove;
public:
halnf mScaleVal = 0;
vec2f mWindowSizeMM;
vec2f mCrs;
vec2f mCrsPrev;
vec2f mCrsmDelta;
halnf mPressure = 0.f;
void update(const glw::Window& window, halnf uiscale);
bool Activated();
bool Anticipating();
bool Selected();
bool MoveLeft();
bool MoveRight();
bool MoveUp();
bool MoveDown();
bool Drag();
};
struct ButtonWidget {
rectf mRect = { 0.f, 10.f };
rgba mCol = { 0.3f, 0.3f, 0.3f, 1.f };
bool mPressed = false;
AnimRect mAnimRec;
void draw(glw::Canvas& canvas);
void proc(glw::WindowSimpleInputs& inputs);
};
struct CheckBoxWidget {
rectf mRect = { 0.f, 10.f };
rgba mCol = { 0.3f, 0.3f, 0.3f, 1.f };
rgba mColActive = { 0.5f, 0.5f, 0.5f, 1.f };
bool mValue = false;
AnimRect mAnimRec;
AnimColor mAnimCol;
void draw(glw::Canvas& canvas);
void proc(glw::WindowSimpleInputs& inputs);
};
struct WindowsHeaderWidget {
rectf header_rec = { 10, 10, 50, 10 };
rgba col = { 0.13f, 0.13f, 0.13f, 0.9f };
rectf grab_rec = 0.f;
ButtonWidget mExitButton;
ButtonWidget mMaxButton;
ButtonWidget mMinButton;
CheckBoxWidget mPinButton;
void updRecs();
void draw(glw::Canvas& canvas);
void proc(glw::Window& window, glw::WindowSimpleInputs& inputs);
};
};
};

View file

@ -1,31 +0,0 @@
#pragma once
#include "array2d.h"
#include "color.h"
#include "vec.h"
namespace tp {
namespace glw {
class texture {
uint4 id;
public:
texture();
~texture();
uint4 getid();
void update(const Array2D<rgba>& buff);
void draw(const uint4& out = 0);
alni sizeAllocatedMem();
alni sizeUsedMem();
static void init();
static void deinit();
static void draw_texture(uint4 out, uint4 in);
static uint4 get_tex(const char* TexId);
static void drawCurcle(vec2f pos, double radius, rgba col);
};
};
};

View file

@ -1,114 +0,0 @@
#pragma once
#include "common.h"
#include "vec.h"
#include "rect.h"
#include "color.h"
#include "stringt.h"
#include "array.h"
#include "map.h"
#include "keycodes.h"
#include "queue.h"
namespace tp {
extern tp::ModuleManifest gModuleGlw;
namespace glw {
struct PlatformContext;
class Window {
public:
struct Device {
time_ms FrameRate = NULL; // monitor fps
vec2f Size; // size of the monitor
tp::halnf mDPMM = 1;
};
struct Events {
tp::Queue<KeyEvent> mKeysQueue;
tp::uhalni mRedraw = 2;
bool mClose = false;
vec2f mCursor = 0;
halnf mPressure = 1.f;
vec2f mCursorPrev = 0.f;
halnf mPressurePrev = 1.f;
};
struct Appearence {
vec2f mPos = { 100.f, 100.f }; // global position
vec2f mSize = { 300.f, 300.f }; // width and height of window
vec2f mSizeMin = { 100.f, 100.f }; // min size possiable
vec2f mSizeMax = { 700.f, 700.f }; // max size possiable
bool mHiden = true;
bool mMaximized = false;
bool mMinimized = false;
bool mTopZ = false;
bool mAllDesktops = false;
rgba mResizeColor = rgba(0.13f, 0.13f, 0.13f, 0.9f);
rectf mMinMaxBox;
tp::Array<rectf> mCaptionsAddArea;
tp::Array<rectf> mCaptionsRemoveArea;
};
public:
PlatformContext* mPlatformCtx = NULL;
void platformCallback();
void* platform_window() const;
struct NativeEventListenerCallback {
typedef void (call_back_func)(PlatformContext* ctx, void* cd);
call_back_func* exec_begin = NULL;
call_back_func* exec = NULL;
call_back_func* exec_end = NULL;
void* cd = NULL;
};
tp::HashMap<NativeEventListenerCallback, string> mNativeEventListeners;
private:
struct Cache {
Appearence mAppearencePrev;
vec2f mWindowSize = 0;
rectf mRectBeforResizing = 0;
bool mUserResizing = false;
bool mMinMaxHover = false;
bool mMouseTracked = false;
} mCache;
void applyAppearance();
void initialize();
public:
static Device mDevice;
Appearence mAppearence;
Events mEvents;
Window();
Window(const Appearence& aAppearence);
void pollEvents();
void beginDraw();
void endDraw();
alni sizeAllocatedMem();
alni sizeUsedMem();
~Window();
};
};
};

View file

@ -1,25 +0,0 @@
#pragma once
#include "queue.h"
struct AndroidApi {
union Event {
enum Type : tp::uint1 {
EV_NONE = 0,
} type = EV_NONE;
struct None {
} none;
};
tp::Queue<Event> events;
};
extern AndroidApi* gAndroidApi;

View file

@ -1,804 +0,0 @@
// Copyright (C) 2010 The Android Open Source Project
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// own headers
#include "window.h"
#include "GraphicsLibApi.h"
// STL
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <stdlib.h>
// jni
//#include <initializer_list>
//#include <memory>
//#include <cstdlib>
//#include <cstring>
#include <jni.h>
//#include <cerrno>
//#include <cassert>
// opengl
#include <EGL/egl.h>
#include <GLES3/gl32.h>
//#include "GL/glew.h"
// glue
#include <android/sensor.h>
#include <android/log.h>
#include <android/input.h>
#include <../../../android/native_app_glue/android_native_app_glue.h>
// AcquireASensorManagerInstance
#include <dlfcn.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
// application side entry point
int main();
// first function to be called in "main thread"
void* main_wrap(void* p);
// AcquireASensorManagerInstance(void)
// Workaround ASensorManager_getInstance() deprecation false alarm
// for Android-N and before, when compiling with NDK-r15
ASensorManager* AcquireASensorManagerInstance(android_app* app) {
if (!app)
return nullptr;
typedef ASensorManager* (*PF_GETINSTANCEFORPACKAGE)(const char* name);
void* androidHandle = dlopen("libandroid.so", RTLD_NOW);
auto getInstanceForPackageFunc = (PF_GETINSTANCEFORPACKAGE)
dlsym(androidHandle, "ASensorManager_getInstanceForPackage");
if (getInstanceForPackageFunc) {
JNIEnv* env = nullptr;
app->activity->vm->AttachCurrentThread(&env, nullptr);
jclass android_content_Context = env->GetObjectClass(app->activity->clazz);
jmethodID midGetPackageName = env->GetMethodID(android_content_Context,
"getPackageName",
"()Ljava/lang/String;");
auto packageName = (jstring)env->CallObjectMethod(app->activity->clazz,
midGetPackageName);
const char* nativePackageName = env->GetStringUTFChars(packageName, nullptr);
ASensorManager* mgr = getInstanceForPackageFunc(nativePackageName);
env->ReleaseStringUTFChars(packageName, nativePackageName);
app->activity->vm->DetachCurrentThread();
if (mgr) {
dlclose(androidHandle);
return mgr;
}
}
typedef ASensorManager* (*PF_GETINSTANCE)();
auto getInstanceFunc = (PF_GETINSTANCE)
dlsym(androidHandle, "ASensorManager_getInstance");
// by all means at this point, ASensorManager_getInstance should be available
assert(getInstanceFunc);
dlclose(androidHandle);
return getInstanceFunc();
}
void GL_APIENTRY MessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) {
DBG_BREAK(true);
LOGW("GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type, severity, message);
}
char const* gl_error_string(GLenum const err) {
switch (err) {
case GL_NO_ERROR: return "GL_NO_ERROR";
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW";
case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW";
case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION";
default: return "unknown error";
}
}
void glerr(GLenum type) {
DBG_BREAK(true);
const GLchar* message = gl_error_string(type);
LOGW("GL CALLBACK: %s type = 0x%x, message = %s\n", (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type, message);
}
void glerr(GLenum type);
#define AssertGL(x) { x; GLenum __gle = glGetError(); if (__gle != GL_NO_ERROR) glerr(__gle); }
// --------------------------------- Data --------------------------------------- //
struct MutexEvent {
pthread_mutex_t mutex;
tp::glw::Window* active_windw;
bool parent_thread_has_events = false;
bool child_whaiting = false;
} mutex_event;
struct ANativeActivityCtx* android_ctx = NULL;
tp::glw::Window::Device tp::glw::Window::mDevice;
extern const char* g_android_internal_data_path;
static pthread_t worker_thread;
static pthread_mutex_t worker_finished_mutex;
static pthread_cond_t worker_finished_cond;
static bool worker_finished = false;
namespace tp {
namespace glw {
struct PlatformContext {
int col = 255;
EGLint w, h, format;
EGLint numConfigs;
EGLConfig config = nullptr;
EGLSurface surface;
EGLContext context;
EGLDisplay display = nullptr;
AInputEvent* chache_event = NULL;
EGLint majorVersion, minorVersion;
// Initialize an EGL context for the current display.
PlatformContext(ANativeWindow* window) {
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (EGL_NO_DISPLAY == display) {
return;
}
if (eglInitialize(display, &majorVersion, &minorVersion) != EGL_TRUE) {
return;
}
// Here specify the attributes of the desired configuration.
// Below, we select an EGLConfig with at least 8 bits per color component compatible with on-screen windows
const EGLint attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, // request OpenGL ES 3.0
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, GLW_CONTEXT_DEPTH_BITS,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
// Here, the application chooses the configuration it desires.
// find the best match if possible, otherwise use the very first one
{
if (eglChooseConfig(display, attribs, nullptr, 0, &numConfigs) != EGL_TRUE) {
return;
}
std::unique_ptr<EGLConfig[]> supportedConfigs(new EGLConfig[numConfigs]);
assert(supportedConfigs);
if (eglChooseConfig(display, attribs, supportedConfigs.get(), numConfigs, &numConfigs) != EGL_TRUE) {
return;
}
assert(numConfigs);
auto i = 0;
for (; i < numConfigs; i++) {
auto& cfg = supportedConfigs[i];
EGLint r, g, b, d;
if (eglGetConfigAttrib(display, cfg, EGL_RED_SIZE, &r) &&
eglGetConfigAttrib(display, cfg, EGL_GREEN_SIZE, &g) &&
eglGetConfigAttrib(display, cfg, EGL_BLUE_SIZE, &b) &&
eglGetConfigAttrib(display, cfg, EGL_DEPTH_SIZE, &d) &&
r == 8 && g == 8 && b == 8 && d == GLW_CONTEXT_DEPTH_BITS) {
config = supportedConfigs[i];
break;
}
}
if (i == numConfigs) {
config = supportedConfigs[0];
}
if (config == nullptr) {
LOGW("Unable to initialize EGLConfig");
return;
}
}
const EGLint egl_context_attributes[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
//EGL_CONTEXT_MAJOR_VERSION, 3,
//EGL_CONTEXT_MINOR_VERSION, 0,
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
#ifdef ENV_BUILD_DEBUG
//EGL_CONTEXT_OPENGL_DEBUG, EGL_TRUE,
#endif
EGL_NONE
};
// EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
// guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
// As soon as we picked a EGLConfig, we can safely reconfigure the
// ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
surface = eglCreateWindowSurface(display, config, window, nullptr);
context = eglCreateContext(display, config, EGL_NO_CONTEXT, egl_context_attributes);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
LOGW("Unable to eglMakeCurrent");
return;
}
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
// Check openGL on the system
auto opengl_info = { GL_VENDOR, GL_RENDERER, GL_VERSION, GL_EXTENSIONS };
for (auto name : opengl_info) {
auto info = glGetString(name);
LOGI("OpenGL Info: %s", info);
}
// Initialize GL state.
//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
AssertGL(glEnable(GL_CULL_FACE));
//AssertGL(glShadeModel(GL_SMOOTH));
AssertGL(glEnable(GL_DEPTH_TEST));
AssertGL(glDepthFunc(GL_LESS));
GLint major = 0;
GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
glGetIntegerv(GL_DEPTH, &minor);
AssertGL(glEnable(GL_DEBUG_OUTPUT));
AssertGL(glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS));
AssertGL(glDebugMessageCallback(MessageCallback, 0));
tp::glw::Window::mDevice.Size = { w, h };
tp::glw::Window::mDevice.FrameRate = 60;
return;
}
void beginDraw() {
if (this->display == nullptr) { return; }
glViewport(0, 0, tp::glw::Window::mDevice.Size.x, tp::glw::Window::mDevice.Size.y);
//glClearColor(col / 255.f, col / 255.f, col / 255.f, 1);
//glClear(GL_COLOR_BUFFER_BIT);
//if (col++ > 255) {
//col = 0;
//}
}
void endDraw() {
eglSwapBuffers(display, surface);
}
// Tear down the EGL context currently associated with the display.
~PlatformContext() {
if (this->display != EGL_NO_DISPLAY) {
eglMakeCurrent(this->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (this->context != EGL_NO_CONTEXT) {
eglDestroyContext(this->display, this->context);
}
if (this->surface != EGL_NO_SURFACE) {
eglDestroySurface(this->display, this->surface);
}
eglTerminate(this->display);
}
display = EGL_NO_DISPLAY;
context = EGL_NO_CONTEXT;
surface = EGL_NO_SURFACE;
}
};
};
};
// ---------------------------------- Parent Thread ------------------------------------ //
#ifndef PARENT_THREAD
// Shared state for our app.
struct ANativeActivityCtx {
// Our saved state data.
struct saved_state {
float angle;
int32_t x;
int32_t y;
};
android_app* app;
ASensorManager* sensorManager;
const ASensor* accelerometerSensor;
ASensorEventQueue* sensorEventQueue;
int animating;
EGLDisplay display;
EGLSurface surface;
EGLContext context;
int32_t width;
int32_t height;
saved_state state;
ANativeActivityCtx(android_app* state) {
memset(this, 0, sizeof(*this));
state->userData = this;
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
app = state;
// Prepare to monitor accelerometer
sensorManager = AcquireASensorManagerInstance(state);
accelerometerSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER);
sensorEventQueue = ASensorManager_createEventQueue(sensorManager, state->looper, LOOPER_ID_USER, 0, 0);
// We are starting with a previous saved state; restore from it.
if (state->savedState != nullptr) {
this->state = *(saved_state*)state->savedState;
}
}
void proc_events_util() {
int ident;
int events;
struct android_poll_source* source;
auto window = mutex_event.active_windw;
if (window) {
for (auto proc : window->mNativeEventListeners) {
proc->val.exec_begin(window->mPlatformCtx, proc->val.cd);
}
}
// we loop until all events are read
while ((ident = ALooper_pollAll(0, nullptr, &events, (void**)&source)) >= 0) {
// Process this event.
if (source != nullptr) {
source->process(this->app, source);
}
// If a sensor has data, process it now.
if (ident == LOOPER_ID_USER) {
if (this->accelerometerSensor != nullptr) {
ASensorEvent event;
while (ASensorEventQueue_getEvents(this->sensorEventQueue, &event, 1) > 0) {
LOGI("accelerometer: x=%f y=%f z=%f", event.acceleration.x, event.acceleration.y, event.acceleration.z);
}
}
}
// Check if we are exiting.
if (this->app->destroyRequested != 0) {
DBG_BREAK(1);
}
}
if (window) {
for (auto proc : window->mNativeEventListeners) {
proc->val.exec_end(window->mPlatformCtx, proc->val.cd);
}
}
}
void proc_events() {
pthread_mutex_lock(&mutex_event.mutex);
auto threaded = mutex_event.active_windw;
pthread_mutex_unlock(&mutex_event.mutex);
if (!threaded) {
proc_events_util();
return;
}
// Read all pending events.
int ident;
int events;
struct android_poll_source* source;
// check if events exist and if so prepare to proccess them
if ((ident = ALooper_pollAll(0, nullptr, &events, (void**)&source)) >= 0) {
// signal child thread that we need to process those events
pthread_mutex_lock(&mutex_event.mutex);
mutex_event.parent_thread_has_events = true;
pthread_mutex_unlock(&mutex_event.mutex);
// whait until child thread pauses
bool whait = true;
while (whait) {
pthread_mutex_lock(&mutex_event.mutex);
whait = !mutex_event.child_whaiting;
pthread_mutex_unlock(&mutex_event.mutex);
}
}
else {
return;
}
pthread_mutex_lock(&mutex_event.mutex);
auto window = mutex_event.active_windw;
pthread_mutex_unlock(&mutex_event.mutex);
proc_events_util();
// signal to child continue to do its work
pthread_mutex_lock(&mutex_event.mutex);
mutex_event.parent_thread_has_events = false;
pthread_mutex_unlock(&mutex_event.mutex);
}
// Process the next input event.
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
auto* engine = (struct ANativeActivityCtx*)app->userData;
auto window = mutex_event.active_windw;
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
window->mEvents.mCursorPrev = window->mEvents.mCursor;
window->mEvents.mCursor.x = AMotionEvent_getX(event, 0);
window->mEvents.mCursor.y = AMotionEvent_getY(event, 0);
window->mEvents.mRedraw = 2;
int32_t event_action = AMotionEvent_getAction(event);
int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
event_action &= AMOTION_EVENT_ACTION_MASK;
if ((AMotionEvent_getToolType(event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
|| (AMotionEvent_getToolType(event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)) {
if (event_action == AMOTION_EVENT_ACTION_DOWN) {
window->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE1, tp::KeyEvent::EventState::PRESSED });
}
else if (event_action == AMOTION_EVENT_ACTION_UP) {
window->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE1, tp::KeyEvent::EventState::RELEASED });
}
}
}
if (window) {
window->mPlatformCtx->chache_event = event;
for (auto proc : window->mNativeEventListeners) {
proc->val.exec(window->mPlatformCtx, proc->val.cd);
}
}
return 0;
}
// Process the next main command.
static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
auto* engine = (struct ANativeActivityCtx*)app->userData;
auto window = mutex_event.active_windw;
switch (cmd) {
// The system has asked us to save our current state. Do so.
case APP_CMD_SAVE_STATE: {
engine->app->savedState = malloc(sizeof(ANativeActivityCtx::saved_state));
*((ANativeActivityCtx::saved_state*)engine->app->savedState) = engine->state;
engine->app->savedStateSize = sizeof(ANativeActivityCtx::saved_state);
} break;
// The window is being shown, get it ready.
case APP_CMD_INIT_WINDOW: {
if (engine->app->window != nullptr) {
//engine->init_display();
//engine->draw_frame();
}
} break;
// The window is being hidden or closed, clean it up.
case APP_CMD_TERM_WINDOW: {
//engine->term_display();
} break;
// When our app gains focus, we start monitoring the accelerometer.
case APP_CMD_GAINED_FOCUS: {
if (engine->accelerometerSensor != nullptr) {
ASensorEventQueue_enableSensor(engine->sensorEventQueue,
engine->accelerometerSensor);
// We'd like to get 60 events per second (in us).
ASensorEventQueue_setEventRate(engine->sensorEventQueue,
engine->accelerometerSensor,
(1000L / 60) * 1000);
}
} break;
// When our app loses focus, we stop monitoring the accelerometer.
// This is to avoid consuming battery while not being used.
case APP_CMD_LOST_FOCUS: {
if (engine->accelerometerSensor != nullptr) {
ASensorEventQueue_disableSensor(engine->sensorEventQueue,
engine->accelerometerSensor);
}
// Also stop animating.
engine->animating = 0;
//engine->draw_frame();
} break;
default: break;
}
}
};
#include <sys/stat.h>
void unsure_dir_exist(const char* path_to_file) {
char* temp_path = strdup(path_to_file);
for (char* p = temp_path + 1; *p; p++) {
if (*p == '/') {
*p = '\0';
int status = mkdir(temp_path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (status != 0 && errno != EEXIST) {
// handle error
break;
}
*p = '/';
}
}
free(temp_path);
}
// FIXME
void unpackAsset(AAssetManager* mgr, const char* filename, const std::string& path) {
AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING);
if (asset == NULL) {
return;
}
off_t length = AAsset_getLength(asset);
char* buffer = new char[length];
AAsset_read(asset, buffer, length);
unsure_dir_exist(path.c_str());
FILE* out = fopen(path.c_str(), "w");
if (out != NULL) {
fwrite(buffer, length, 1, out);
fclose(out);
}
delete[] buffer;
AAsset_close(asset);
}
// FIXME
void unpackDirectory(AAssetManager* mgr, const char* dirname, const std::string& path) {
AAssetDir* assetDir = AAssetManager_openDir(mgr, dirname);
const char* filename = NULL;
while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {
std::string assetPath = std::string(dirname) + "/" + filename;
std::string internalPath = path + "/" + std::string(dirname) + "/" + filename;
struct stat sb;
stat(assetPath.c_str(), &sb);
if (S_ISDIR(sb.st_mode)) {
unpackDirectory(mgr, assetPath.c_str(), internalPath);
}
else {
unpackAsset(mgr, assetPath.c_str(), internalPath);
}
}
AAssetDir_close(assetDir);
}
extern "C" {
// This is the main entry point of a native application that is using
// android_native_app_glue. It runs in its own thread, with its own
// event loop for receiving input events and doing other things.
void android_main(android_app* state) {
tp::print_env_info();
tp::alloc_init();
ANativeActivityCtx engine(state);
unpackDirectory(state->activity->assetManager, "", state->activity->internalDataPath);
unpackDirectory(state->activity->assetManager, "rsc", state->activity->internalDataPath);
unpackDirectory(state->activity->assetManager, "rsc/fonts", state->activity->internalDataPath);
android_ctx = &engine;
bool running = true;
while (running) {
engine.proc_events();
// whait until our app fully initialized
if (!engine.app->window) {
continue;
}
// run once
static bool main_thread_started = false;
if (!main_thread_started) {
// init types
g_android_internal_data_path = state->activity->internalDataPath;
// create main thread
pthread_create(&worker_thread, NULL, main_wrap, NULL);
pthread_mutex_init(&worker_finished_mutex, NULL);
pthread_cond_init(&worker_finished_cond, NULL);
main_thread_started = true;
continue;
}
// check for exit
pthread_mutex_lock(&worker_finished_mutex);
running = !worker_finished;
pthread_mutex_unlock(&worker_finished_mutex);
}
pthread_join(worker_thread, NULL);
tp::alloc_uninit();
}
};
#endif
// ------------------------------- Child thread --------------------------------------- //
#ifndef CHILD_THREAD
//#include <android/configuration.h>
//#include <android/native_activity.h>
AInputEvent* androidPlatformContextGetEvent(tp::glw::PlatformContext* ctx) {
return ctx->chache_event;
}
int32_t getDensityDpi(android_app* app) {
AConfiguration* config = AConfiguration_new();
AConfiguration_fromAssetManager(config, app->activity->assetManager);
int32_t density = AConfiguration_getDensity(config);
AConfiguration_delete(config);
return density;
}
// statics
void tp::glw::Window::init() {}
void tp::glw::Window::deinit() {}
void tp::glw::Window::initialize() {
mPlatformCtx = new PlatformContext(android_ctx->app->window);
applyAppearance();
AConfiguration* config = AConfiguration_new();
AConfiguration_fromAssetManager(config, android_ctx->app->activity->assetManager);
int32_t density = AConfiguration_getDensity(config);
AConfiguration_delete(config);
mDevice.mDPMM = density / 25.4f;
}
tp::glw::Window::Window() {
initialize();
pthread_mutex_lock(&mutex_event.mutex);
mutex_event.active_windw = this;
pthread_mutex_unlock(&mutex_event.mutex);
}
tp::glw::Window::Window(const Appearence& aAppearence) {
mAppearence = aAppearence;
initialize();
}
tp::glw::Window::~Window() {
delete mPlatformCtx;
}
void tp::glw::Window::applyAppearance() {
int width = ANativeWindow_getWidth(android_ctx->app->window);
int height = ANativeWindow_getHeight(android_ctx->app->window);
if (width != mAppearence.mSize.x || height != mAppearence.mSize.y) {
mEvents.mRedraw = 2;
}
mAppearence.mPos = mCache.mAppearencePrev.mPos = 0;
mAppearence.mSize.x = mCache.mAppearencePrev.mSize.x = tp::glw::Window::mDevice.Size.x = width;
mAppearence.mSize.y = mCache.mAppearencePrev.mSize.y = tp::glw::Window::mDevice.Size.y = height;
}
void tp::glw::Window::pollEvents() {
applyAppearance();
// check if parent thread has some events to pass
pthread_mutex_lock(&mutex_event.mutex);
bool has_event = mutex_event.parent_thread_has_events;
mutex_event.child_whaiting = has_event;
pthread_mutex_unlock(&mutex_event.mutex);
while (has_event) {
pthread_mutex_lock(&mutex_event.mutex);
has_event = mutex_event.parent_thread_has_events;
pthread_mutex_unlock(&mutex_event.mutex);
}
pthread_mutex_lock(&mutex_event.mutex);
mutex_event.child_whaiting = false;
pthread_mutex_unlock(&mutex_event.mutex);
}
void tp::glw::Window::platformCallback() {}
void tp::glw::Window::beginDraw() {
mPlatformCtx->beginDraw();
}
void tp::glw::Window::endDraw() {
mPlatformCtx->endDraw();
if (mEvents.mRedraw-- < 0) mEvents.mRedraw = 0;
}
void* tp::glw::Window::platform_window() const { return android_ctx->app->window; }
tp::alni tp::glw::Window::sizeAllocatedMem() { return 0; }
tp::alni tp::glw::Window::sizeUsedMem() { return 0; }
void* main_wrap(void* p) {
// exec main
main();
// mark as doen after completion
pthread_mutex_lock(&worker_finished_mutex);
worker_finished = true;
pthread_cond_signal(&worker_finished_cond);
pthread_mutex_unlock(&worker_finished_mutex);
// exit "main thread"
pthread_exit(NULL);
return NULL;
}
#endif

View file

@ -1,453 +0,0 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "android_native_app_glue.h"
#include <jni.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <android/log.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))
/* For debug builds, always enable the debug traces in this library */
#ifndef NDEBUG
# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))
#else
# define LOGV(...) ((void)0)
#endif
void free_saved_state(struct android_app* android_app) {
pthread_mutex_lock(&android_app->mutex);
if (android_app->savedState != NULL) {
free(android_app->savedState);
android_app->savedState = NULL;
android_app->savedStateSize = 0;
}
pthread_mutex_unlock(&android_app->mutex);
}
int8_t android_app_read_cmd(struct android_app* android_app) {
int8_t cmd;
if (read(android_app->msgread, &cmd, sizeof(cmd)) != sizeof(cmd)) {
LOGE("No data on command pipe!");
return -1;
}
if (cmd == APP_CMD_SAVE_STATE) free_saved_state(android_app);
return cmd;
}
void print_cur_config(struct android_app* android_app) {
char lang[2], country[2];
AConfiguration_getLanguage(android_app->config, lang);
AConfiguration_getCountry(android_app->config, country);
LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
"keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
"modetype=%d modenight=%d",
AConfiguration_getMcc(android_app->config),
AConfiguration_getMnc(android_app->config),
lang[0], lang[1], country[0], country[1],
AConfiguration_getOrientation(android_app->config),
AConfiguration_getTouchscreen(android_app->config),
AConfiguration_getDensity(android_app->config),
AConfiguration_getKeyboard(android_app->config),
AConfiguration_getNavigation(android_app->config),
AConfiguration_getKeysHidden(android_app->config),
AConfiguration_getNavHidden(android_app->config),
AConfiguration_getSdkVersion(android_app->config),
AConfiguration_getScreenSize(android_app->config),
AConfiguration_getScreenLong(android_app->config),
AConfiguration_getUiModeType(android_app->config),
AConfiguration_getUiModeNight(android_app->config));
}
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
switch (cmd) {
case APP_CMD_INPUT_CHANGED:
LOGV("APP_CMD_INPUT_CHANGED");
pthread_mutex_lock(&android_app->mutex);
if (android_app->inputQueue != NULL) {
AInputQueue_detachLooper(android_app->inputQueue);
}
android_app->inputQueue = android_app->pendingInputQueue;
if (android_app->inputQueue != NULL) {
LOGV("Attaching input queue to looper");
AInputQueue_attachLooper(android_app->inputQueue,
android_app->looper, LOOPER_ID_INPUT, NULL,
&android_app->inputPollSource);
}
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_INIT_WINDOW:
LOGV("APP_CMD_INIT_WINDOW");
pthread_mutex_lock(&android_app->mutex);
android_app->window = android_app->pendingWindow;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_TERM_WINDOW:
LOGV("APP_CMD_TERM_WINDOW");
pthread_cond_broadcast(&android_app->cond);
break;
case APP_CMD_RESUME:
case APP_CMD_START:
case APP_CMD_PAUSE:
case APP_CMD_STOP:
LOGV("activityState=%d", cmd);
pthread_mutex_lock(&android_app->mutex);
android_app->activityState = cmd;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_CONFIG_CHANGED:
LOGV("APP_CMD_CONFIG_CHANGED");
AConfiguration_fromAssetManager(android_app->config,
android_app->activity->assetManager);
print_cur_config(android_app);
break;
case APP_CMD_DESTROY:
LOGV("APP_CMD_DESTROY");
android_app->destroyRequested = 1;
break;
}
}
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
switch (cmd) {
case APP_CMD_TERM_WINDOW:
LOGV("APP_CMD_TERM_WINDOW");
pthread_mutex_lock(&android_app->mutex);
android_app->window = NULL;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_SAVE_STATE:
LOGV("APP_CMD_SAVE_STATE");
pthread_mutex_lock(&android_app->mutex);
android_app->stateSaved = 1;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_RESUME:
free_saved_state(android_app);
break;
}
}
void android_app_destroy(struct android_app* android_app) {
LOGV("android_app_destroy!");
free_saved_state(android_app);
pthread_mutex_lock(&android_app->mutex);
if (android_app->inputQueue != NULL) {
AInputQueue_detachLooper(android_app->inputQueue);
}
AConfiguration_delete(android_app->config);
android_app->destroyed = 1;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
// Can't touch android_app object after this.
}
void process_input(struct android_app* app, struct android_poll_source* source) {
AInputEvent* event = NULL;
while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
LOGV("New input event: type=%d", AInputEvent_getType(event));
if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
continue;
}
int32_t handled = 0;
if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
AInputQueue_finishEvent(app->inputQueue, event, handled);
}
}
void process_cmd(struct android_app* app, struct android_poll_source* source) {
int8_t cmd = android_app_read_cmd(app);
android_app_pre_exec_cmd(app, cmd);
if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
android_app_post_exec_cmd(app, cmd);
}
void* android_app_entry(void* param) {
struct android_app* android_app = (struct android_app*)param;
android_app->config = AConfiguration_new();
AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
print_cur_config(android_app);
android_app->cmdPollSource.id = LOOPER_ID_MAIN;
android_app->cmdPollSource.app = android_app;
android_app->cmdPollSource.process = process_cmd;
android_app->inputPollSource.id = LOOPER_ID_INPUT;
android_app->inputPollSource.app = android_app;
android_app->inputPollSource.process = process_input;
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
&android_app->cmdPollSource);
android_app->looper = looper;
pthread_mutex_lock(&android_app->mutex);
android_app->running = 1;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
android_main(android_app);
android_app_destroy(android_app);
return NULL;
}
// --------------------------------------------------------------------
// Native activity interaction (called from main thread)
// --------------------------------------------------------------------
struct android_app* android_app_create(ANativeActivity* activity,
void* savedState, size_t savedStateSize) {
struct android_app* android_app = calloc(1, sizeof(struct android_app));
android_app->activity = activity;
pthread_mutex_init(&android_app->mutex, NULL);
pthread_cond_init(&android_app->cond, NULL);
if (savedState != NULL) {
android_app->savedState = malloc(savedStateSize);
android_app->savedStateSize = savedStateSize;
memcpy(android_app->savedState, savedState, savedStateSize);
}
int msgpipe[2];
if (pipe(msgpipe)) {
LOGE("could not create pipe: %s", strerror(errno));
return NULL;
}
android_app->msgread = msgpipe[0];
android_app->msgwrite = msgpipe[1];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
// Wait for thread to start.
pthread_mutex_lock(&android_app->mutex);
while (!android_app->running) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
return android_app;
}
void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
LOGE("Failure writing android_app cmd: %s", strerror(errno));
}
}
void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
pthread_mutex_lock(&android_app->mutex);
android_app->pendingInputQueue = inputQueue;
android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
while (android_app->inputQueue != android_app->pendingInputQueue) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
}
void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
pthread_mutex_lock(&android_app->mutex);
if (android_app->pendingWindow != NULL) {
android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
}
android_app->pendingWindow = window;
if (window != NULL) {
android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
}
while (android_app->window != android_app->pendingWindow) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
}
void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
pthread_mutex_lock(&android_app->mutex);
android_app_write_cmd(android_app, cmd);
while (android_app->activityState != cmd) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
}
void android_app_free(struct android_app* android_app) {
pthread_mutex_lock(&android_app->mutex);
android_app_write_cmd(android_app, APP_CMD_DESTROY);
while (!android_app->destroyed) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
close(android_app->msgread);
close(android_app->msgwrite);
pthread_cond_destroy(&android_app->cond);
pthread_mutex_destroy(&android_app->mutex);
free(android_app);
}
struct android_app* ToApp(ANativeActivity* activity) {
return (struct android_app*) activity->instance;
}
void onDestroy(ANativeActivity* activity) {
LOGV("Destroy: %p", activity);
android_app_free(ToApp(activity));
}
void onStart(ANativeActivity* activity) {
LOGV("Start: %p", activity);
android_app_set_activity_state(ToApp(activity), APP_CMD_START);
}
void onResume(ANativeActivity* activity) {
LOGV("Resume: %p", activity);
android_app_set_activity_state(ToApp(activity), APP_CMD_RESUME);
}
void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
LOGV("SaveInstanceState: %p", activity);
struct android_app* android_app = ToApp(activity);
void* savedState = NULL;
pthread_mutex_lock(&android_app->mutex);
android_app->stateSaved = 0;
android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
while (!android_app->stateSaved) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
if (android_app->savedState != NULL) {
savedState = android_app->savedState;
*outLen = android_app->savedStateSize;
android_app->savedState = NULL;
android_app->savedStateSize = 0;
}
pthread_mutex_unlock(&android_app->mutex);
return savedState;
}
void onPause(ANativeActivity* activity) {
LOGV("Pause: %p", activity);
android_app_set_activity_state(ToApp(activity), APP_CMD_PAUSE);
}
void onStop(ANativeActivity* activity) {
LOGV("Stop: %p", activity);
android_app_set_activity_state(ToApp(activity), APP_CMD_STOP);
}
void onConfigurationChanged(ANativeActivity* activity) {
LOGV("ConfigurationChanged: %p", activity);
android_app_write_cmd(ToApp(activity), APP_CMD_CONFIG_CHANGED);
}
void onContentRectChanged(ANativeActivity* activity, const ARect* r) {
LOGV("ContentRectChanged: l=%d,t=%d,r=%d,b=%d", r->left, r->top, r->right, r->bottom);
struct android_app* android_app = ToApp(activity);
pthread_mutex_lock(&android_app->mutex);
android_app->contentRect = *r;
pthread_mutex_unlock(&android_app->mutex);
android_app_write_cmd(ToApp(activity), APP_CMD_CONTENT_RECT_CHANGED);
}
void onLowMemory(ANativeActivity* activity) {
LOGV("LowMemory: %p", activity);
android_app_write_cmd(ToApp(activity), APP_CMD_LOW_MEMORY);
}
void onWindowFocusChanged(ANativeActivity* activity, int focused) {
LOGV("WindowFocusChanged: %p -- %d", activity, focused);
android_app_write_cmd(ToApp(activity), focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
}
void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
LOGV("NativeWindowCreated: %p -- %p", activity, window);
android_app_set_window(ToApp(activity), window);
}
void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
LOGV("NativeWindowDestroyed: %p -- %p", activity, window);
android_app_set_window(ToApp(activity), NULL);
}
void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) {
LOGV("NativeWindowRedrawNeeded: %p -- %p", activity, window);
android_app_write_cmd(ToApp(activity), APP_CMD_WINDOW_REDRAW_NEEDED);
}
void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) {
LOGV("NativeWindowResized: %p -- %p", activity, window);
android_app_write_cmd(ToApp(activity), APP_CMD_WINDOW_RESIZED);
}
void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
LOGV("InputQueueCreated: %p -- %p", activity, queue);
android_app_set_input(ToApp(activity), queue);
}
void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
LOGV("InputQueueDestroyed: %p -- %p", activity, queue);
android_app_set_input(ToApp(activity), NULL);
}
void ILOVEU_ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) {
LOGV("Creating: %p", activity);
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
activity->callbacks->onContentRectChanged = onContentRectChanged;
activity->callbacks->onDestroy = onDestroy;
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
activity->callbacks->onLowMemory = onLowMemory;
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
activity->callbacks->onNativeWindowResized = onNativeWindowResized;
activity->callbacks->onPause = onPause;
activity->callbacks->onResume = onResume;
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
activity->callbacks->onStart = onStart;
activity->callbacks->onStop = onStop;
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
activity->instance = android_app_create(activity, savedState, savedStateSize);
}

View file

@ -1,350 +0,0 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <android/configuration.h>
#include <android/looper.h>
#include <android/native_activity.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* The native activity interface provided by <android/native_activity.h>
* is based on a set of application-provided callbacks that will be called
* by the Activity's main thread when certain events occur.
*
* This means that each one of this callbacks _should_ _not_ block, or they
* risk having the system force-close the application. This programming
* model is direct, lightweight, but constraining.
*
* The 'android_native_app_glue' static library is used to provide a different
* execution model where the application can implement its own main event
* loop in a different thread instead. Here's how it works:
*
* 1/ The application must provide a function named "android_main()" that
* will be called when the activity is created, in a new thread that is
* distinct from the activity's main thread.
*
* 2/ android_main() receives a pointer to a valid "android_app" structure
* that contains references to other important objects, e.g. the
* ANativeActivity obejct instance the application is running in.
*
* 3/ the "android_app" object holds an ALooper instance that already
* listens to two important things:
*
* - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
* declarations below.
*
* - input events coming from the AInputQueue attached to the activity.
*
* Each of these correspond to an ALooper identifier returned by
* ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT,
* respectively.
*
* Your application can use the same ALooper to listen to additional
* file-descriptors. They can either be callback based, or with return
* identifiers starting with LOOPER_ID_USER.
*
* 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event,
* the returned data will point to an android_poll_source structure. You
* can call the process() function on it, and fill in android_app->onAppCmd
* and android_app->onInputEvent to be called for your own processing
* of the event.
*
* Alternatively, you can call the low-level functions to read and process
* the data directly... look at the process_cmd() and process_input()
* implementations in the glue to see how to do this.
*
* See the sample named "native-activity" that comes with the NDK with a
* full usage example. Also look at the JavaDoc of NativeActivity.
*/
struct android_app;
/**
* Data associated with an ALooper fd that will be returned as the "outData"
* when that source has data ready.
*/
struct android_poll_source {
// The identifier of this source. May be LOOPER_ID_MAIN or
// LOOPER_ID_INPUT.
int32_t id;
// The android_app this ident is associated with.
struct android_app* app;
// Function to call to perform the standard processing of data from
// this source.
void (*process)(struct android_app* app, struct android_poll_source* source);
};
/**
* This is the interface for the standard glue code of a threaded
* application. In this model, the application's code is running
* in its own thread separate from the main thread of the process.
* It is not required that this thread be associated with the Java
* VM, although it will need to be in order to make JNI calls any
* Java objects.
*/
struct android_app {
// The application can place a pointer to its own state object
// here if it likes.
void* userData;
// Fill this in with the function to process main app commands (APP_CMD_*)
void (*onAppCmd)(struct android_app* app, int32_t cmd);
// Fill this in with the function to process input events. At this point
// the event has already been pre-dispatched, and it will be finished upon
// return. Return 1 if you have handled the event, 0 for any default
// dispatching.
int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
// The ANativeActivity object instance that this app is running in.
ANativeActivity* activity;
// The current configuration the app is running in.
AConfiguration* config;
// This is the last instance's saved state, as provided at creation time.
// It is NULL if there was no state. You can use this as you need; the
// memory will remain around until you call android_app_exec_cmd() for
// APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
// These variables should only be changed when processing a APP_CMD_SAVE_STATE,
// at which point they will be initialized to NULL and you can malloc your
// state and place the information here. In that case the memory will be
// freed for you later.
void* savedState;
size_t savedStateSize;
// The ALooper associated with the app's thread.
ALooper* looper;
// When non-NULL, this is the input queue from which the app will
// receive user input events.
AInputQueue* inputQueue;
// When non-NULL, this is the window surface that the app can draw in.
ANativeWindow* window;
// Current content rectangle of the window; this is the area where the
// window's content should be placed to be seen by the user.
ARect contentRect;
// Current state of the app's activity. May be either APP_CMD_START,
// APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
int activityState;
// This is non-zero when the application's NativeActivity is being
// destroyed and waiting for the app thread to complete.
int destroyRequested;
// -------------------------------------------------
// Below are "private" implementation of the glue code.
pthread_mutex_t mutex;
pthread_cond_t cond;
int msgread;
int msgwrite;
pthread_t thread;
struct android_poll_source cmdPollSource;
struct android_poll_source inputPollSource;
int running;
int stateSaved;
int destroyed;
int redrawNeeded;
AInputQueue* pendingInputQueue;
ANativeWindow* pendingWindow;
ARect pendingContentRect;
};
enum {
/**
* Looper data ID of commands coming from the app's main thread, which
* is returned as an identifier from ALooper_pollOnce(). The data for this
* identifier is a pointer to an android_poll_source structure.
* These can be retrieved and processed with android_app_read_cmd()
* and android_app_exec_cmd().
*/
LOOPER_ID_MAIN = 1,
/**
* Looper data ID of events coming from the AInputQueue of the
* application's window, which is returned as an identifier from
* ALooper_pollOnce(). The data for this identifier is a pointer to an
* android_poll_source structure. These can be read via the inputQueue
* object of android_app.
*/
LOOPER_ID_INPUT = 2,
/**
* Start of user-defined ALooper identifiers.
*/
LOOPER_ID_USER = 3,
};
enum {
/**
* Command from main thread: the AInputQueue has changed. Upon processing
* this command, android_app->inputQueue will be updated to the new queue
* (or NULL).
*/
APP_CMD_INPUT_CHANGED,
/**
* Command from main thread: a new ANativeWindow is ready for use. Upon
* receiving this command, android_app->window will contain the new window
* surface.
*/
APP_CMD_INIT_WINDOW,
/**
* Command from main thread: the existing ANativeWindow needs to be
* terminated. Upon receiving this command, android_app->window still
* contains the existing window; after calling android_app_exec_cmd
* it will be set to NULL.
*/
APP_CMD_TERM_WINDOW,
/**
* Command from main thread: the current ANativeWindow has been resized.
* Please redraw with its new size.
*/
APP_CMD_WINDOW_RESIZED,
/**
* Command from main thread: the system needs that the current ANativeWindow
* be redrawn. You should redraw the window before handing this to
* android_app_exec_cmd() in order to avoid transient drawing glitches.
*/
APP_CMD_WINDOW_REDRAW_NEEDED,
/**
* Command from main thread: the content area of the window has changed,
* such as from the soft input window being shown or hidden. You can
* find the new content rect in android_app::contentRect.
*/
APP_CMD_CONTENT_RECT_CHANGED,
/**
* Command from main thread: the app's activity window has gained
* input focus.
*/
APP_CMD_GAINED_FOCUS,
/**
* Command from main thread: the app's activity window has lost
* input focus.
*/
APP_CMD_LOST_FOCUS,
/**
* Command from main thread: the current device configuration has changed.
*/
APP_CMD_CONFIG_CHANGED,
/**
* Command from main thread: the system is running low on memory.
* Try to reduce your memory use.
*/
APP_CMD_LOW_MEMORY,
/**
* Command from main thread: the app's activity has been started.
*/
APP_CMD_START,
/**
* Command from main thread: the app's activity has been resumed.
*/
APP_CMD_RESUME,
/**
* Command from main thread: the app should generate a new saved state
* for itself, to restore from later if needed. If you have saved state,
* allocate it with malloc and place it in android_app.savedState with
* the size in android_app.savedStateSize. The will be freed for you
* later.
*/
APP_CMD_SAVE_STATE,
/**
* Command from main thread: the app's activity has been paused.
*/
APP_CMD_PAUSE,
/**
* Command from main thread: the app's activity has been stopped.
*/
APP_CMD_STOP,
/**
* Command from main thread: the app's activity is being destroyed,
* and waiting for the app thread to clean up and exit before proceeding.
*/
APP_CMD_DESTROY,
};
/**
* Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
* app command message.
*/
int8_t android_app_read_cmd(struct android_app* android_app);
/**
* Call with the command returned by android_app_read_cmd() to do the
* initial pre-processing of the given command. You can perform your own
* actions for the command after calling this function.
*/
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
/**
* Call with the command returned by android_app_read_cmd() to do the
* final post-processing of the given command. You must have done your own
* actions for the command before calling this function.
*/
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
/**
* No-op function that used to be used to prevent the linker from stripping app
* glue code. No longer necessary, since __attribute__((visibility("default")))
* does this for us.
*/
__attribute__((
deprecated("Calls to app_dummy are no longer necessary. See "
"https://github.com/android-ndk/ndk/issues/381."))) void
app_dummy();
/**
* This is the function that application code must implement, representing
* the main entry to the app.
*/
extern void android_main(struct android_app* app);
#ifdef __cplusplus
}
#endif

View file

@ -1,115 +0,0 @@
#include "animations.h"
#include "timer.h"
using namespace tp;
using namespace glw;
bool tp::glw::gInTransition = false;
halnf AnimValue::interpolate() const {
if (!mTimeAnim) {
return mVal;
}
auto dt = gCurrentTime - mTimeStart;
if (dt > mTimeAnim) dt = mTimeAnim;
auto t = (halnf)dt / mTimeAnim;
t = (halnf)(0.511 + atan((t - 0.36) * 28) / 2.9);
t = clamp(t, 0.f, 1.f);
auto out = mValPrev + (mVal - mValPrev) * t;
return out;
}
AnimValue::AnimValue() {}
void AnimValue::setAnimTime(halni time) {
mTimeAnim = time;
}
AnimValue::AnimValue(halnf val) {
mVal = val;
mValPrev = mVal;
mTimeStart = gCurrentTime;
}
bool AnimValue::inTransition() const {
auto time_pased = gCurrentTime - mTimeStart >= mTimeAnim;
return !time_pased;
}
void AnimValue::set(halnf val) {
if (!inTransition()) {
mValPrev = mVal;
}
if (val == mVal) {
return;
}
mValPrev = get();
mVal = val;
if (!inTransition()) {
mTimeStart = (halni)gCurrentTime;
}
}
halnf AnimValue::getTarget() const {
return mVal;
}
void AnimValue::setNoTransition(halnf val) {
mValPrev = val;
mVal = val;
mTimeStart -= mTimeStart;
}
halnf AnimValue::get() const {
if (inTransition()) {
gInTransition = true;
}
return interpolate();
}
AnimValue::operator halnf() const {
return get();
}
rectf AnimRect::get() const {
return { x.get(), y.get() , z.get(), w.get() };
}
rectf AnimRect::getTarget() const {
return { x.getTarget(), y.getTarget() , z.getTarget(), w.getTarget() };
}
void AnimRect::setNoTransition(rectf rec) {
x.setNoTransition(rec.x);
y.setNoTransition(rec.y);
z.setNoTransition(rec.z);
w.setNoTransition(rec.w);
}
void AnimRect::setAnimTime(const halni time) {
x.setAnimTime(time);
y.setAnimTime(time);
z.setAnimTime(time);
w.setAnimTime(time);
}
void AnimRect::set(const rectf& in) {
x.set(in.x);
y.set(in.y);
z.set(in.z);
w.set(in.w);
}
rgba AnimColor::get() const {
auto col = mColor.get();
return rgba(col.x, col.y, col.z, col.w);
}
void AnimColor::set(const rgba& col) {
mColor.set(rectf(col.r, col.g, col.b, col.a));
}

View file

@ -1,378 +0,0 @@
#include "canvas.h"
#include "GraphicsLibApi.h"
#ifdef ENV_OS_ANDROID
const char* get_android_abs_path(const char* path, bool second = false);
#define NANOVG_GLES3_IMPLEMENTATION // Use GLES3 implementation.
#else
#define NANOVG_GL3_IMPLEMENTATION // Use GL3 implementation.
#endif
#include "nanovg.h"
#include "nanovg_gl.h"
#include "nanovg_gl_utils.h"
using namespace tp;
using namespace glw;
#define NVG ((NVGcontext*) mCtx)
static const char* getFontPath() {
#ifdef ENV_OS_ANDROID
return get_android_abs_path("rsc/fonts/CONSOLAB.TTF");
#else
return "./rsc/fonts/CONSOLAB.TTF";
#endif
}
Canvas::Canvas() {
// create context
mCtx =
#ifdef ENV_OS_ANDROID
nvgCreateGLES3
#else
nvgCreateGL3
#endif
(NVG_ANTIALIAS | NVG_STENCIL_STROKES
#ifdef ENV_BUILD_DEBUG
| NVG_DEBUG
#endif
);
mColorPrimary = rgba(0.5f, 0.5f, 0.5f, 0.9f);
mColorSecondary = rgba(0.2f, 0.2f, 0.2f, 0.9f);
nvgCreateFont(NVG, "basic", getFontPath());
}
Canvas::Val& Canvas::convert2pxls(Val& val) {
val = val * mDpmm * mUIScale;
return val;
}
Canvas::Val Canvas::as2pxls(Val val) {
return val * mDpmm * mUIScale;
}
Canvas::Rect& Canvas::convert2pxls(Rect& rec) {
convert2pxls(rec.x);
convert2pxls(rec.y);
convert2pxls(rec.z);
convert2pxls(rec.w);
return rec;
}
Canvas::Vec2& Canvas::convert2pxls(Vec2& vec) {
convert2pxls(vec.x);
convert2pxls(vec.y);
return vec;
}
void Canvas::beginDraw(Rect viewport, tp::halnf dpmm, tp::halnf uiscale) {
convert2pxls(viewport);
nvgBeginFrame(NVG, viewport.size.x, viewport.size.y, 1);
mVieport = { 0.f, 0.f, viewport.size.x, viewport.size.y };
glViewport((GLsizei)mVieport.x, (GLsizei)mVieport.y, (GLsizei)mVieport.size.x, (GLsizei)mVieport.size.y);
mDpmm = dpmm;
mUIScale = tp::clamp(uiscale, 0.03f, 100.f);
mClamping = mVieport;
}
void Canvas::resetViewport() {
glViewport((GLsizei)mVieport.x, (GLsizei)mVieport.y, (GLsizei)mVieport.size.x, (GLsizei)mVieport.size.y);
}
void Canvas::clear(Col color) {
glClearColor(color.r, color.g, color.b, color.a);
//glClearDepth(0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Canvas::endDraw() {
nvgEndFrame(NVG);
}
void Canvas::setClamping(Rect rec) {
mClamping = rec;
convert2pxls(rec);
nvgScissor(NVG, rec.x, rec.y, rec.z, rec.w);
}
void Canvas::setCol1(const Col& col) {
mColorPrimary = col;
}
void Canvas::setCol2(const Col& col) {
mColorSecondary = col;
}
void Canvas::rect(Rect rec, halnf rounding, halnf borders) {
convert2pxls(rec);
convert2pxls(rounding);
convert2pxls(borders);
if (borders) {
nvgBeginPath(NVG);
auto borders_rec = rec;
rec.pos += borders;
rec.size -= borders * 2;
if (rounding) {
nvgRoundedRect(NVG, borders_rec.x, borders_rec.y, borders_rec.z, borders_rec.w, rounding);
}
else {
nvgRect(NVG, borders_rec.x, borders_rec.y, borders_rec.z, borders_rec.w);
}
nvgFillColor(NVG, nvgRGBAf(mColorSecondary.r, mColorSecondary.g, mColorSecondary.b, mColorSecondary.a));
nvgFill(NVG);
}
nvgBeginPath(NVG);
if (rounding) {
nvgRoundedRect(NVG, rec.x, rec.y, rec.z, rec.w, rounding);
}
else {
nvgRect(NVG, rec.x, rec.y, rec.z, rec.w);
}
nvgFillColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
nvgFill(NVG);
}
void Canvas::line(Vec2 p1, Vec2 p2, halnf thikness) {
convert2pxls(p1);
convert2pxls(p2);
convert2pxls(thikness);
nvgBeginPath(NVG);
nvgMoveTo(NVG, p1.x, p1.y);
nvgLineTo(NVG, p2.x, p2.y);
nvgStrokeColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
nvgStrokeWidth(NVG, thikness);
nvgStroke(NVG);
}
void Canvas::trig(Vec2 p1, Vec2 p2, Vec2 p3) {
convert2pxls(p1);
convert2pxls(p2);
convert2pxls(p3);
nvgBeginPath(NVG);
nvgMoveTo(NVG, p1.x, p1.y);
nvgLineTo(NVG, p2.x, p2.y);
nvgLineTo(NVG, p3.x, p3.y);
nvgFillColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
nvgFill(NVG);
}
void Canvas::circle(Vec2 rec, halnf radius, halnf borders) {
convert2pxls(rec);
convert2pxls(radius);
convert2pxls(borders);
DBG_BREAK(1);
}
void Canvas::text(const char* start, const char* end, Rect rec, halnf size, Align align) {
convert2pxls(rec);
convert2pxls(size);
nvgFillColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
nvgFontSize(NVG, size);
nvgTextAlign(NVG, NVGalign(align));
auto y = (align & Align::MIDDLE) ? rec.y + rec.w / 2 : rec.y;
auto x = (align & Align::CENTER) ? rec.x + rec.z / 2 : rec.x;
nvgText(NVG, x, y, start, end);
}
void Canvas::text(const string text, Rect rec, halnf size, Align align) {
convert2pxls(rec);
convert2pxls(size);
nvgFillColor(NVG, nvgRGBAf(mColorPrimary.r, mColorPrimary.g, mColorPrimary.b, mColorPrimary.a));
nvgFontSize(NVG, size);
nvgTextAlign(NVG, NVGalign(align));
//nvgTextBounds(NVG, );
auto t_mid = rec.y + rec.w / 2;
auto t_top = rec.y;
auto res = bool(align & Align::MIDDLE);
auto y = res ? t_mid : t_top;
auto x_mid = rec.x + rec.z / 2;
auto x_left = rec.x;
res = bool(align & Align::CENTER);
auto x = res ? x_mid : x_left;
nvgText(NVG, x, y, text.cstr(), text.cstr() + text.size());
}
void Canvas::ImageHandle::createFromBuff(glw::fbuffer* buff, Canvas* drawer) {
this->~ImageHandle();
auto const size = buff->getSize();
#ifdef ENV_OS_ANDROID
mId = nvglCreateImageFromHandleGLES3((NVGcontext*)drawer->mCtx, buff->texId(), size.x, size.y, 0);
#else
mId = nvglCreateImageFromHandleGL3((NVGcontext*)drawer->mCtx, buff->texId(), (halni) size.x, (halni) size.y, 0);
#endif
}
void Canvas::ImageHandle::free(Canvas* drawer) {
if (mId && (NVGcontext*)drawer->mCtx) {
nvgDeleteImage((NVGcontext*)drawer->mCtx, mId);
}
}
Canvas::ImageHandle::~ImageHandle() {}
void Canvas::drawImage(Rect rec, ImageHandle* image, halnf angle, halnf alpha, halnf rounding) {
convert2pxls(rec);
convert2pxls(rounding);
auto imgPaint = nvgImagePattern(NVG, rec.x, rec.y, rec.z, rec.w, angle, image->mId, alpha);
nvgBeginPath(NVG);
nvgRoundedRect(NVG, rec.x, rec.y, rec.z, rec.w, rounding);
nvgFillPaint(NVG, imgPaint);
nvgFill(NVG);
}
void Canvas::drawColorwheel(Rect rec, const rgb& col) {
convert2pxls(rec);
float const x = rec.x;
float const y = rec.y;
float const w = rec.z;
float const h = rec.w;
hsv hsv = tp::hsv(col);
float const hue = hsv.h / (NVG_PI * 2);
int i;
float r0, r1, ax, ay, bx, by, cx, cy, aeps, r;
NVGpaint paint;
nvgSave(NVG);
cx = x + w * 0.5f;
cy = y + h * 0.5f;
r1 = (w < h ? w : h) * 0.5f - as2pxls(1.0f);
r0 = r1 - as2pxls(3.0f);
aeps = 0.5f / r1; // half a pixel arc length in radians (2pi cancels out).
for (i = 0; i < 6; i++) {
float a0 = (float)i / 6.0f * NVG_PI * 2.0f - aeps;
float a1 = (float)(i + 1.0f) / 6.0f * NVG_PI * 2.0f + aeps;
nvgBeginPath(NVG);
nvgArc(NVG, cx, cy, r0, a0, a1, NVG_CW);
nvgArc(NVG, cx, cy, r1, a1, a0, NVG_CCW);
nvgClosePath(NVG);
ax = cx + cosf(a0) * (r0 + r1) * 0.5f;
ay = cy + sinf(a0) * (r0 + r1) * 0.5f;
bx = cx + cosf(a1) * (r0 + r1) * 0.5f;
by = cy + sinf(a1) * (r0 + r1) * 0.5f;
paint = nvgLinearGradient(NVG, ax, ay, bx, by, nvgHSLA(a0 / (NVG_PI * 2), 1.0f, 0.55f, 255), nvgHSLA(a1 / (NVG_PI * 2), 1.0f, 0.55f, 255));
nvgFillPaint(NVG, paint);
nvgFill(NVG);
}
nvgBeginPath(NVG);
nvgCircle(NVG, cx, cy, r0 - 0.5f);
nvgCircle(NVG, cx, cy, r1 + 0.5f);
nvgStrokeColor(NVG, nvgRGBA(0, 0, 0, 64));
nvgStrokeWidth(NVG, 1.0f);
nvgStroke(NVG);
// Selector
nvgSave(NVG);
nvgTranslate(NVG, cx, cy);
nvgRotate(NVG, hue * NVG_PI * 2);
// Marker on
nvgStrokeWidth(NVG, 2.0f);
nvgBeginPath(NVG);
nvgRect(NVG, r0 - 1, -3, r1 - r0 + 2, 6);
nvgStrokeColor(NVG, nvgRGBA(255, 255, 255, 192));
nvgStroke(NVG);
paint = nvgBoxGradient(NVG, r0 - 3, -5, r1 - r0 + 6, 10, 2, 4, nvgRGBA(0, 0, 0, 128), nvgRGBA(0, 0, 0, 0));
nvgBeginPath(NVG);
nvgRect(NVG, r0 - 2 - 10, -4 - 10, r1 - r0 + 4 + 20, 8 + 20);
nvgRect(NVG, r0 - 2, -4, r1 - r0 + 4, 8);
nvgPathWinding(NVG, NVG_HOLE);
nvgFillPaint(NVG, paint);
nvgFill(NVG);
// Center triangle
r = r0 - 6;
ax = cosf(120.0f / 180.0f * NVG_PI) * r;
ay = sinf(120.0f / 180.0f * NVG_PI) * r;
bx = cosf(-120.0f / 180.0f * NVG_PI) * r;
by = sinf(-120.0f / 180.0f * NVG_PI) * r;
nvgBeginPath(NVG);
nvgMoveTo(NVG, r, 0);
nvgLineTo(NVG, ax, ay);
nvgLineTo(NVG, bx, by);
nvgClosePath(NVG);
paint = nvgLinearGradient(NVG, r, 0, ax, ay, nvgHSLA(hue, 1.0f, 0.5f, 255), nvgRGBA(255, 255, 255, 255));
nvgFillPaint(NVG, paint);
nvgFill(NVG);
paint = nvgLinearGradient(NVG, (r + ax) * 0.5f, (0 + ay) * 0.5f, bx, by, nvgRGBA(0, 0, 0, 0), nvgRGBA(0, 0, 0, 255));
nvgFillPaint(NVG, paint);
nvgFill(NVG);
nvgStrokeColor(NVG, nvgRGBA(0, 0, 0, 64));
nvgStroke(NVG);
// Select circle on triangle
auto inner = as2pxls(3);
//auto outter = as2pxls(5);
float yt = hsv.v * hsv.s;
float xt = hsv.v - 0.5f * yt;
ay = sinf(120.0f / 180.0f * NVG_PI) * r * (-1.0f + xt * 2.0f);
ax = cosf(120.0f / 180.0f * NVG_PI) * r * (1.0f - yt * 3.f);
nvgStrokeWidth(NVG, as2pxls(0.6f));
nvgBeginPath(NVG);
nvgCircle(NVG, ax, ay, inner);
nvgStrokeColor(NVG, nvgRGBA(255, 255, 255, 192));
nvgStroke(NVG);
//paint = nvgRadialGradient(NVG, ax, ay, 4, 9, nvgRGBA(0, 0, 0, 64), nvgRGBA(0, 0, 0, 0));
//nvgBeginPath(NVG);
//nvgRect(NVG, ax - outter, ay - outter, outter * 2, outter * 2);
//nvgCircle(NVG, ax, ay, outter);
//nvgPathWinding(NVG, NVG_HOLE);
//nvgFillPaint(NVG, paint);
//nvgFill(NVG);
nvgRestore(NVG);
nvgRestore(NVG);
}
Canvas::~Canvas() {
if (NVG) {
#ifdef ENV_OS_ANDROID
nvgDeleteGLES3(NVG);
#else
nvgDeleteGL3(NVG);
#endif
}
mCtx = NULL;
}

View file

@ -1,877 +0,0 @@
#include "debugui.h"
#include "typelist.h"
#include "stringt.h"
#include "stack.h"
#include "npple.h"
#include "rect.h"
#include "map.h"
#include "imgui.h"
#include "imgui_internal.h"
#include "implot.h"
// -------------- Platform Includes ---------------------- //
#if defined ENV_OS_WINDOWS
#include "backends/imgui_impl_opengl3.h"
#include "backends/imgui_impl_win32.h"
#include <Windows.h>
#elif defined ENV_OS_LINUX
#include "backends/imgui_impl_opengl3.h"
#include "backends/imgui_impl_glfw.h"
#elif defined ENV_OS_ANDROID
#include "backends/imgui_impl_opengl3.h"
#include "backends/imgui_impl_android.h"
#include <android/sensor.h>
#include <android/log.h>
#include <android/input.h>
#include <string.h>
#endif
#if defined ENV_OS_WINDOWS
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
extern HWND windowsPlatformContextGetNativeWindow(tp::glw::PlatformContext* ctx);
extern UINT windowsPlatformContextGetMessage(tp::glw::PlatformContext* ctx);
extern WPARAM windowsPlatformContextGetWparam(tp::glw::PlatformContext* ctx);
extern LRESULT windowsPlatformContextGetLparam(tp::glw::PlatformContext* ctx);
#elif defined ENV_OS_LINUX
#elif defined ENV_OS_ANDROID
extern AInputEvent* androidPlatformContextGetEvent(tp::glw::PlatformContext* ctx);
extern const char* get_android_abs_path(const char* path, bool second = false);
const char* AndroidGetImGuiIniPath() {
static char imgui_path[512];
auto tmp = get_android_abs_path("imgui.ini");
memcpy(imgui_path, tmp, strlen(tmp));
return imgui_path;
}
#endif
static const char* getFontPath() {
#ifdef ENV_OS_ANDROID
return get_android_abs_path("rsc/fonts/CONSOLAB.TTF");
#else
return "./rsc/fonts/CONSOLAB.TTF";
#endif
}
namespace tp {
namespace glw {
struct DebugUiInternalContext {
DebugUiDrawCallBack* cb = NULL;
void* cd = NULL;
ImGuiContext* ui_context = NULL;
ImGuiContext* vk_context = NULL;
bool initialized = false;
bool ui_first_drawn = false;
bool vk_first_drawn = false;
bool ui_context_want_active = true;
bool ui_context_want_active_vk = false;
bool vk_context_want_active = false;
tp::halnf dpmm;
tp::halnf font_size_mm;
tp::halnf ui_scale;
struct VKState {
struct InputButton {
char val = '?';
char shift_val = '?';
tp::halnf width = 1;
void (*action)(InputButton* button, VKState* state) = [](InputButton* button, VKState* state) {
if (state->mShifted) {
ImGui::GetIO().AddInputCharacter(button->shift_val);
}
else {
ImGui::GetIO().AddInputCharacter(button->val);
}
};
const char* display_name = NULL;
};
struct Config {
InputButton** rows = NULL;
tp::halni nrows = NULL;
tp::halnf* rows_widths = NULL;
tp::halnf* rows_sizes = NULL;
};
bool mShifted = false;
static const tp::uhalni mNConfigs = 2;
Config mConfigs[mNConfigs];
tp::uhalni mActiveConfigIdx = 0;
InputButton mCommonRow[7];
//bool mActive = false;
VKState() {
mCommonRow[0] = { '^', '^', 1 , [](InputButton* button, VKState* state) { state->mShifted = !state->mShifted; } };
mCommonRow[1] = { ' ', ' ', 1,
[](InputButton* button, VKState* state) {
state->mActiveConfigIdx++;
if (state->mActiveConfigIdx == state->mNConfigs) {
state->mActiveConfigIdx = 0;
}
},
"..."
};
mCommonRow[2] = { ' ', ' ', 2 };
mCommonRow[3] = { '<', '<', 2, [](InputButton* button, VKState* state) {
ImGui::GetIO().AddKeyEvent(ImGuiKey_Backspace, true);
ImGui::GetIO().AddKeyEvent(ImGuiKey_Backspace, false);
} };
mCommonRow[4] = { '.', '.', 1 };
mCommonRow[5] = { '@', '@', 1 };
mCommonRow[6] = { ' ', ' ', 2, [](InputButton* button, VKState* state) {
ImGui::GetIO().AddKeyEvent(ImGuiKey_Enter, true);
ImGui::GetIO().AddKeyEvent(ImGuiKey_Enter, false);
}, "Entrer" };
setupMainConfig(mConfigs[0]);
setupAdditionalConfig(mConfigs[1]);
}
void setupMainConfig(Config& config) {
static InputButton row1[] = {
{'1', '!'},
{'2', '@'},
{'3', '#'},
{'4', '$'},
{'5', '%'},
{'6', '^'},
{'7', '&'},
{'8', '*'},
{'9', '('},
{'0', ')'},
};
static InputButton row2[] = {
{'q', 'Q'},
{'w', 'W'},
{'e', 'E'},
{'r', 'R'},
{'t', 'T'},
{'y', 'Y'},
{'u', 'U'},
{'i', 'I'},
{'o', 'O'},
{'p', 'P'},
};
static InputButton row3[] = {
{'a', 'A'},
{'s', 'S'},
{'d', 'D'},
{'f', 'F'},
{'g', 'G'},
{'h', 'H'},
{'j', 'J'},
{'k', 'K'},
{'l', 'L'},
};
static InputButton row4[] = {
{'z', 'Z'},
{'x', 'X'},
{'c', 'C'},
{'v', 'V'},
{'b', 'B'},
{'n', 'N'},
{'m', 'M'},
};
static InputButton* rows[] = {
row1,
row2,
row3,
row4,
mCommonRow,
};
static tp::halnf rows_sizes[IM_ARRAYSIZE(rows)] = {
IM_ARRAYSIZE(row1),
IM_ARRAYSIZE(row2),
IM_ARRAYSIZE(row3),
IM_ARRAYSIZE(row4),
IM_ARRAYSIZE(mCommonRow),
};
static tp::halnf rows_widths[IM_ARRAYSIZE(rows)];
for (auto row = 0; row < IM_ARRAYSIZE(rows); row++) {
for (auto butt = 0; butt < rows_sizes[row]; butt++) {
rows_widths[row] += rows[row][butt].width;
}
}
config = {
rows,
IM_ARRAYSIZE(rows),
rows_widths,
rows_sizes,
};
}
void setupAdditionalConfig(Config& config) {
static InputButton row1[] = {
{'~', '~'},
{'`', '`'},
{'_', '_'},
{'|', '|'},
{'\\', '\\'},
{'/', '/'},
{'"', '"'},
{'\'', '\''},
};
static InputButton row2[] = {
{';', ';'},
{':', ':'},
{'?', '?'},
{',', ','},
{'[', '['},
{']', ']'},
{'{', '{'},
{'}', '}'},
{'(', '('},
{')', ')'},
};
static InputButton row3[] = {
{'-', '-'},
{'=', '='},
{'*', '*'},
{'+', '+'},
{'<', '<'},
{'>', '>'},
};
static InputButton row4[] = {
{' ', ' ', 1, [](InputButton* butt, VKState* state) {
ImGui::GetIO().AddKeyEvent(ImGuiKey_UpArrow, true);
ImGui::GetIO().AddKeyEvent(ImGuiKey_UpArrow, false);
}, "up" },
{' ', ' ', 1, [](InputButton* butt, VKState* state) {
ImGui::GetIO().AddKeyEvent(ImGuiKey_DownArrow, true);
ImGui::GetIO().AddKeyEvent(ImGuiKey_DownArrow, false);
}, "down"},
{' ', ' ', 1, [](InputButton* butt, VKState* state) {
ImGui::GetIO().AddKeyEvent(ImGuiKey_LeftArrow, true);
ImGui::GetIO().AddKeyEvent(ImGuiKey_LeftArrow, false);
}, "left"},
{' ', ' ', 1, [](InputButton* butt, VKState* state) {
ImGui::GetIO().AddKeyEvent(ImGuiKey_RightArrow, true);
ImGui::GetIO().AddKeyEvent(ImGuiKey_RightArrow, false);
}, "right"},
};
static InputButton* rows[] = {
row1,
row2,
row3,
row4,
mCommonRow,
};
static tp::halnf rows_sizes[IM_ARRAYSIZE(rows)] = {
IM_ARRAYSIZE(row1),
IM_ARRAYSIZE(row2),
IM_ARRAYSIZE(row3),
IM_ARRAYSIZE(row4),
IM_ARRAYSIZE(mCommonRow),
};
static tp::halnf rows_widths[IM_ARRAYSIZE(rows)];
for (auto row = 0; row < IM_ARRAYSIZE(rows); row++) {
for (auto butt = 0; butt < rows_sizes[row]; butt++) {
rows_widths[row] += rows[row][butt].width;
}
}
config = {
rows,
IM_ARRAYSIZE(rows),
rows_widths,
rows_sizes,
};
}
} mVKState;
DebugUiInternalContext(Window& window, DebugUiDrawCallBack* acb, void* acd) {
cb = acb;
cd = acd;
ui_context = ImGui::CreateContext();
ImGui::SetCurrentContext(ui_context);
ImGuiContextInit(window);
vk_context = ImGui::CreateContext();
ImGui::SetCurrentContext(vk_context);
ImGuiContextInit(window);
initialized = true;
}
void drawDebugUI(tp::halnf a_dpmm, tp::halnf a_font_size_mm, tp::halnf a_ui_scale) {
dpmm = a_dpmm;
font_size_mm = a_font_size_mm;
ui_scale = a_ui_scale;
if (!initialized) return;
ImGui::SetCurrentContext(ui_context);
ImGui::ApplyStyle(dpmm, font_size_mm, ui_scale);
ImGuiContextBeginFrame();
cb(cd);
ImGuiContextEndFrame();
ImGui::SetCurrentContext(NULL);
ui_first_drawn = true;
if (ui_context_want_active_vk || vk_context_want_active) {
ImGui::SetCurrentContext(vk_context);
ImGui::ApplyStyle(dpmm, font_size_mm, ui_scale);
ImGuiContextBeginFrame();
VirtualKeyboard(dpmm, font_size_mm, ui_scale);
ImGuiContextEndFrame();
ImGui::SetCurrentContext(NULL);
vk_first_drawn = true;
}
}
~DebugUiInternalContext() {
if (!initialized) return;
ImGui::SetCurrentContext(ui_context);
ImGuiContextDeinit();
ImGui::DestroyContext(ui_context);
ImGui::SetCurrentContext(vk_context);
ImGuiContextDeinit();
ImGui::DestroyContext(vk_context);
}
private:
void ImGuiContextInit(Window& window) {
#if defined ENV_OS_WINDOWS
ImGui_ImplOpenGL3_Init();
ImGui_ImplWin32_Init(window.platform_window());
window.mNativeEventListeners.put("imgui", {
nativeWindowEventListenerWrapBegin,
nativeWindowEventListenerWrap,
nativeWindowEventListenerWrapEnd,
this
});
#elif defined ENV_OS_LINUX
ImGui_ImplOpenGL3_Init();
ImGui_ImplGlfw_InitForOpenGL((GLFWwindow*)window.platform_window(), true);
#elif defined ENV_OS_ANDROID
ImGui_ImplOpenGL3_Init("#version 300 es");
ImGui_ImplAndroid_Init((ANativeWindow*)window.platform_window());
ImGui::GetIO().IniFilename = AndroidGetImGuiIniPath();
window.mNativeEventListeners.put("imgui", {
nativeWindowEventListenerWrapBegin,
nativeWindowEventListenerWrap,
nativeWindowEventListenerWrapEnd,
this
});
#endif
}
void ImGuiContextBeginFrame() {
#if defined ENV_OS_WINDOWS
ImGui_ImplWin32_NewFrame();
ImGui_ImplOpenGL3_NewFrame();
#elif defined ENV_OS_LINUX
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
#elif defined ENV_OS_ANDROID
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplAndroid_NewFrame();
#endif
ImGui::NewFrame();
}
void ImGuiContextEndFrame() {
ImGui::Render();
#if defined ENV_OS_WINDOWS
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
#elif defined ENV_OS_LINUX
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
#elif defined ENV_OS_ANDROID
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
#endif
}
void ImGuiContextDeinit() {
#if defined ENV_OS_WINDOWS
ImGui_ImplWin32_Shutdown();
#elif defined ENV_OS_LINUX
ImGui_ImplGlfw_Shutdown();
#elif defined ENV_OS_ANDROID
ImGui_ImplAndroid_Shutdown();
#endif
ImGui_ImplOpenGL3_Shutdown();
}
void nativeWindowEventListenerPlatform(tp::glw::PlatformContext* ctx) {
#if defined ENV_OS_WINDOWS
auto native_window = windowsPlatformContextGetNativeWindow(ctx);
auto message = windowsPlatformContextGetMessage(ctx);
auto w_param = windowsPlatformContextGetWparam(ctx);
auto l_param = windowsPlatformContextGetLparam(ctx);
// IMGUI : needs to be commented out
//if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr)
// ::SetCapture(hwnd);
ImGui_ImplWin32_WndProcHandler(native_window, message, w_param, l_param);
#elif defined ENV_OS_LINUX
#elif defined ENV_OS_ANDROID
auto aev = androidPlatformContextGetEvent(ctx);
int32_t event_type = AInputEvent_getType(aev);
ImGui_ImplAndroid_HandleInputEvent(aev);
auto& io = ImGui::GetIO();
if (event_type == AINPUT_EVENT_TYPE_MOTION); {
int32_t event_action = AMotionEvent_getAction(aev);
int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
event_action &= AMOTION_EVENT_ACTION_MASK;
if ((AMotionEvent_getToolType(aev, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
|| (AMotionEvent_getToolType(aev, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN)) {
if (event_action == AMOTION_EVENT_ACTION_DOWN) {
io.AddMousePosEvent(AMotionEvent_getX(aev, event_pointer_index), AMotionEvent_getY(aev, event_pointer_index));
}
else if (event_action == AMOTION_EVENT_ACTION_UP) {
io.AddMousePosEvent(AMotionEvent_getX(aev, event_pointer_index), AMotionEvent_getY(aev, event_pointer_index));
if (!ui_context_want_active_vk || vk_context_want_active) {
io.AddMousePosEvent(-1, -1);
}
}
}
}
#endif
}
void nativeWindowEventListenerBegin(tp::glw::PlatformContext* ctx) {
vk_context_want_active = vk_context->IO.WantCaptureMouse || vk_context->IO.WantSetMousePos;
ui_context_want_active_vk = ui_context->IO.WantTextInput;
ui_context_want_active = ui_context->IO.WantCaptureKeyboard || ui_context->IO.WantCaptureMouse || ui_context->IO.WantSetMousePos;
}
void nativeWindowEventListener(tp::glw::PlatformContext* ctx) {
// proc vk
if ((ui_context_want_active_vk || vk_context_want_active) && vk_first_drawn) {
ImGui::SetCurrentContext(vk_context);
nativeWindowEventListenerPlatform(ctx);
while (vk_context->InputEventsQueue.Size) {
ImGui::ApplyStyle(dpmm, font_size_mm, ui_scale);
ImGui::NewFrame();
VirtualKeyboard(dpmm, font_size_mm, ui_scale);
ImGui::Render();
vk_context_want_active |= vk_context->IO.WantCaptureMouse || vk_context->IO.WantSetMousePos;
}
vk_context_want_active |= vk_context->IO.WantCaptureMouse || vk_context->IO.WantSetMousePos;
ImGui::SetCurrentContext(NULL);
}
// proc ui
if (!vk_context_want_active && ui_first_drawn) {
ImGui::SetCurrentContext(ui_context);
nativeWindowEventListenerPlatform(ctx);
while (ui_context->InputEventsQueue.Size) {
ImGui::ApplyStyle(dpmm, font_size_mm, ui_scale);
ImGui::NewFrame();
cb(cd);
ImGui::Render();
ui_context_want_active_vk |= ui_context->IO.WantTextInput;
ui_context_want_active |= ui_context->IO.WantCaptureKeyboard || ui_context->IO.WantCaptureMouse || ui_context->IO.WantSetMousePos;
}
ImGui::SetCurrentContext(NULL);
}
}
void nativeWindowEventListenerEnd(tp::glw::PlatformContext* ctx) {}
static void nativeWindowEventListenerWrapBegin(tp::glw::PlatformContext* ctx, void* cd) { ((DebugUiInternalContext*)cd)->nativeWindowEventListenerBegin(ctx); }
static void nativeWindowEventListenerWrap(tp::glw::PlatformContext* ctx, void* cd) { ((DebugUiInternalContext*)cd)->nativeWindowEventListener(ctx); }
static void nativeWindowEventListenerWrapEnd(tp::glw::PlatformContext* ctx, void* cd) { ((DebugUiInternalContext*)cd)->nativeWindowEventListenerEnd(ctx); }
void VirtualKeyboard(tp::halnf dpmm, tp::halnf font_size_mm, tp::halnf ui_scale) {
auto& config = mVKState.mConfigs[mVKState.mActiveConfigIdx];
ImGuiID dockspace_id = ImGui::DockSpaceOverViewport(0, ImGuiDockNodeFlags_PassthruCentralNode);
ImGuiDockNode* node = ImGui::DockContextFindNodeByID(ImGui::GetCurrentContext(), dockspace_id);
if (!node->IsSplitNode()) {
node->MergedFlags |= ImGuiDockNodeFlags_HiddenTabBar;
ImGuiID dock_id = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Down, 0.33f, nullptr, &dockspace_id);
ImGui::DockBuilderDockWindow("VK", dock_id);
}
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0.f, 0.f });
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, { 50 * dpmm, 30 * dpmm });
ImGui::Begin("VK");
ImGui::PopStyleVar(3);
auto pos = ImGui::GetCursorPos();
auto width = ImGui::GetWindowWidth();
auto height = ImGui::GetWindowHeight() - pos.y;
//auto scale = dpmm * ui_scale;
auto padding = dpmm * 2 * ui_scale;
auto button_sizey = (tp::halnf)(height - (config.nrows + 1) * padding) / config.nrows;
tp::vec2f crs = { pos.x + padding, pos.y + padding };
for (auto row = 0; row < config.nrows; row++) {
tp::halnf butt_scalex = (width - (config.rows_sizes[row] + 1) * padding) / config.rows_widths[row];
crs.x = pos.x + padding;
for (auto butt = 0; butt < config.rows_sizes[row]; butt++) {
auto& button = config.rows[row][butt];
ImGui::SetCursorPos({ crs.x, crs.y });
char name[2] = { mVKState.mShifted ? button.shift_val : button.val, 0 };
ImGui::PushID(&button);
if (!ImGui::Button(button.display_name ? button.display_name: name, { butt_scalex * button.width, button_sizey })) {
crs.x += butt_scalex * button.width + padding;
ImGui::PopID();
continue;
}
ImGui::SetCurrentContext(ui_context);
button.action(&button, &mVKState);
ImGui::SetCurrentContext(vk_context);
ImGui::PopID();
}
crs.y += button_sizey + padding;
}
ImGui::End();
}
};
}
}
tp::glw::DebugUI::DebugUI(Window& window, DebugUiDrawCallBack* acb, void* acd) {
mDPMM = window.mDevice.mDPMM;
// map device size to font and ui size
{
auto device_max = 600.f;
auto device_min = 50.f;
auto device = tp::clamp(window.mDevice.Size.x / mDPMM, device_min, device_max);
auto device_factor = (device - device_min) / (device_max - device_min);
auto font_min = 2.f;
auto font_max = 3.5f;
mFontSizeMM = (font_max - font_min) * device_factor + font_min;
auto ui_max = 1.f;
auto ui_min = 0.45f;
mUIScale = (ui_max - ui_min) * device_factor + ui_min;
}
mCtx = new DebugUiInternalContext(window, acb, acd);
}
void tp::glw::DebugUI::drawDebugUI(tp::halnf dpmm) {
mDPMM = dpmm;
mCtx->drawDebugUI(mDPMM, mFontSizeMM, mUIScale);
}
tp::glw::DebugUI::~DebugUI() {
delete mCtx;
}
// ------------------------------------------------------ //
static const int sWindowFrameFlags = (ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoDecoration);
bool ImGui::SubMenuBegin(const char* desc, int level) {
if (level == 1) {
ImGui::Separator();
}
if (ImGui::TreeNode(desc)) {
GImGui->Style.IndentSpacing = 6;
return true;
}
return false;
}
void ImGui::SubMenuEnd(int level) {
ImGui::TreePop();
}
void ImGui::ToolTip(const char* desc) {
ImGui::SameLine();
ImGui::TextDisabled("*");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc);
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
}
ImGui::PopupData ImGui::HoverPopupBeginButton(const char* id, tp::vec2f butsize, tp::vec2f popupsize) {
ImVec2 curs = ImGui::GetCursorScreenPos();
tp::vec2f popup_pos = tp::vec2f(curs.x + butsize.x / 2.f - popupsize.x / 2.f, (curs.y + butsize.y + 7));
ImGui::Button(id, ImVec2(butsize.x, butsize.y)); ImGui::SameLine();
return HoverPopupBegin(id, popupsize, popup_pos);
}
ImGui::PopupData ImGui::HoverPopupBegin(const char* str_id, tp::vec2f size, tp::vec2f pos_p, ImGuiPopupFlags popup_flags) {
ImGui::PopupData out;
out.ishovered = ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
if (out.ishovered) {
ImVec2 pos;
if (pos_p == tp::vec2f(-1)) {
pos = GImGui->CurrentWindow->DC.CursorPos;
}
else {
pos.x = pos_p.x;
pos.y = pos_p.y;
}
ImGui::SetNextWindowPos(pos);
out.p1 = { pos.x, pos.y };
ImGui::OpenPopup(str_id);
out.p2 = out.p1;
out.p2.x += ImGui::GetWindowWidth();
}
if (BeginPopup(str_id, ImGuiWindowFlags_NoMove)) {
out.opened = true;
auto pos = GetWindowPos();
out.p1 = { pos.x, pos.y };
out.p2 = out.p1;
out.p2.x += ImGui::GetWindowWidth();
}
return out;
}
void ImGui::HoverPopupEnd(ImGui::PopupData& in) {
if (!in.opened) {
return;
}
in.ishovered |= IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_ChildWindows);
tp::vec2f mousepos = { ImGui::GetMousePos().x, ImGui::GetMousePos().y };
tp::halnf tollerance = 10;
tp::rectf tollerace_rect = tp::rectf(tp::vec2f(in.p1.x, in.p1.y - tollerance), tp::vec2f(in.p2.x - in.p1.x, tollerance * 2.f));
bool is_tollerance = tollerace_rect.inside(mousepos);
if (!(in.ishovered || is_tollerance)) {
CloseCurrentPopup();
}
EndPopup();
}
#define VAL(val) (val * dpmm / 3 * ui_scale)
#define VEC(x, y) ImVec2(x * dpmm / 3, y * dpmm / 3 * ui_scale)
void ImGui::ApplyStyle(tp::halnf dpmm, float font_size_mm, float ui_scale) {
ImGuiStyle* style = &ImGui::GetStyle();
auto& io = ImGui::GetIO();
bool first_init = io.Fonts->Fonts.Size == 0;
auto font_path = getFontPath();
// supports PDMM from 0.3 to 10
const float min_dpmm = 0.3f;
const float max_dpmm = 20.f;
dpmm = tp::clamp(dpmm, min_dpmm, max_dpmm);
// calc font
const float font_size_mm_max = 10;
const float font_size_pixels_min = 9;
float font_size_mm_min = font_size_pixels_min / dpmm;
const int font_quality_steps = 3;
font_size_mm = tp::clamp(font_size_mm, font_size_mm_min, font_size_mm_max);
float font_sizes[font_quality_steps];
for (auto i = 0; i < font_quality_steps; i++) {
auto mm = font_size_mm_min + (font_size_mm_max - font_size_mm_min) * tp::pow(((tp::halnf) (i + 1) / font_quality_steps), 3);
font_sizes[i] = dpmm * mm;
}
if (first_init) {
for (auto i = 0; i < font_quality_steps; i++) {
io.Fonts->AddFontFromFileTTF(font_path, font_sizes[i] * 1);
}
}
// select fonts
auto const pixels_required = dpmm * font_size_mm;
auto idx = -1;
for (auto i = 0; i < font_quality_steps; i++) {
idx = i;
if (pixels_required <= font_sizes[i]) {
break;
}
}
DBG_BREAK(idx == -1);
io.FontDefault = io.Fonts->Fonts[idx];
io.FontGlobalScale = font_size_mm / (font_size_mm_min + ((font_size_mm_max - font_size_mm_min) / font_quality_steps) * (idx + 1));
io.FontGlobalScale = pixels_required / font_sizes[idx];
auto rounding = VAL(5);
auto pudding = VEC(7, 7);
style->WindowPadding = pudding;
style->WindowRounding = rounding;
//style->WindowMinSize = VEC(11, 11);
style->ChildRounding = rounding;
style->PopupRounding = rounding;
style->FramePadding = pudding;
style->FrameRounding = rounding;
style->ItemSpacing = VEC(4, 11);
style->ItemInnerSpacing = VEC(9, 4);
style->CellPadding = pudding;
style->TouchExtraPadding = pudding;
style->IndentSpacing = VAL(25);
style->ColumnsMinSpacing = VAL(5);
style->ScrollbarSize = VAL(16);
style->ScrollbarRounding = rounding;
style->GrabMinSize = VAL(2);
style->GrabRounding = rounding;
style->LogSliderDeadzone = VAL(2);
style->TabRounding = rounding;
style->TabMinWidthForCloseButton = VAL(5);
style->DisplayWindowPadding = pudding;
style->DisplaySafeAreaPadding = pudding;
style->MouseCursorScale = VAL(5);
style->FrameBorderSize = VAL(0);
style->WindowBorderSize = VAL(1.5f);
style->ChildBorderSize = VAL(2);
style->WindowTitleAlign = VEC(0.5f, 0.6f);
style->WindowMenuButtonPosition = ImGuiDir_Right;
if (!first_init)
return;
ImVec4* colors = ImGui::GetStyle().Colors;
colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_ChildBg] = ImVec4(0.09f, 0.09f, 0.10f, 1.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.10f, 1.00f);
colors[ImGuiCol_Border] = ImVec4(0.06f, 0.06f, 0.06f, 1.00f);
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_FrameBg] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.43f, 0.43f, 0.53f, 1.00f);
colors[ImGuiCol_TitleBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.09f, 0.09f, 0.10f, 0.00f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.15f, 0.15f, 0.19f, 1.00f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.21f, 0.20f, 0.25f, 1.00f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.30f, 0.29f, 0.35f, 1.00f);
colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.48f, 0.50f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.53f, 0.57f, 0.64f, 1.00f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.69f, 0.74f, 0.83f, 1.00f);
colors[ImGuiCol_Button] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.43f, 0.43f, 0.53f, 1.00f);
colors[ImGuiCol_Header] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.33f, 0.33f, 0.40f, 1.00f);
colors[ImGuiCol_Separator] = ImVec4(0.37f, 0.37f, 0.40f, 1.00f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.33f, 0.35f, 0.38f, 1.00f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.37f, 0.39f, 0.42f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.16f, 0.17f, 0.19f, 1.00f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.33f, 0.35f, 0.38f, 1.00f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.28f, 0.34f, 0.42f, 1.00f);
colors[ImGuiCol_Tab] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
colors[ImGuiCol_TabHovered] = ImVec4(0.23f, 0.23f, 0.28f, 1.00f);
colors[ImGuiCol_TabActive] = ImVec4(0.23f, 0.23f, 0.28f, 1.00f);
colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.43f, 0.45f, 0.48f, 1.00f);
colors[ImGuiCol_DockingPreview] = ImVec4(0.81f, 0.81f, 0.81f, 0.18f);
colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.33f, 0.35f, 0.38f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(0.49f, 0.51f, 0.54f, 1.00f);
colors[ImGuiCol_TableHeaderBg] = ImVec4(0.13f, 0.13f, 0.20f, 1.00f);
colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f);
colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f);
colors[ImGuiCol_TableRowBg] = ImVec4(0.23f, 0.20f, 0.20f, 0.00f);
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.38f, 0.22f, 0.22f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.10f, 1.00f);
colors[ImGuiCol_DockingPreview] = ImVec4(0.64f, 0.75f, 0.83f, 0.18f);
colors[ImGuiCol_TabHovered] = ImVec4(0.39f, 0.39f, 0.47f, 1.00f);
colors[ImGuiCol_TabActive] = ImVec4(0.27f, 0.27f, 0.33f, 1.00f);
colors[ImGuiCol_TabUnfocused] = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.24f, 0.24f, 0.29f, 1.00f);
colors[ImGuiCol_Border] = ImVec4(0.65f, 0.65f, 0.65f, 0.70f);
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
}

View file

@ -1,116 +0,0 @@
#include "fbuffer.h"
#include "GraphicsLibApi.h"
void glerr(GLenum type);
#define AssertGL(x) { x; GLenum __gle = glGetError(); if (__gle != GL_NO_ERROR) glerr(__gle); }
namespace tp {
using namespace glw;
fbuffer::fbuffer(const vec2f& size) : mSize(size) {
mDrawBuffers[0] = {GL_COLOR_ATTACHMENT0};
// --------- texture ---------
AssertGL(glGenTextures(1, &mTextureId));
AssertGL(glBindTexture(GL_TEXTURE_2D, mTextureId));
// Give an empty image to OpenGL ( the last "0" )
AssertGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)size.x, (GLsizei)size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
// Poor filtering. Needed
AssertGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
AssertGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
// --------- depth ---------
AssertGL(glGenRenderbuffers(1, &mDepthBufferID));
AssertGL(glBindRenderbuffer(GL_RENDERBUFFER, mDepthBufferID));
AssertGL(glRenderbufferStorage(GL_RENDERBUFFER, GLW_CONTEXT_DEPTH_COMPONENT, (GLsizei)size.x, (GLsizei)size.y));
// ------------ framebuffer ------------
AssertGL(glGenFramebuffers(1, &mFrameBufferID));
AssertGL(glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID));
AssertGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthBufferID));
// Set "renderedTexture" as our colour attachement #0
AssertGL(glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextureId, 0));
// Set the list of draw buffers.
AssertGL(glDrawBuffers(1, mDrawBuffers)); // "1" is the size of DrawBuffers
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
fbuffer::fbuffer(const vec2f& size, tp::uint1 samples) : mSize(size) {
mDrawBuffers[0] = { GL_COLOR_ATTACHMENT0 };
// ------- texture ---------
AssertGL(glGenTextures(1, &mTextureId));
AssertGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextureId));
#ifdef ENV_OS_ANDROID
AssertGL(glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, (GLsizei)size.x, (GLsizei)size.y, GL_TRUE));
#else
AssertGL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, (GLsizei)size.x, (GLsizei)size.y, GL_TRUE));
#endif
// !?
//AssertGL(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
//AssertGL(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
// ------- depth -------
AssertGL(glGenRenderbuffers(1, &mDepthBufferID));
AssertGL(glBindRenderbuffer(GL_RENDERBUFFER, mDepthBufferID));
AssertGL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GLW_CONTEXT_DEPTH_COMPONENT, (GLsizei)size.x, (GLsizei)size.y));
// ------- fbuff -------
AssertGL(glGenFramebuffers(1, &mFrameBufferID));
AssertGL(glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID));
AssertGL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, mTextureId, 0));
AssertGL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthBufferID));
AssertGL(glDrawBuffers(1, mDrawBuffers));
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
tp::uint4 fbuffer::buffId() const {
return mFrameBufferID;
}
void fbuffer::beginDraw() {
AssertGL(glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID));
setViewport({ 0.f, 0.f, mSize.x, mSize.y });
}
void fbuffer::setViewport(const rectf& viewport) {
AssertGL(glViewport((GLsizei)viewport.x, (GLsizei)viewport.y, (GLsizei)viewport.z, (GLsizei)viewport.w));
}
void fbuffer::clear() {
AssertGL(glClearColor(mClearCol.r, mClearCol.g, mClearCol.b, mClearCol.a));
AssertGL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
}
void fbuffer::endDraw() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0, 0, 0, 0);
glUseProgram(0);
}
fbuffer::~fbuffer() {
glDeleteFramebuffers(1, &mFrameBufferID);
glDeleteTextures(1, &mTextureId);
glDeleteRenderbuffers(1, &mDepthBufferID);
}
uhalni glw::fbuffer::sizeAllocatedMem() const {
return uhalni(sizeof(GLenum) * 4 + mSize.sizeAllocatedMem() + (sizeof(mClearCol) + 1) * (alni) mSize.x * (alni) mSize.y);
}
uhalni glw::fbuffer::sizeUsedMem() const {
return sizeAllocatedMem();
}
uint4 glw::fbuffer::texId() const {
return mTextureId;
}
const vec2f& fbuffer::getSize() const { return mSize; }
};

View file

@ -1,282 +0,0 @@
#include "window.h"
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include <iostream>
#include <stdlib.h>
tp::glw::Window::Device tp::glw::Window::mDevice;
static void glfw_error_callback(int error, const char* description) {
std::cout << stderr << "Glfw Error" << error << " " << description << "\n";
}
void tp::glw::Window::init() {
tp::glw::Window::mDevice.Size;
tp::glw::Window::mDevice.FrameRate;
// Setup window
setenv("DISPLAY", ":0.0", 0); // does overwrite
glfwSetErrorCallback(glfw_error_callback);
RelAssert(glfwInit());
// GL 3.0 + GLSL 130
const char* glsl_version = "#version 130";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
GLFWmonitor* primary = glfwGetPrimaryMonitor();
auto mode = glfwGetVideoMode(primary);
tp::glw::Window::mDevice.Size = { mode->width, mode->height };
tp::glw::Window::mDevice.FrameRate = mode->refreshRate;
}
#define MAP_EV(SYSKEY, code) case SYSKEY: { self->mEvents.mKeysQueue.push(tp::KeyEvent{ code, state }); break; }
namespace tp {
namespace glw {
struct PlatformContext {
GLFWwindow* window;
tp::glw::Window* window_ctx = NULL;
PlatformContext(tp::glw::Window* a_window_ctx) {
window_ctx = a_window_ctx;
// Create window with graphics context
window = glfwCreateWindow(300, 300, " ", NULL, NULL);
RelAssert(window);
glfwMakeContextCurrent(window);
GLenum err = glewInit();
if (GLEW_OK != err)
{
std::cout << stderr << "Error:" << glewGetErrorString(err);
RelAssert(0);
}
glfwSwapInterval(1); // Enable vsync
glfwSetWindowUserPointer(window, window_ctx);
glfwSetKeyCallback(window, key_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetScrollCallback(window, scroll_callback);
}
void applyAppearance(tp::glw::Window::Appearence& appear, tp::glw::Window::Appearence& prev, tp::glw::Window* win_ctx) {
if (!(appear.mSize == prev.mSize)) {
glfwSetWindowSize(window, appear.mSize.x, appear.mSize.y);
prev.mSize = appear.mSize;
}
if (!(appear.mPos == prev.mPos)) {
//glfwSetWindowPos(window, appear.mPos.x, appear.mPos.y);
win_ctx->mEvents.mCursor -= appear.mPos - prev.mPos;
//win_ctx->mEvents.mCursorPrev -= appear.mPos - prev.mPos;
prev.mPos = appear.mPos;
}
if (!(appear.mSizeMax == prev.mSizeMax && appear.mSizeMin == prev.mSizeMin)) {
glfwSetWindowSizeLimits(window, appear.mSizeMin.x, appear.mSizeMin.y, appear.mSizeMax.x, appear.mSizeMax.y);
prev.mSizeMax = appear.mSizeMax;
prev.mSizeMin = appear.mSizeMin;
}
if (!(appear.mMaximized == prev.mMaximized)) {
DBG_BREAK(1);
}
if (!(appear.mMinimized == prev.mMinimized)) {
DBG_BREAK(1);
}
int width, height;
glfwGetWindowSize(window, &width, &height);
appear.mSize = { width, height };
prev.mSize = appear.mSize;
glfwGetWindowPos(window, &width, &height);
appear.mPos = { width, height };
prev.mPos = appear.mPos;
}
void beginDraw() {
//int display_w, display_h;
//glfwGetFramebufferSize(window, &display_w, &display_h);
//glViewport(0, 0, display_w, display_h);
//glClearColor(0, 0, 0, 0);
//glClear(GL_COLOR_BUFFER_BIT);
}
void endDraw() {
glfwSwapBuffers(window);
}
void pollEvents() {
glfwPollEvents();
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
window_ctx->mEvents.mCursorPrev = window_ctx->mEvents.mCursor;
window_ctx->mEvents.mCursor = { xpos, ypos };
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
auto self = (tp::glw::Window*) glfwGetWindowUserPointer(window);
if (action != GLFW_PRESS && action != GLFW_RELEASE) {
return;
}
auto state = (action == GLFW_RELEASE) ? tp::KeyEvent::EventState::RELEASED : tp::KeyEvent::EventState::PRESSED;
//* VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39)
if (key >= GLFW_KEY_0 && key <= GLFW_KEY_9) {
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode(key), state });
return;
}
//* VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A)
else if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z) {
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode(key), state });
return;
}
switch (key) {
MAP_EV(GLFW_KEY_LEFT_SHIFT, tp::Keycode::LEFT_SHIFT);
MAP_EV(GLFW_KEY_LEFT, tp::Keycode::LEFT);
MAP_EV(GLFW_KEY_RIGHT, tp::Keycode::RIGHT);
MAP_EV(GLFW_KEY_UP, tp::Keycode::UP);
MAP_EV(GLFW_KEY_DOWN, tp::Keycode::DOWN);
MAP_EV(GLFW_KEY_BACKSPACE, tp::Keycode::BACKSPACE);
MAP_EV(GLFW_KEY_LEFT_CONTROL, tp::Keycode::LEFT_CONTROL);
MAP_EV(GLFW_KEY_MENU, tp::Keycode::LEFT_ALT);
MAP_EV(GLFW_KEY_ENTER, tp::Keycode::ENTER);
MAP_EV(GLFW_KEY_SPACE, tp::Keycode::SPACE);
MAP_EV(GLFW_KEY_COMMA, tp::Keycode::COMMA);
MAP_EV(GLFW_KEY_PERIOD, tp::Keycode::PERIOD);
MAP_EV(GLFW_KEY_TAB, tp::Keycode::TAB);
MAP_EV(GLFW_KEY_EQUAL, tp::Keycode::EQUAL);
MAP_EV(GLFW_KEY_MINUS, tp::Keycode::MINUS);
MAP_EV(GLFW_KEY_3, tp::Keycode::TILDA);
MAP_EV(GLFW_KEY_4, tp::Keycode::BRA);
MAP_EV(GLFW_KEY_5, tp::Keycode::SLASH);
MAP_EV(GLFW_KEY_6, tp::Keycode::KET);
MAP_EV(GLFW_KEY_1, tp::Keycode::DOUBLE_DOT);
MAP_EV(GLFW_KEY_7, tp::Keycode::QUOTES);
MAP_EV(GLFW_KEY_2, tp::Keycode::INV_SLASH);
MAP_EV(GLFW_KEY_ESCAPE, tp::Keycode::ESCAPE);
}
}
static void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
auto self = (tp::glw::Window*)glfwGetWindowUserPointer(window);
if (action != GLFW_PRESS && action != GLFW_RELEASE) {
return;
}
auto state = (action == GLFW_RELEASE) ? tp::KeyEvent::EventState::RELEASED : tp::KeyEvent::EventState::PRESSED;
switch (button) {
case GLFW_MOUSE_BUTTON_RIGHT: {
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE2, state });
} break;
case GLFW_MOUSE_BUTTON_LEFT: {
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE1, state });
} break;
case GLFW_MOUSE_BUTTON_MIDDLE: {
self->mEvents.mKeysQueue.push(tp::KeyEvent{ tp::Keycode::MOUSE3, state });
} break;
}
}
static void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
}
~PlatformContext() {
glfwDestroyWindow(window);
}
};
};
};
void tp::glw::Window::deinit() {}
tp::glw::Window::Window() {
initialize();
mAppearence.mSize = tp::glw::Window::mDevice.Size / 1.5f;
mAppearence.mPos = (tp::glw::Window::mDevice.Size - mAppearence.mSize) / 2.f;
mAppearence.mSizeMax = tp::glw::Window::mDevice.Size;
applyAppearance();
}
tp::glw::Window::Window(const Appearence& aAppearence) {
mAppearence = aAppearence;
initialize();
}
void tp::glw::Window::initialize() {
mPlatformCtx = new PlatformContext(this);
applyAppearance();
}
void tp::glw::Window::applyAppearance() {
mPlatformCtx->applyAppearance(mAppearence, this->mCache.mAppearencePrev, this);
}
void tp::glw::Window::pollEvents() {
applyAppearance();
mPlatformCtx->pollEvents();
mEvents.mRedraw |= (mEvents.mCursorPrev - mEvents.mCursor) != 0;
mEvents.mRedraw |= mEvents.mKeysQueue.length;
}
void tp::glw::Window::platformCallback() {}
void tp::glw::Window::beginDraw() {
mPlatformCtx->beginDraw();
}
void tp::glw::Window::endDraw() {
mPlatformCtx->endDraw();
if (mEvents.mRedraw-- < 0) mEvents.mRedraw = 0;
}
void* tp::glw::Window::platform_window() const {
return mPlatformCtx->window;
}
tp::alni tp::glw::Window::sizeAllocatedMem() {
return 0;
}
tp::alni tp::glw::Window::sizeUsedMem() {
return 0;
}
tp::glw::Window::~Window() {
delete mPlatformCtx;
}

View file

@ -1,170 +0,0 @@
#include "stringt.h"
#include "array.h"
#include "array.h"
#include "filesystem.h"
#include "shader.h"
#include "new.h"
#include "GraphicsLibApi.h"
#include <cstdio>
namespace tp {
using namespace glw;
//string shader_path = "../rsc/shaders/";
shader::shader() {
programm = 0;
VertexShaderID = 0;
FragmentShaderID = 0;
GeometryShaderID = 0;
}
void shader::vert_bind_source(const char* vert_src) {
VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
compile_shader(vert_src, VertexShaderID);
}
void shader::frag_bind_source(const char* frag_src) {
FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
compile_shader(frag_src, FragmentShaderID);
}
void shader::geom_bind_source(const char* geom_src) {
GeometryShaderID = glCreateShader(GL_GEOMETRY_SHADER);
compile_shader(geom_src, GeometryShaderID);
}
void shader::compile() {
GLint Result = GL_FALSE;
int InfoLogLength;
programm = glCreateProgram();
glAttachShader(programm, VertexShaderID);
if (GeometryShaderID) glAttachShader(programm, GeometryShaderID);
glAttachShader(programm, FragmentShaderID);
glLinkProgram(programm);
// Check the program
glGetProgramiv(programm, GL_LINK_STATUS, &Result);
glGetProgramiv(programm, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
Array<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(programm, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDetachShader(programm, VertexShaderID);
glDetachShader(programm, FragmentShaderID);
if (GeometryShaderID) glDetachShader(programm, GeometryShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
if (GeometryShaderID) glDeleteShader(GeometryShaderID);
}
bool shader::compile_shader(const char* ShaderCode, uint4 ShaderID) {
GLint Result = GL_FALSE;
int InfoLogLength;
char const* SourcePointer = ShaderCode;
glShaderSource(ShaderID, 1, &SourcePointer, NULL);
glCompileShader(ShaderID);
// Check Shader
glGetShaderiv(ShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(ShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
Array<char> VertexShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(ShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
return Result;
}
void shader::load(const char* pvert, const char* pgeom, const char* pfrag, bool paths) {
// Create the shaders
VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
if (pgeom) GeometryShaderID = glCreateShader(GL_GEOMETRY_SHADER);
else GeometryShaderID = 0;
GLint Result = GL_FALSE;
int InfoLogLength = 0;
if (paths) {
string vert = sfmt("%c.vert", pvert);
string geom = pgeom ? sfmt("%c.geom", pgeom) : " ";
string frag = sfmt("%c.frag", pfrag);
tp::string content;
printf("Compiling shader : %s\n", vert.cstr());
if (content.loadFile(vert)) {
compile_shader(content.cstr(), VertexShaderID);
}
if (GeometryShaderID) {
printf("Compiling shader : %s\n", geom.cstr());
if (content.loadFile(geom)) {
compile_shader(content.cstr(), GeometryShaderID);
}
}
printf("Compiling shader : %s\n", frag.cstr());
if (content.loadFile(frag)) {
compile_shader(content.cstr(), FragmentShaderID);
}
}
else {
compile_shader(pvert, VertexShaderID);
if (GeometryShaderID) {
compile_shader(pgeom, GeometryShaderID);
}
compile_shader(pfrag, FragmentShaderID);
}
compile();
}
shader::shader(const char* vert, const char* geom, const char* frag, bool paths) {
load(vert, geom, frag, paths);
}
void shader::bind() {
glUseProgram(programm);
}
GLuint glw::shader::getu(const char* uid) {
return glGetUniformLocation(programm, uid);
}
void shader::unbind() {
glUseProgram(0);
}
shader::~shader() {
glDeleteProgram(programm);
}
alni glw::shader::sizeAllocatedMem() {
return sizeof(GLuint) * 4;
}
alni glw::shader::sizeUsedMem() {
return sizeof(GLuint) * 4;
}
};

View file

@ -1,164 +0,0 @@
#pragma once
#include "simplegui.h"
using namespace tp;
using namespace glw;
void WindowSimpleInputs::update(const glw::Window& window, halnf uiscale) {
mScaleVal = (window.mDevice.mDPMM * uiscale);
mWindowSizeMM = window.mAppearence.mSize / mScaleVal;
mCrs = window.mEvents.mCursor / mScaleVal;
mCrsPrev = window.mEvents.mCursorPrev / mScaleVal;
mCrsmDelta = mCrs - mCrsPrev;
if (mMouse == Mouse::PRESSED) {
mMouse = Mouse::HOLD;
}
else if (mMouse == Mouse::RELEASED) {
mMouse = Mouse::NONE;
}
mMove = Move::NONE;
for (auto event : window.mEvents.mKeysQueue) {
bool press = event.data().event_state == KeyEvent::EventState::PRESSED;
if (press) {
switch (event.data().code) {
case Keycode::UP: mMove = Move::UP; break;
case Keycode::DOWN: mMove = Move::DOWN; break;
case Keycode::LEFT: mMove = Move::LEFT; break;
case Keycode::RIGHT: mMove = Move::RIGHT; break;
}
}
if (event.data().code == Keycode::MOUSE1) {
if (press) {
mMouse = Mouse::PRESSED;
}
else {
mMouse = Mouse::RELEASED;
}
}
}
}
bool WindowSimpleInputs::Activated() { return mMouse == Mouse::PRESSED; }
bool WindowSimpleInputs::Anticipating() { return mMouse == Mouse::HOLD; }
bool WindowSimpleInputs::Selected() { return mMouse == Mouse::RELEASED; }
bool WindowSimpleInputs::MoveLeft() { return mMove == Move::LEFT; }
bool WindowSimpleInputs::MoveRight() { return mMove == Move::RIGHT; }
bool WindowSimpleInputs::MoveUp() { return mMove == Move::UP; }
bool WindowSimpleInputs::MoveDown() { return mMove == Move::DOWN; }
bool WindowSimpleInputs::Drag() { return mCrsmDelta != 0; }
void ButtonWidget::draw(glw::Canvas& canvas) {
canvas.setCol1(mCol);
canvas.rect(mAnimRec.get(), 1.f);
}
void ButtonWidget::proc(glw::WindowSimpleInputs& inputs) {
auto rec = mAnimRec.get();
mPressed = false;
mAnimRec.setAnimTime(100);
if (rec.inside(inputs.mCrs)) {
if (inputs.Anticipating()) {
auto new_rec = mRect;
new_rec.scale_from_center(0.3f, true);
mAnimRec.setNoTransition(new_rec);
}
else {
mAnimRec.set(mRect);
}
if (inputs.Selected()) {
mPressed = true;
}
}
else {
auto new_rec = mRect;
new_rec.scale_from_center(0.3f, true);
mAnimRec.set(new_rec);
}
}
void CheckBoxWidget::draw(glw::Canvas& canvas) {
canvas.setCol1(mAnimCol.get());
canvas.rect(mAnimRec.get(), 1.f);
}
void CheckBoxWidget::proc(glw::WindowSimpleInputs& inputs) {
auto rec = mAnimRec.get();
mAnimRec.setAnimTime(100);
if (rec.inside(inputs.mCrs)) {
if (inputs.Anticipating()) {
auto new_rec = mRect;
new_rec.scale_from_center(0.3f, true);
mAnimRec.setNoTransition(new_rec);
}
else {
mAnimRec.set(mRect);
}
if (inputs.Selected()) {
mValue = !mValue;
}
}
else {
auto new_rec = mRect;
new_rec.scale_from_center(0.3f, true);
mAnimRec.set(new_rec);
}
if (mValue) {
mAnimCol.set(mColActive);
}
else {
mAnimCol.set(mCol);
}
}
void WindowsHeaderWidget::updRecs() {
auto padding = 0.7f;
auto butt_size = header_rec.w - padding * 2.f;
grab_rec = { header_rec.pos, { header_rec.z - header_rec.w * 4, header_rec.w } };
mPinButton.mRect = { { grab_rec.pos.x + grab_rec.size.x + padding, grab_rec.y + padding }, butt_size };
mMinButton.mRect = { { mPinButton.mRect.pos.x + mPinButton.mRect.size.x + padding * 2, mPinButton.mRect.y }, butt_size };
mMaxButton.mRect = { { mMinButton.mRect.pos.x + mMinButton.mRect.size.x + padding * 2, mPinButton.mRect.y }, butt_size };
mExitButton.mRect = { { mMaxButton.mRect.pos.x + mMaxButton.mRect.size.x + padding * 2, mPinButton.mRect.y }, butt_size };
mPinButton.mCol = { 0.3f, 0.3f, 0.3f, 0.9f};
mMinButton.mCol = { 0.3f, 0.3f, 0.8f, 0.9f };
mMaxButton.mCol = { 0.3f, 0.8f, 0.3f, 0.9f };
mExitButton.mCol = { 0.8f, 0.3f, 0.3f, 0.9f };
}
void WindowsHeaderWidget::draw(glw::Canvas& canvas) {
updRecs();
canvas.setCol1(col);
canvas.rect(header_rec, 1.f);
canvas.setCol1(1.f);
canvas.text("MemLeaks", grab_rec, 4.f);
mExitButton.draw(canvas);
mMaxButton.draw(canvas);
mMinButton.draw(canvas);
mPinButton.draw(canvas);
}
void WindowsHeaderWidget::proc(glw::Window& window, glw::WindowSimpleInputs& inputs) {
get_time();
mExitButton.proc(inputs);
mMaxButton.proc(inputs);
mMinButton.proc(inputs);
mPinButton.proc(inputs);
window.mAppearence.mMinMaxBox = mMaxButton.mRect * inputs.mScaleVal;
window.mAppearence.mCaptionsAddArea = { grab_rec * inputs.mScaleVal };
window.mAppearence.mMinimized = mMinButton.mPressed;
window.mEvents.mClose = mExitButton.mPressed;
window.mAppearence.mTopZ = mPinButton.mValue;
}

View file

@ -1,216 +0,0 @@
#include "texture.h"
#include "map.h"
#include "stringt.h"
#include "shader.h"
#include "GraphicsLibApi.h"
const char* texture_vertex =
#ifdef ENV_OS_ANDROID
"#version 300 es\n"
"precision mediump float;\n"
#else
"#version 330 core\n"
#endif
"layout(location = 0) in vec3 vPos;\n"
"out vec2 UV;\n"
"void main() {\n"
" gl_Position = vec4(vPos, 1);\n"
" UV = (vPos.xy + vec2(1, 1)) / 2.0;\n"
"}\n";
const char* texture_fragment =
#ifdef ENV_OS_ANDROID
"#version 300 es\n"
"precision mediump float;\n"
#else
"#version 330 core\n"
#endif
"in vec2 UV;\n"
"out vec4 color;\n"
"uniform sampler2D renderedTexture;\n"
"uniform float time;\n"
"void main() {\n"
" vec4 texColor = texture(renderedTexture, UV);\n"
" if (texColor.a < 0.2)\n"
" discard;\n"
" color = texColor;\n"
"}\n";
namespace tp {
using namespace glw;
GLuint texture::getid() { return id; }
texture::texture() {
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
texture::~texture() { glDeleteTextures(1, &id); }
alni texture::sizeAllocatedMem() {
return sizeof(GLuint);
}
alni texture::sizeUsedMem() {
return sizeof(GLuint);
}
void texture::update(const Array2D<rgba>& buff) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)buff.size().x, (GLsizei)buff.size().y, 0, GL_RGBA, GL_FLOAT, buff.buff());
}
void texture::draw(const GLuint& out) {
draw_texture(out, id);
}
struct texture_drawer_data {
HashMap<GLuint, string> textures;
GLuint quad_VertexArrayID;
GLuint quad_vertexbuffer;
GLuint texID;
glw::shader shader;
const GLfloat g_quad_vertex_buffer_data[18] = {
-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
};
texture_drawer_data() : shader(texture_vertex, NULL, texture_fragment, false) {
// The fullscreen quad's FBO
glGenVertexArrays(1, &quad_VertexArrayID);
glBindVertexArray(quad_VertexArrayID);
glGenBuffers(1, &quad_vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data),
g_quad_vertex_buffer_data, GL_STATIC_DRAW);
texID = shader.getu("renderedTexture");
}
~texture_drawer_data() {
glDeleteBuffers(1, &quad_vertexbuffer);
glDeleteVertexArrays(1, &quad_VertexArrayID);
for (auto tex : textures) {
glDeleteTextures(1, &tex->val);
}
}
};
texture_drawer_data* texdd = NULL;
void texture::init() {
if (!texdd) texdd = new texture_drawer_data();
}
void texture::deinit() {
if (texdd) delete texdd;
texdd = NULL;
}
void texture::draw_texture(uint4 out, uint4 in) {
assert(in);
// Render to the screen
glBindFramebuffer(GL_FRAMEBUFFER, out);
// Use our shader
texdd->shader.bind();
// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, in);
// Set our "renderedTexture" sampler to use Texture Unit 0
glUniform1i(texdd->texID, 0);
// glUniformMatrix4fv(texdd->rect_mat, 1, GL_FALSE, &tmat[0][0]);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, texdd->quad_vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
// Draw the triangles. 2*3 indices starting at 0 -> 2 triangles
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
texdd->shader.unbind();
}
GLuint load_texture(string name) {
GLuint tex_2d = 0;
RelAssert(0 && "incomplete compilation - no SOIL support added");
if (0) {
//auto document = lunasvg::Document::loadFromFile("tiger.svg");
//auto bitmap = document->renderToBitmap();
}
else {
/*
tex_2d = SOIL_load_OGL_texture(
name.cstr(), SOIL_LOAD_RGBA, SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB |
SOIL_FLAG_COMPRESS_TO_DXT);
if (0 == tex_2d) {
printf("SOIL loading error: '%s'\n", SOIL_last_result());
}
*/
}
return tex_2d;
}
GLuint texture::get_tex(const char* TexId) {
GLuint out = 0;
alni idx = texdd->textures.presents(TexId);
if (idx != -1) {
out = texdd->textures.get(TexId);
}
else {
out = load_texture(TexId);
texdd->textures.put(TexId, out);
}
return out;
}
void texture::drawCurcle(vec2f pos, double radius, rgba col) {
#ifndef ENV_OS_ANDROID
static alni precision = 40;
glColor4f(col.r, col.g, col.b, col.a);
double twicePi = 2.0 * 3.142;
glBegin(GL_TRIANGLE_FAN); // BEGIN CIRCLE
glVertex2f(pos.x, pos.y); // center of circle
for (alni i = 0; i <= precision; i++) {
glVertex2f((GLfloat)(pos.x + (radius * cos(i * twicePi / precision))),
(GLfloat)(pos.y + (radius * sin(i * twicePi / precision))));
}
glEnd(); // END
#endif
}
};

View file

@ -1,107 +0,0 @@
#include "SimpleGui.h"
#include "debugui.h"
#include "texture.h"
#include "timer.h"
#include "imgui.h"
struct CollorWheelWidget {
tp::rgba col = { 0.3f, 0.3f, 0.3f, 0.9f };
tp::rectf rec = { 10, 30, 40, 40 };
void draw(tp::glw::Canvas& canvas) {
canvas.setCol1(col);
canvas.rect(rec, 3.f);
canvas.drawColorwheel(rec, col.rgbs);
}
};
struct Test {
tp::glw::Window window;
tp::glw::DebugUI ui;
tp::glw::Canvas canvas;
tp::glw::WindowsHeaderWidget header;
tp::glw::WindowSimpleInputs inputs;
tp::halnf mHeaderHeight = 6.5f;
CollorWheelWidget colorwheel;
tp::halnf uiscale = 1.f;
tp::Timer time;
tp::halni frames = 0;
tp::halni fps = 0;
Test() : window(), ui(window, debuguiCallBack, this), time(1000) {
tp::glw::texture::init();
canvas.setCol1({ 0.5f, 0.5f, 0.5f, 0.5f });
window.mAppearence.mHiden = false;
}
void proc() {
window.pollEvents();
inputs.update(window, uiscale);
header.header_rec = { (inputs.mWindowSizeMM.x - 60.f) / 2.f, 3.f, 60.f, mHeaderHeight };
header.proc(window, inputs);
}
void draw() {
// window frame
window.beginDraw(); {
// canvas draw
canvas.beginDraw({ { 0, 0 }, inputs.mWindowSizeMM }, window.mDevice.mDPMM, uiscale); {
canvas.clear();
header.draw(canvas);
colorwheel.draw(canvas);
} canvas.endDraw();
// debug draw
ui.drawDebugUI(window.mDevice.mDPMM);
} window.endDraw();
}
void run() {
while (!window.mEvents.mClose) {
proc();
if (window.mEvents.mRedraw || tp::glw::gInTransition) {
draw();
}
if (time.isTimeout()) {
fps = frames;
frames = 0;
time.reset();
}
frames++;
}
}
void debugui() {
static char buff[100];
ImGui::DragFloat("UI SCale", &uiscale, 0.02);
ImGui::Text("Fps: %i", fps);
ImGui::InputText("Fps: %i", buff, 100);
}
static void debuguiCallBack(void* self) {
((Test*)self)->debugui();
}
~Test() {
tp::glw::texture::deinit();
}
};
CROSSPLATFORM_MAIN
int main() {
tp::ModuleManifest* ModuleDependencies[] = { &tp::gModuleGlw, NULL };
tp::ModuleManifest TestModule("Test", NULL, NULL, ModuleDependencies);
if (!TestModule.initialize()) {
return 1;
}
{
Test test;
test.run();
}
TestModule.deinitialize();
}

20
.project Normal file
View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Modules</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.core.cBuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.cmake.core.cmakeNature</nature>
</natures>
</projectDescription>

View file

@ -3,20 +3,18 @@ cmake_minimum_required(VERSION 3.2)
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)
project(Tokenizer) project(Language)
### ---------------------- Static Library --------------------- ### ### ---------------------- Static Library --------------------- ###
file(GLOB SOURCES "./private/*.cpp") file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
file(GLOB HEADERS "./public/*.hpp") file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS}) add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/) target_include_directories(${PROJECT_NAME} PUBLIC public/)
target_link_libraries(${PROJECT_NAME} PUBLIC Strings) target_link_libraries(${PROJECT_NAME} PUBLIC Strings)
### -------------------------- Tests -------------------------- ### ### -------------------------- Tests -------------------------- ###
enable_testing() enable_testing()
file(GLOB TEST_SOURCES "./tests/*.cpp") file(GLOB TEST_SOURCES "./tests/*.cpp")
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES}) add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils) target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} UnitTest++)
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests) add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib)

View file

@ -0,0 +1,36 @@
#include "Grammar.hpp"
using namespace tp;
ContextFreeGrammar::Arg::Arg(const String& id, bool terminal, bool epsilon) {
mId = id;
mIsTerminal = terminal;
mIsEpsilon = epsilon;
}
const String& ContextFreeGrammar::Arg::getId() const { return mId; }
bool ContextFreeGrammar::Arg::operator==(const Arg& in) const {
return (mId == in.mId) && (mIsEpsilon == in.mIsEpsilon) && (mIsTerminal == in.mIsTerminal);
}
ContextFreeGrammar::Rule::Rule(const String& id, const InitialierList<Arg>& args) {
mId = id;
mArgs = args;
}
bool ContextFreeGrammar::Rule::operator==(const Rule& in) const { return (mId == in.mId) && (mArgs == in.mArgs); }
bool ContextFreeGrammar::Rule::isProductive() const {
for (auto arg : mArgs) {
if (arg->getId() == mId) return false;
}
return true;
}
void ContextFreeGrammar::addRule(const Rule& rule) { mRules.append(rule); }
void ContextFreeGrammar::addRule(const String& id, const InitialierList<Arg>& args) { addRule(Rule(id, args)); }
void ContextFreeGrammar::setStart(const String& startRule) { mStartTerminal = startRule; }

View file

@ -0,0 +1,8 @@
#include "LanguageCommon.hpp"
#include "Strings.hpp"
using namespace tp;
static ModuleManifest* sModuleDependencies[] = { &gModuleStrings, nullptr };
ModuleManifest tp::gModuleLanguage = ModuleManifest("Language", nullptr, nullptr, sModuleDependencies);

View file

@ -0,0 +1,249 @@
#pragma once
#include "Utils.hpp"
#include "List.hpp"
#include "Map.hpp"
#include "Tree.hpp"
namespace tp {
// Non-Deterministic Finite-State Automata
template <typename tAlphabetType, typename tStateType>
class FiniteStateAutomation {
public:
struct State;
public:
class Transition {
friend FiniteStateAutomation;
public:
enum Type { ANY, EPSILON, SYMBOL };
public:
Transition(Type type, State* state, tAlphabetType symbol = tAlphabetType()) {
mState = state;
mType = type;
mSymbol = symbol;
}
[[nodiscard]] bool isTransition(const tAlphabetType& symbol) const {
return (mType == ANY || mType == EPSILON) || (mSymbol == symbol);
}
[[nodiscard]] bool doesConsumes(const tAlphabetType& symbol) const {
return (mType == ANY || (mType == SYMBOL && mSymbol == symbol));
}
[[nodiscard]] bool isEpsilon() const { return mType == EPSILON; }
const State* getState() const { return mState; }
const tAlphabetType& getSymbol() const { return mSymbol; }
private:
State* mState = nullptr;
Type mType;
tAlphabetType mSymbol;
};
class State {
friend FiniteStateAutomation;
public:
State() = default;
public:
void setValue(const tStateType& stateValue) { mStateVal = stateValue; }
void setAcceptance(bool isAccepting) { mIsAccepting = isAccepting; }
[[nodiscard]] bool isAccepting() const { return mIsAccepting; }
const tStateType& getStateVal() const { return mStateVal; }
[[nodiscard]] const Buffer<Transition>* getTransitions() const { return &mTransitions; }
private:
Buffer<Transition> mTransitions{};
tStateType mStateVal = tStateType();
bool mIsAccepting = false;
};
private:
List<State> mStates;
State* mStartState = nullptr;
Range<ualni> mAlphabetRange = { ENV_UALNI_MAX, ENV_UALNI_MIN };
public:
FiniteStateAutomation() = default;
State* addState(const tStateType& state, bool accepting) {
auto node = mStates.newNode();
node->data.mIsAccepting = accepting;
node->data.mStateVal = state;
mStates.pushBack(node);
return &node->data;
}
void addTransition(State* from, State* to, const tAlphabetType& symbol) {
from->mTransitions.append(Transition(Transition::SYMBOL, to, symbol));
if (mAlphabetRange.mBegin < ualni(symbol)) mAlphabetRange.mBegin = ualni(symbol);
if (mAlphabetRange.mEnd > ualni(symbol)) mAlphabetRange.mEnd = ualni(symbol);
}
void addEpsilonTransition(State* from, State* to) { from->mTransitions.append(Transition(Transition::SYMBOL, to)); }
void addAnyTransition(State* from, State* to) { from->mTransitions.append(Transition(Transition::ANY, to)); }
void setStartState(State* start) { mStartState = start; }
[[nodiscard]] State* getStartState() const { return mStartState; }
[[nodiscard]] bool isValid() const {
if (!mStartState) {
return false;
}
return true;
}
[[nodiscard]] ualni numStates() const { return mStates.length(); }
[[nodiscard]] const List<State>* getStates() const { return &mStates; }
[[nodiscard]] Range<ualni> getAlphabetRange() const { return mAlphabetRange; }
private:
typedef AvlTree<AvlNumericKey<State*>, bool> StatesSet;
// Expands initial set with states that are reachable from initial set with no input consumption (E-transitions)
static void expandSet(StatesSet& set) {
List<State*> workingSet;
set.forEach([&](AvlNumericKey<State*>& key, bool) { workingSet.pushBack(key.val); });
while (workingSet.length()) {
auto first = workingSet.first()->data;
set.insert(first, {});
for (auto transition : first->mTransitions) {
if (!transition->isEpsilon()) continue;
if (set.find(transition->mState)) continue;
workingSet.pushBack(transition->mState);
}
workingSet.popFront();
}
}
// States that are reachable from initial set with symbol transition
static void findMoveSet(StatesSet& from, StatesSet& moveSet, tAlphabetType symbol) {
from.forEach([&](AvlNumericKey<State*>& key, bool) {
for (auto transition : key.val->mTransitions) {
if (transition->isEpsilon()) continue;
if (!transition->isTransition(symbol)) continue;
if (moveSet.find(transition->mState)) continue;
moveSet.insert(transition->mState, {});
}
});
}
public:
bool makeDeterministic() {
if (!isValid()) return false;
struct GroupKey {
const StatesSet* group;
static ualni hash(GroupKey key) { return 0; }
bool operator==(const GroupKey& key) const { return false; }
};
struct GroupInfo {
StatesSet* group = nullptr;
AvlTree<AvlNumericKey<StatesSet*>, tAlphabetType> transitions;
State* newState = nullptr;
bool accepting = false;
tStateType stateVal = tStateType();
};
Buffer<StatesSet> groups = { {} };
Map<GroupKey, GroupInfo, DefaultAllocator, GroupKey::hash> groupInfos;
groups.first().insert(getStartState(), false);
expandSet(groups.first());
groupInfos.put({ &groups.first() }, { &groups.first() });
// 1) find new states
List<StatesSet*> workingSet;
workingSet.pushBack(&groups.first());
while (workingSet.length()) {
StatesSet* group = workingSet.first()->data;
GroupInfo* info = &groupInfos.get({ group });
for (auto symbol : getAlphabetRange()) {
// calculate new possible state
StatesSet potentialGroup;
findMoveSet(*group, potentialGroup, tAlphabetType(symbol));
expandSet(potentialGroup);
if (!potentialGroup.size()) continue;
// find existing or create group
StatesSet* targetGroup = nullptr;
auto iter = groupInfos.presents({ &potentialGroup });
if (iter) {
targetGroup = groupInfos.getSlotVal(iter).group;
} else {
targetGroup = &groups.append(potentialGroup);
groupInfos.put({ targetGroup }, { targetGroup });
workingSet.pushBack(targetGroup);
}
// assert transition is added
info->transitions.insert(targetGroup, tAlphabetType(symbol));
}
workingSet.popFront();
}
// 2) find new states termination values
for (auto group : groupInfos) {
GroupInfo* info = &group->val;
ualni accepting = 0;
info->group->forEach([&](AvlNumericKey<State*>& key, bool) {
if (key.val->mIsAccepting) {
accepting++;
info->accepting = true;
info->stateVal = key.val->mStateVal;
}
});
if (!accepting) {
info->accepting = false;
info->stateVal = info->group->head()->key.val->mStateVal;
}
}
// 3) transfer
mStates.removeAll();
// create states
for (auto group : groupInfos) {
group->val.newState = addState(group->val.stateVal, group->val.accepting);
}
// create transitions
for (auto group : groupInfos) {
auto functor = [&](AvlNumericKey<StatesSet*> targetGroupKey, tAlphabetType symbol) {
GroupInfo* targetGroup = &groupInfos.get({ (StatesSet*) targetGroupKey.val });
addTransition(group->val.newState, targetGroup->newState, symbol);
};
group->val.transitions.forEach(functor);
}
return true;
}
};
}

View file

@ -0,0 +1,137 @@
#pragma once
#include "Strings.hpp"
#include "Automata.hpp"
#include "Buffer2D.hpp"
namespace tp {
template <typename tAlphabetType, typename tStateType>
class ContextFreeAutomata {
struct Action {
enum Type { SHIFT, REDUCE, TRAP } type = TRAP;
ualni num = 0; // state to shift (shift action) or pop count (reduce action)
};
public:
struct StackItem {
ualni state = 0;
tAlphabetType symbol;
Buffer<StackItem*> leafs;
};
struct AcceptResult {
bool accepted = false;
ualni advancedIdx = 0;
const StackItem* ast = nullptr;
};
public:
ContextFreeAutomata() = default;
AcceptResult accept(const tAlphabetType* stream, ualni size) {
mCurrentState = mStartState;
mStack.append(&mItems.append({ mCurrentState, {}, {} }));
ualni advancedIdx = 0;
while (advancedIdx < size) {
const tAlphabetType& symbol = *(stream + advancedIdx);
if (!(symbol >= mRange.mBegin && symbol < mRange.mEnd)) {
return { false, advancedIdx, nullptr };
}
const Action& action = mTable.get({ ualni(symbol - mRange.mBegin), mCurrentState });
if (action.type == Action::TRAP) {
return { false, advancedIdx, nullptr };
}
if (action.type == Action::SHIFT) {
mStack.last()->symbol = symbol;
mStack.append(&mItems.append({ mCurrentState, {}, {} }));
mCurrentState = action.num;
}
if (mTable.get({ 0, mCurrentState }).type == Action::REDUCE) {
StackItem* newItem = &mItems.append(StackItem{});
for (auto iter : Range<ualni>(action.num)) {
newItem->leafs.append(mStack.last());
mCurrentState = mStack.last()->state;
mStack.pop();
}
if (!mStack.size()) {
if (advancedIdx == size) {
return { true, advancedIdx, newItem };
} else {
return { false, advancedIdx, {} };
}
}
mStack.append(&mItems.append({ mCurrentState, {}, {} }));
}
advancedIdx++;
}
return { false, advancedIdx, nullptr };
}
public:
typedef FiniteStateAutomation<tAlphabetType, tStateType> Automata;
typedef Automata::State AutomataState;
void construct(const Automata& automata) {
mRange = automata.getAlphabetRange();
const ualni numStates = automata.numStates();
const ualni numSymbols = mRange.idxDiff();
mTable.reserve({ numSymbols, numStates });
mTable.assign(Action{ Action::TRAP, 0 });
Map<const AutomataState*, ualni> states;
ualni stateIndex = 0;
for (auto state : *automata.getStates()) {
states.put(&state.data(), { stateIndex });
stateIndex++;
}
stateIndex = 0;
for (auto state : *automata.getStates()) {
if (&state.data() == automata.getStartState()) {
mStartState = stateIndex;
}
if (state->isAccepting()) {
ASSERT(state->getTransitions()->size() == 0)
for (auto symbolIndex : Range<ualni>(numSymbols)) {
mTable.set({ stateIndex, symbolIndex }, { Action::REDUCE, state->getStateVal().numArgs() });
}
} else {
for (auto transition : *state->getTransitions()) {
ualni symbolIndex = ualni(transition->getSymbol()) - mRange.mBegin;
ualni targetStateIndex = states.get(transition->getState());
mTable.set({ stateIndex, symbolIndex }, { Action::SHIFT, targetStateIndex });
}
}
stateIndex++;
}
}
private:
Buffer2D<Action> mTable;
Buffer<StackItem> mItems;
Buffer<StackItem*> mStack;
ualni mStartState = 0;
ualni mCurrentState = 0;
Range<ualni> mRange;
};
}

View file

@ -0,0 +1,181 @@
#pragma once
#include "Automata.hpp"
#include "Grammar.hpp"
namespace tp {
class ContextFreeCompiler {
public:
struct SymbolVal {
SymbolVal() = default;
SymbolVal(ualni aId, ualni aStart, ualni aLen) {
id = aId;
start = aStart;
len = aLen;
};
SymbolVal(ualni val) { id = val; }
operator ualni() const { return id; }
bool operator==(const SymbolVal& in) const { return in.id == id; }
SymbolVal& operator=(const SymbolVal& in) = default;
ualni id = 0;
ualni start = 0;
ualni len = 0;
};
struct Item {
const ContextFreeGrammar::Rule* mRule = nullptr;
ualni mAdvanceIdx = 0;
ualni numArgs() const { return 0; }
};
struct Symbol {
String mId;
bool mIsTerminal = false;
};
private:
struct NonTerminal {
Buffer<ContextFreeGrammar::Rule*> rules;
Map<String, NonTerminal*> references;
Map<String, NonTerminal*> referencing;
public:
[[nodiscard]] bool isProductive() const {
for (auto rule : rules) {
if (rule->isProductive()) return true;
}
return false;
}
[[nodiscard]] bool isLooped(Map<String, ualni>& processed, const String& id) const {
for (auto ref : referencing) {
if (processed.presents(ref->key)) return true;
}
processed.put(id, {});
for (auto ref : referencing) {
if (ref->val->isLooped(processed, ref->key)) return true;
}
return false;
}
};
public:
bool compile(const ContextFreeGrammar& grammar, FiniteStateAutomation<SymbolVal, Item>& automata) {
if (!init(grammar)) return false;
return true;
}
[[nodiscard]] const Buffer<Symbol>* getSymbols() const { return &mSymbols; }
[[nodiscard]] SymbolVal getSymbolId(const String& name) const { return mSymbolLookup.get(name); }
private:
bool init(const ContextFreeGrammar& grammar) {
if (!grammar.getRules()->size()) {
return false;
}
for (auto rule : *grammar.getRules()) {
if (!rule->getArgs()->size()) {
return false;
}
}
findNonTerminals(grammar);
for (auto nonTerminal : mNonTerminals) {
for (auto rule : nonTerminal->val.rules) {
for (auto arg : *rule->getArgs()) {
if (arg->isTerminal() || arg->isEpsilon()) continue;
if (!mNonTerminals.presents(arg->getId())) {
printf("Referenced non-terminal '%s' is not defined\n", arg->getId().read());
return false;
}
}
}
}
findAllReferences(grammar);
for (auto nonTerminal : mNonTerminals) {
if (!nonTerminal->val.references.size() && nonTerminal->key != grammar.getStartTerminal()) {
printf("Non-terminal '%s' is defined but not used\n", nonTerminal->key.read());
return false;
}
}
for (auto nonTerminal : mNonTerminals) {
if (!nonTerminal->val.isProductive()) {
printf("Non-terminal '%s' is not productive\n", nonTerminal->val.rules.first()->getId().read());
return false;
}
}
Map<String, ualni> processed;
if (mNonTerminals.get(grammar.getStartTerminal()).isLooped(processed, grammar.getStartTerminal())) {
printf("Note that grammar is looped.\n");
return false;
}
initSymbols(grammar);
return true;
}
void findNonTerminals(const ContextFreeGrammar& grammar) {
for (auto rule : *grammar.getRules()) {
if (!mNonTerminals.presents(rule->getId())) {
mNonTerminals.put(rule->getId(), {});
}
auto nonTerminal = &mNonTerminals.get(rule->getId());
nonTerminal->rules.append(&rule.data());
}
}
void findAllReferences(const ContextFreeGrammar& grammar) {
for (auto nonTerminal : mNonTerminals) {
for (auto rule : nonTerminal->val.rules) {
for (auto arg : *rule->getArgs()) {
if (arg->isTerminal() || arg->isEpsilon()) continue;
NonTerminal* reference = &mNonTerminals.get(arg->getId());
nonTerminal->val.referencing.put(arg->getId(), reference);
reference->references.put(nonTerminal->key, &nonTerminal->val);
}
}
}
}
void initSymbols(const ContextFreeGrammar& grammar) {
for (auto nonTerminal : mNonTerminals) {
mSymbols.append({ nonTerminal->key, false });
mSymbolLookup.put(nonTerminal->key, SymbolVal(mSymbols.size() - 1));
for (auto rule : nonTerminal->val.rules) {
for (auto arg : *rule->getArgs()) {
if (arg->isEpsilon() || arg->isTerminal()) continue;
if (mTerminals.presents(arg->getId())) continue;
mTerminals.put(arg->getId(), {});
mSymbols.append({ nonTerminal->key, true });
mSymbolLookup.put(nonTerminal->key, SymbolVal(mSymbols.size() - 1));
}
}
}
}
private:
Map<String, NonTerminal> mNonTerminals;
Map<String, bool> mTerminals;
Buffer<Symbol> mSymbols;
Map<String, SymbolVal> mSymbolLookup;
};
}

View file

@ -0,0 +1,224 @@
#pragma once
#include "Buffer.hpp"
#include "LanguageCommon.hpp"
#include "Map.hpp"
#include "Strings.hpp"
namespace tp {
class ContextFreeGrammar {
public:
struct Arg {
friend class Rule;
public:
Arg() = default;
explicit Arg(const String& id, bool terminal = true, bool epsilon = false);
public:
bool operator==(const Arg& in) const;
[[nodiscard]] const String& getId() const;
[[nodiscard]] bool isTerminal() const { return mIsTerminal; }
[[nodiscard]] bool isEpsilon() const { return mIsEpsilon; }
private:
String mId;
bool mIsTerminal = false;
bool mIsEpsilon = false;
};
class Rule {
public:
Rule() = default;
Rule(const String& id, const InitialierList<Arg>& args);
public:
bool operator==(const Rule& in) const;
[[nodiscard]] bool isProductive() const;
[[nodiscard]] const String& getId() const { return mId; }
[[nodiscard]] const Buffer<Arg>* getArgs() const { return &mArgs; }
private:
String mId;
Buffer<Arg> mArgs;
};
public:
ContextFreeGrammar() = default;
public:
void addRule(const Rule& rule);
void addRule(const String& id, const InitialierList<Arg>& args);
void setStart(const String& startRule);
[[nodiscard]] const Buffer<Rule>* getRules() const { return &mRules; }
[[nodiscard]] const String& getStartTerminal() const { return mStartTerminal; }
public:
Buffer<Rule> mRules;
String mStartTerminal;
bool mIsLooped = false;
};
template <typename tAlphabetType, typename tTokType>
class RegularGrammar {
public:
struct Node {
enum Type {
NONE,
ANY,
OR,
IF,
CLASS,
COMPOUND,
REPEAT,
VAL,
} mType = NONE;
explicit Node(Type type) :
mType(type) {}
virtual ~Node() = default;
};
class ValueNode : public Node {
public:
explicit ValueNode(tAlphabetType val) :
mVal(val),
Node(Node::VAL) {}
~ValueNode() override = default;
public:
tAlphabetType mVal;
};
class CompoundNode : public Node {
public:
CompoundNode() :
Node(Node::COMPOUND) {}
CompoundNode(const InitialierList<const Node*>& nodes) :
Node(Node::COMPOUND) {
mSequence = nodes;
}
~CompoundNode() override {
for (auto iter : mSequence) {
delete iter.data();
}
mSequence.clear();
}
public:
Buffer<const Node*> mSequence;
};
class AlternationNode : public Node {
public:
AlternationNode() :
Node(Node::OR) {}
AlternationNode(const Node* a, const Node* b) :
Node(Node::OR) {
mFirst = a;
mSecond = b;
}
~AlternationNode() override {
delete mFirst;
delete mSecond;
}
public:
const Node* mFirst = nullptr;
const Node* mSecond = nullptr;
};
class IfNode : public Node {
public:
IfNode() :
Node(Node::IF) {}
explicit IfNode(const Node* a) :
Node(Node::IF) {
mNode = a;
}
~IfNode() override { delete mNode; }
public:
const Node* mNode = nullptr;
};
class AnyNode : public Node {
public:
AnyNode() :
Node(Node::ANY) {}
~AnyNode() override = default;
};
class RepetitionNode : public Node {
public:
RepetitionNode() :
Node(Node::REPEAT) {}
explicit RepetitionNode(const Node* rep, bool plus = false) :
Node(Node::REPEAT) {
mNode = rep;
mPlus = plus;
}
~RepetitionNode() override { delete mNode; }
public:
Node* mNode = nullptr;
bool mPlus = false;
};
class ClassNode : public Node {
public:
ClassNode() :
Node(Node::CLASS) {}
explicit ClassNode(const Buffer<Range<tAlphabetType>>& ranges, bool exclude = false) :
Node(Node::CLASS) {
mExclude = exclude;
mRanges = ranges;
}
~ClassNode() override { mRanges.removeAll(); }
public:
Buffer<Range<tAlphabetType>> mRanges;
bool mExclude = false;
};
public:
RegularGrammar() = default;
~RegularGrammar() {
for (auto rule : mRules) {
delete rule->t1;
}
}
void addRule(const Node* node, tTokType id) { mRules.append({ node, id }); }
public:
const Node* seq(const InitialierList<const Node*>& nodes) { return new CompoundNode(nodes); }
const Node* val(tAlphabetType in) { return new ValueNode(in); }
const Node* alt(const Node* a, const Node* b) { return new AlternationNode(a, b); }
const Node* may(const Node* a) { return new IfNode(a); }
const Node* any() { return new AnyNode(); }
const Node* rep(const Node* rep, bool plus = false) { return new RepetitionNode(rep, plus); }
const Node* ranges(const Buffer<Range<tAlphabetType>>& ranges, bool exclude = false) {
return new ClassNode(ranges, exclude);
}
public:
Buffer<Pair<const Node*, tTokType>> mRules;
};
}

View file

@ -0,0 +1,7 @@
#pragma once
#include "Module.hpp"
namespace tp {
extern ModuleManifest gModuleLanguage;
}

View file

@ -0,0 +1,107 @@
#pragma once
#include "RegularCompiler.hpp"
#include "RegularAutomata.hpp"
#include "ContextFreeCompiler.hpp"
#include "ContextFreeAutomata.hpp"
namespace tp {
template <typename tAlphabetType, typename tTokenType, tTokenType tInTransition, ualni MinSymbol, ualni MaxSymbol>
class Parser {
typedef RegularGrammar<tAlphabetType, tTokenType> RegularGrammar;
typedef RegularCompiler<tAlphabetType, tTokenType, tInTransition, MinSymbol, MaxSymbol> RegularCompiler;
typedef FiniteStateAutomation<tAlphabetType, tTokenType> RegularGraph;
typedef RegularAutomata<tAlphabetType, tTokenType> RegularAutomata;
// ContextFreeGrammar;
// ContextFreeCompiler;
typedef FiniteStateAutomation<ContextFreeCompiler::SymbolVal, ContextFreeCompiler::Item> ContextFreeGraph;
typedef ContextFreeAutomata<ContextFreeCompiler::SymbolVal, ContextFreeCompiler::Item> ContextFreeAutomata;
public:
struct ParseResult {
bool accepted = false;
const ContextFreeAutomata::StackItem* ast = nullptr;
};
public:
Parser() = default;
public:
bool compileTables(
const ContextFreeGrammar& cfGrammar,
const RegularGrammar& reGrammar,
const Map<String, tTokenType>& contextFreeToRegular
) {
// Compile Regular Grammar
{
RegularGraph graph;
RegularCompiler compiler;
compiler.compile(graph, reGrammar);
graph.makeDeterministic();
mRegularAutomata.construct(graph);
}
// compile context free grammar
{
ContextFreeGraph graph;
ContextFreeCompiler compiler;
compiler.compile(cfGrammar, graph);
graph.makeDeterministic();
mContextFreeAutomata.construct(graph);
// make glue
for (auto symbol : *compiler.getSymbols()) {
auto symbolId = compiler.getSymbolId(symbol->mId);
if (symbol->mIsTerminal) {
auto iter = contextFreeToRegular.presents(symbol->mId);
if (!iter) return false;
mGrammarGlue.put(contextFreeToRegular.getSlotVal(iter), symbolId);
} else {
mAstNames.put(symbolId, symbol->mId);
}
}
}
return true;
}
ParseResult parse(const tAlphabetType* sentence, ualni sentenceLength) {
// get tokens stream
Buffer<ContextFreeCompiler::SymbolVal> tokens;
const tAlphabetType* sentenceIter = sentence;
ualni lengthIter = sentenceLength;
while (lengthIter) {
auto result = mRegularAutomata.accept(sentenceIter, lengthIter);
if (!result.accepted) {
return { false, nullptr };
}
tokens.append(ContextFreeCompiler::SymbolVal(
mGrammarGlue.get(result.state), ualni(sentenceIter - sentence), result.advancedIdx
));
sentenceIter += result.advancedIdx;
lengthIter -= result.advancedIdx;
}
ContextFreeAutomata::AcceptResult result = mContextFreeAutomata.accept(tokens.getBuff(), tokens.size());
return { result.accepted, result.ast };
}
public:
// save load compiled tables
RegularAutomata mRegularAutomata;
ContextFreeAutomata mContextFreeAutomata;
Map<tTokenType, ContextFreeCompiler::SymbolVal> mGrammarGlue;
Map<ContextFreeCompiler::SymbolVal, String> mAstNames;
};
}

View file

@ -0,0 +1,101 @@
#pragma once
#include "Strings.hpp"
#include "Automata.hpp"
#include "Buffer2D.hpp"
namespace tp {
template <typename tAlphabetType, typename tStateType>
class RegularAutomata {
public:
struct AcceptResult {
bool accepted = false;
ualni advancedIdx = 0;
tStateType state = tStateType();
};
public:
RegularAutomata() = default;
AcceptResult accept(const tAlphabetType* stream, ualni size) {
mCurrentState = mStartState;
ualni advancedIdx = 0;
while (advancedIdx < size) {
const tAlphabetType& symbol = *(stream + advancedIdx);
if (!(symbol >= mSymbolRange.mBegin && symbol < mSymbolRange.mEnd)) {
return { false, advancedIdx, {} };
}
mCurrentState = mTable.get({ (ualni) (symbol - mSymbolRange.mBegin), mCurrentState });
if (mCurrentState == mStates.size()) {
return { false, advancedIdx, {} };
}
if (mStates[mCurrentState].first) {
return { true, advancedIdx, mStates[mCurrentState].second };
}
advancedIdx++;
}
return { false, advancedIdx, {} };
}
public:
void construct(const FiniteStateAutomation<tAlphabetType, tStateType>& automata) {
const auto range = automata.getAlphabetRange();
mSymbolRange = { tAlphabetType(range.mBegin), tAlphabetType(range.mEnd) };
auto range_len = ualni(mSymbolRange.mEnd - mSymbolRange.mBegin);
auto sizeX = range_len ? range_len : 1;
auto sizeY = (ualni) (automata.numStates());
mTable.reserve({ sizeX, sizeY });
mTable.assign(automata.numStates());
mStates.reserve(sizeY);
ualni idx = 0;
for (auto state : *automata.getStates()) {
mStates[idx] = { state->isAccepting(), state->getStateVal() };
idx++;
}
idx = 0;
for (auto state : *automata.getStates()) {
if (&state.data() == automata.getStartState()) {
mStartState = mCurrentState = idx;
}
idx++;
}
ualni stateIdx = 0;
for (auto state : *automata.getStates()) {
for (auto transition : *state->getTransitions()) {
ualni stateIdx2 = 0;
for (auto state2 : *automata.getStates()) {
if (transition->getState() == &state2.data()) break;
stateIdx2++;
}
auto const code = transition->getSymbol();
mTable.set({ (ualni) (code - mSymbolRange.mBegin), (ualni) stateIdx }, stateIdx2);
}
stateIdx++;
}
}
private:
Buffer2D<ualni> mTable;
Buffer<Pair<bool, tStateType>> mStates;
ualni mCurrentState = 0;
ualni mStartState = 0;
Range<tAlphabetType> mSymbolRange = { 0, 0 };
};
}

View file

@ -0,0 +1,208 @@
#pragma once
#include "Grammar.hpp"
#include "Automata.hpp"
namespace tp {
template <typename tAlphabetType, typename tStateType, tStateType tInTransition, ualni tMinSymbol, ualni tMaxSymbol>
class RegularCompiler {
typedef FiniteStateAutomation<tAlphabetType, tStateType> Graph;
typedef typename Graph::State Vertex;
typedef RegularGrammar<tAlphabetType, tStateType> Grammar;
struct Node {
Vertex* left = nullptr;
Vertex* right = nullptr;
};
private:
Graph* mGraph = nullptr;
public:
struct CompileError {
uhalni mRuleIndex = 0;
tStateType mRuleState;
const char* description = nullptr;
[[nodiscard]] bool isError() const { return description; }
};
CompileError mError;
void compile(Graph& graph, const tAlphabetType* regex, tStateType state) {
mGraph = &graph;
compileUtil(regex, state);
}
void compile(Graph& aGraph, const Grammar& grammar) {
mGraph = &aGraph;
auto left = addVertex();
auto right = addVertex();
halni idx = 0;
for (auto rule : grammar.mRules) {
auto node = compileUtil(rule.data().first, rule.data().second);
if (!(node.left && node.right)) {
mError.mRuleIndex = idx;
return;
}
transitionAny(left, node.left);
transitionAny(node.right, right);
idx++;
}
mGraph->setStartState(left);
}
private:
Node compileUtil(const Grammar::Node* astNode, tStateType state) {
auto node = compileNode(astNode, nullptr, nullptr);
node.right->setValue(state);
node.right->setAcceptance(true);
mGraph->setStartState(node.left);
return node;
}
Node compileVal(Grammar::ValueNode* val, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
auto left = aLeft ? aLeft : addVertex();
auto right = aRight ? aRight : addVertex();
transitionVal(left, right, val->mVal);
return { left, right };
}
Node compileAlternation(const Grammar::AlternationNode* alt, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
auto first_node = compileNode(alt->mFirst, aLeft, aRight);
auto second_node = compileNode(alt->mSecond);
transitionAny(first_node.left, second_node.left);
transitionAny(second_node.right, first_node.right);
return first_node;
}
Node compileAny(const Grammar::AnyNode*, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
auto left = aLeft ? aLeft : addVertex();
auto right = aRight ? aRight : addVertex();
transitionAny(left, right, true);
return { left, right };
}
Node compileRepeat(const Grammar::RepetitionNode* repeat, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
if (repeat->mPlus) {
auto middle = addVertex();
auto left_node = compileNode(repeat->mNode, aLeft, middle);
auto right_node = compileNode(repeat->mNode, middle, aRight);
transitionAny(right_node.right, right_node.left);
transitionAny(right_node.left, right_node.right);
return { left_node.left, right_node.right };
} else {
auto node = compileNode(repeat->mNode, aLeft, aRight);
transitionAny(node.right, node.left);
transitionAny(node.left, node.right);
return node;
}
}
Node compileIf(const Grammar::IfNode* ifNode, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
auto node = compileNode(ifNode->mNode, aLeft, aRight);
transitionAny(node.left, node.right);
return node;
}
Node compileClass(const Grammar::ClassNode* node, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
auto left = aLeft ? aLeft : addVertex();
auto right = aRight ? aRight : addVertex();
if (node->mRanges.size() == 1) {
auto const& range = node->mRanges.first();
transitionRange(left, right, { ualni(range.mBegin), ualni(range.mEnd) }, node->mExclude);
return { left, right };
}
for (auto range : node->mRanges) {
auto middle = addVertex();
transitionRange(left, middle, { ualni(range->mBegin), ualni(range->mEnd) }, node->mExclude);
transitionAny(middle, right);
}
return { left, right };
}
Node compileCompound(const Grammar::CompoundNode* compound, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
Vertex* left = nullptr;
Vertex* rigth = nullptr;
ualni idx = 0;
for (auto child : compound->mSequence) {
auto pass_left = idx == 0 ? aLeft : rigth;
auto pass_right = idx == compound->mSequence.size() - 1 ? aRight : nullptr;
auto node = compileNode(child.data(), pass_left, pass_right);
if (!left) left = node.left;
rigth = node.right;
idx++;
}
return { left, rigth };
}
Node compileNode(const Grammar::Node* node, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
switch (node->mType) {
case Grammar::Node::CLASS: return compileClass((typename Grammar::ClassNode*) node, aLeft, aRight);
case Grammar::Node::COMPOUND: return compileCompound((typename Grammar::CompoundNode*) node, aLeft, aRight);
case Grammar::Node::IF: return compileIf((typename Grammar::IfNode*) node, aLeft, aRight);
case Grammar::Node::REPEAT: return compileRepeat((typename Grammar::RepetitionNode*) node, aLeft, aRight);
case Grammar::Node::ANY: return compileAny((typename Grammar::AnyNode*) node, aLeft, aRight);
case Grammar::Node::OR: return compileAlternation((typename Grammar::AlternationNode*) node, aLeft, aRight);
case Grammar::Node::VAL: return compileVal((typename Grammar::ValueNode*) node, aLeft, aRight);
case Grammar::Node::NONE: break;
}
ASSERT(0)
return {};
}
void transitionAny(Vertex* from, Vertex* to, bool consumes = false) {
for (auto symbol : Range<ualni>(tMinSymbol, tMaxSymbol)) {
transitionVal(from, to, symbol);
}
}
void transitionVal(Vertex* from, Vertex* to, tAlphabetType val) { mGraph->addTransition(from, to, val); }
void transitionRange(Vertex* from, Vertex* to, Range<ualni> range, bool exclude) {
if (exclude) {
Range<ualni> first = { tMinSymbol, range.mBegin - 1 };
Range<ualni> second = { range.mEnd + 1, tMaxSymbol };
if (first.valid()) {
for (auto symbol : first) {
transitionVal(from, to, symbol);
}
}
if (second.valid()) {
for (auto symbol : second) {
transitionVal(from, to, symbol);
}
}
} else {
for (auto symbol : range) {
transitionVal(from, to, symbol);
}
}
}
Vertex* addVertex() { return mGraph->addState(tInTransition, false); }
};
}

View file

@ -0,0 +1,69 @@
#pragma once
#include "Parser.hpp"
namespace tp {
// Gives ability to express grammar in the Unified Format as sentence
template <typename tAlphabetType>
class SimpleParser {
enum UGTokens : alni { InTransition = -1, TestSeq };
typedef Parser<tAlphabetType, UGTokens, InTransition, 0, 127> UGParser;
typedef Parser<tAlphabetType, alni, -1, 0, 127> UserParser;
public:
SimpleParser() {
// Grammar for unified grammar format sentence that tables compiled from
// Define Context-Free grammar
ContextFreeGrammar contextFreeGrammar;
{
// use existing CF grammar interface
contextFreeGrammar.addRule("a", { ContextFreeGrammar::Arg("") });
contextFreeGrammar.setStart("a");
}
// Define Regular grammar
RegularGrammar<tAlphabetType, UGTokens> regularGrammar;
{
// this is basically ast from existing tokenizer
regularGrammar.addRule(regularGrammar.seq({ regularGrammar.val('a'), regularGrammar.val('b') }), TestSeq);
}
Map<String, UGTokens> terminalsMap;
terminalsMap.put("TestSeq", TestSeq);
mUnifiedGrammarParser.compileTables(contextFreeGrammar, regularGrammar, terminalsMap);
}
public:
void compileTables(const tAlphabetType* grammar, ualni grammarLength) {
mUnifiedGrammarParser.parse(grammar, grammarLength);
// compile each ast into RegularGrammar and ContextFree Grammar api instructions
ContextFreeGrammar userContextFreeGrammar;
RegularGrammar<tAlphabetType, alni> userRegularGrammar;
// ...
// split ast into RE and CF part
// generate and execute grammar api commands
// use existing tokenizer code to create RE transition matrix
// ...
// compile tables from user grammar
Map<String, alni> terminalsMap;
terminalsMap.put("TestSeq", 0);
mUserParser.compileTables(userContextFreeGrammar, userRegularGrammar, terminalsMap);
}
UserParser::ParseResult parse(const tAlphabetType* grammar, ualni grammarLength) {
return mUserParser.parse(grammar, grammarLength);
}
private:
UGParser mUnifiedGrammarParser;
UserParser mUserParser;
};
}

View file

@ -0,0 +1,43 @@
#pragma once
// #include "SimpleParser.hpp"
const char* gGrammar = R"(
# Grammar in the CF-RE United Format (Defined by language module)
Rules : {
ScopeList : ScopeList Scope | Scope ;
Scope : \ScopeBegin StatementList \ScopeEnd;
StatementList : StatementList Statement \StatementEnd;
StatementList : Statement \StatementEnd;
Statement : \StatementBody;
}
Terminals : {
Space : " " | "\t" | "\n" | "\r";
ScopeBegin : "{";
ScopeEnd : "}";
StatementEnd : ";";
StatementBody : "a" | "b";
}
Start : Scope;
Ignore : Space;
)";
const char* gSentence = R"(
{}
{ }
{
a;
a ; a ;
}
{
a;
a;
}
)";

View file

@ -0,0 +1,45 @@
#include "Test.hpp"
/*
using namespace tp;
void testAutomation() {
FiniteStateAutomation<char, int> automata;
auto start = automata.addState(0, false);
auto end = automata.addState(1, true);
automata.addTransition(start, end, 'a');
automata.setStartState(start);
automata.makeDeterministic();
}
void test() {
auto parser = SimpleParser<int1>();
parser.compileTables(gGrammar, String::Logic::calcLength(gGrammar));
auto result = parser.parse(gSentence, String::Logic::calcLength(gSentence));
}
int main() {
tp::ModuleManifest* deps[] = { &tp::gModuleLanguage, nullptr };
tp::ModuleManifest testModule("Test", nullptr, nullptr, deps);
if (!testModule.initialize()) {
return 1;
}
testAutomation();
test();
testModule.deinitialize();
}
*/
int main() { return 0; }

24
3DEditor/CMakeLists.txt Normal file
View file

@ -0,0 +1,24 @@
project(3DEditor)
### ---------------------- Externals --------------------- ###
set(BINDINGS_INCLUDE ../Externals/glfw/include ../Externals)
set(BINDINGS_LIBS glfw Imgui OpenImageDenoise)
### ---------------------- Static Library --------------------- ###
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/ ${BINDINGS_INCLUDE} ./ext/)
target_link_libraries(${PROJECT_NAME} PUBLIC Widgets RasterRender RayTracer)
target_link_libraries(${PROJECT_NAME} PRIVATE ${BINDINGS_LIBS})
### -------------------------- Applications -------------------------- ###
file(GLOB APP_SOURCES "./applications/*.cpp")
add_executable(3DEditorApp ${APP_SOURCES})
target_link_libraries(3DEditorApp ${PROJECT_NAME})
file(COPY "../RasterRender/rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
file(COPY "../Graphics/rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
file(COPY "../3DScene/rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")

View file

@ -0,0 +1,31 @@
#include "EditorWidget.hpp"
#include "WidgetApplication.hpp"
#include "RootWidget.hpp"
using namespace tp;
class EditorGUI : public WidgetApplication {
public:
EditorGUI() {
auto canvas = this->mGraphics->getCanvas();
mGui = new EditorWidget(canvas, &mEditor);
mEditor.loadDefaults();
setRoot(mGui);
// mScene.mCamera.lookAtPoint({ 0, 0, 0 }, { 3, 3, 2 }, { 0, 0, 1 });
}
~EditorGUI() override { delete mGui; }
private:
Editor mEditor;
EditorWidget* mGui;
};
int main() {
EditorGUI gui;
gui.run();
}

View file

@ -0,0 +1,40 @@
#include "Editor.hpp"
#include "OpenImageDenoise/oidn.hpp"
#include <iostream>
using namespace tp;
void Editor::denoise() {
auto& out = mPathTracerBuffers;
// Initialize OIDN device
oidn::DeviceRef device = oidn::newDevice(oidn::DeviceType::CPU);
device.commit();
// Define buffer size
const int channels = 4; // ARGB
const auto size = out.color.size();
// Create the denoising filter
oidn::FilterRef filter = device.newFilter("RT"); // Use the 'RT' filter for path tracing
// Set the input and output buffer (same buffer for in-place denoising)
filter.setImage("color", out.color.getBuff(), oidn::Format::Float3, size.x, size.y, 0, sizeof(float) * channels); // ARGB
filter.setImage("output", out.color.getBuff(), oidn::Format::Float3, size.x, size.y, 0, sizeof(float) * channels); // ARGB
// Set additional parameters if needed
filter.set("hdr", false); // Assuming the input image is not HDR
// Commit the filter
filter.commit();
// Execute the filter
filter.execute();
// Check for errors
const char* errorMessage;
if (device.getError(errorMessage) != oidn::Error::None) {
std::cerr << "Error: " << errorMessage << std::endl;
}
}

140
3DEditor/private/Editor.cpp Normal file
View file

@ -0,0 +1,140 @@
#include "Editor.hpp"
#include "GraphicsApi.hpp"
using namespace tp;
Editor::Editor() {
{ // create path tracer gpu texture
glGenTextures(1, &mPathRenderTexture);
glBindTexture(GL_TEXTURE_2D, mPathRenderTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 100, 100, 0, GL_RGBA, GL_FLOAT, nullptr);
glBindTexture(GL_TEXTURE_2D, 0);
}
}
void Editor::renderViewport() {
switch (mRenderType) {
case RenderType::RASTER:
mRasterRenderer.beginRender(mScene, mScene.mRenderSettings.size);
mRasterRenderer.renderDefault(mScene);
if (mActive) mRasterRenderer.renderOutline(mScene.mCamera, *mActive);
mRasterRenderer.endRender();
break;
case RenderType::PATH_TRACER:
{
// TODO : include in render viewport method
// renderPathFrame();
break;
}
default:
break;
}
}
uint4 Editor::getViewportTexID() {
switch (mRenderType) {
case RenderType::PATH_TRACER:
return mPathRenderTexture;
case RenderType::RASTER:
return mRasterRenderer.getRenderBufferID();
default:
return 0;
}
}
void Editor::loadDefaults() {
mScene.load("rsc/scene/script.lua");
mResetCamera = mScene.mCamera;
}
void Editor::setViewportSize(const Vec2F& size) {
if (size.x <= 0 || size.y <= 0) return;
// TODO remove
// mScene.mCamera.rotate(0.01f, 0.0);
mScene.mRenderSettings.size = size;
mRasterRenderer.getRenderBuffer()->resize(size);
mScene.mCamera.setRatio(size.y / size.x);
}
Editor::~Editor() {
glDeleteTextures(1, &mPathRenderTexture);
}
void Editor::renderPathFrame() {
mScene.updateCache();
mPathRenderer.render(mScene, mPathTracerBuffers, mScene.mRenderSettings);
sendBuffersToGPU();
}
void Editor::sendBuffersToGPU() {
glBindTexture(GL_TEXTURE_2D, mPathRenderTexture);
const auto size = mPathTracerBuffers.color.size();
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGBA32F,
(GLsizei) size.x,
(GLsizei) size.y,
0,
GL_RGBA,
GL_FLOAT,
mPathTracerBuffers.color.getBuff()
);
glBindTexture(GL_TEXTURE_2D, 0);
}
void Editor::denoisePathRenderBuffers() {
denoise();
sendBuffersToGPU();
}
void Editor::setRenderType(Editor::RenderType type) {
mRenderType = type;
}
void Editor::navigationOrbit(const Vec2F& delta) {
mScene.mCamera.rotate(delta.x, delta.y);
}
void Editor::navigationPan(const Vec2F& pos, const Vec2F& prevPos) {
mScene.mCamera.move(pos, prevPos);
}
void Editor::navigationZoom(halnf factor) {
mScene.mCamera.zoom(factor);
}
void Editor::navigationReset() {
mScene.mCamera = mResetCamera;
// mScene.mCamera.lookAtPoint({ 0, 0, 0 }, { 1, 5, 1 }, { 0, 0, 1 });
}
void Editor::selectObject(const Vec2F& screenPos) {
mScene.updateCache();
auto dir = (mScene.mCamera.project(screenPos) - mScene.mCamera.getPos()).normalize();
Ray ray = Ray( dir, mScene.mCamera.getPos() );
auto rayCastData = mScene.castRay(ray, 1000);
mActive = rayCastData.obj;
}
Object* Editor::getActiveObject() { return mActive; }
Scene* Editor::getScene() { return &mScene; }

View file

@ -0,0 +1,55 @@
#pragma once
#include "RayTracer.hpp"
#include "RasterRender.hpp"
namespace tp {
class Editor {
public:
enum class RenderType { RASTER, PATH_TRACER };
public:
Editor();
~Editor();
void loadDefaults();
uint4 getViewportTexID();
void setViewportSize(const Vec2F& size);
void renderViewport();
void renderPathFrame();
void setRenderType(RenderType type);
void denoisePathRenderBuffers();
void navigationOrbit(const Vec2F& delta);
void navigationPan(const Vec2F& pos, const Vec2F& prevPos);
void navigationZoom(halnf factor);
void navigationReset();
void selectObject(const Vec2F& screenPos);
Object* getActiveObject();
Scene* getScene();
private:
void sendBuffersToGPU();
void denoise();
private:
Scene mScene;
Camera mResetCamera;
RenderType mRenderType = RenderType::RASTER;
RasterRender mRasterRenderer;
RayTracer mPathRenderer;
RayTracer::OutputBuffers mPathTracerBuffers;
uint4 mPathRenderTexture = 0;
Object* mActive = nullptr;
};
}

View file

@ -0,0 +1,154 @@
#include "Widget.hpp"
#include "DockWidget.hpp"
#include "Editor.hpp"
#include "FloatingWidget.hpp"
namespace tp {
class ViewportWidget : public Widget {
public:
explicit ViewportWidget(Canvas* canvas, Editor* editor) {
mEditor = editor;
mImage = canvas->createImageFromTextId(mEditor->getViewportTexID(), { 0, 0 });
mCanvas = canvas;
}
~ViewportWidget() override { mCanvas->deleteImageHandle(mImage); }
void process(const EventHandler& events) override {
mEditor->setViewportSize(getAreaT().size);
}
void draw(Canvas& canvas) override {
mEditor->renderViewport();
canvas.updateTextureID(mImage, mEditor->getViewportTexID());
canvas.drawImage(getArea().relative(), &mImage, PI);
}
public:
Editor* mEditor;
Canvas* mCanvas = nullptr;
Canvas::ImageHandle mImage;
};
class EditorWidget : public DockWidget {
public:
EditorWidget(Canvas* canvas, Editor* editor) :
mViewport(canvas, editor) {
mEditor = editor;
mPanel.setText("Controls");
mPanel.addToMenu(&mNavigationMenu);
mPanel.addToMenu(&mRenderMenu);
dockWidget(&mPanel, DockLayout::RIGHT);
setCenterWidget(&mViewport);
// Render
{
mRenderPathTracer.setText("Render with Path Tracer");
mRenderRaster.setText("Render with Raster");
mRenderDeNoise.setText("Denoise (IntelOpenImage)");
mRenderMenu.addToMenu(&mRenderPathTracer);
mRenderMenu.addToMenu(&mRenderRaster);
mRenderMenu.addToMenu(&mRenderDeNoise);
mRenderMenu.setText("Render");
}
// Navigation
{
mNavigationPan.setText("Pan");
mNavigationOrbit.setText("Orbit");
mNavigationZoom.setText("Zoom");
mNavigationReset.setText("Reset");
mNavigationSelect.setText("Select");
mNavigationMenu.addToMenu(&mNavigationPan);
mNavigationMenu.addToMenu(&mNavigationOrbit);
mNavigationMenu.addToMenu(&mNavigationZoom);
mNavigationMenu.addToMenu(&mNavigationReset);
mNavigationMenu.addToMenu(&mNavigationSelect);
mNavigationMenu.setText("Navigation");
}
mRenderPathTracer.setAction([this]() {
mEditor->renderPathFrame();
mEditor->setRenderType(Editor::RenderType::PATH_TRACER);
});
mRenderRaster.setAction( [this]() { mEditor->setRenderType(Editor::RenderType::RASTER); });
mRenderDeNoise.setAction( [this]() { mEditor->denoisePathRenderBuffers(); });
mNavigationOrbit.setAction( [this]() { mNavigationType = ORBIT; });
mNavigationPan.setAction( [this]() { mNavigationType = PAN; });
mNavigationZoom.setAction( [this](){ mNavigationType = ZOOM; });
mNavigationSelect.setAction( [this](){ mNavigationType = SELECT; });
mNavigationReset.setAction( [this]() { mEditor->navigationReset(); });
}
void process(const EventHandler& events) override {
DockWidget::process(events);
if (auto obj = mEditor->getActiveObject()) { // dummy rotate active object
auto rotator = obj->mTopology.Basis.rotatorDir({1, 1, 1}, 0.1);
obj->mTopology.Basis = rotator * obj->mTopology.Basis;
}
mEditor->getScene()->updateCache();
const auto& activeArea = mViewport.getArea();
auto pointer = events.getPointer();
auto pointerPrev = events.getPointerPrev();
auto pointerRelative = (((pointer - activeArea.pos) / activeArea.size) - 0.5f) * 2;
if (activeArea.isInside(pointer) && events.isDown(InputID::MOUSE1)) {
switch (mNavigationType) {
case ORBIT: mEditor->navigationOrbit(events.getPointerDelta() / activeArea.size * 3); break;
case PAN:
{
auto prevPointerRelative = (((pointerPrev - activeArea.pos) / activeArea.size) - 0.5f) * 2;
mEditor->navigationPan(prevPointerRelative, pointerRelative);
}
break;
case ZOOM: mEditor->navigationZoom(1 + (events.getPointerDelta().y / activeArea.size.y)); break;
case SELECT: mEditor->selectObject(pointerRelative * -1); break;
}
}
}
void draw(Canvas& canvas) override { canvas.rect(getArea().relative(), mBaseColor); }
public:
Editor* mEditor = nullptr;
ViewportWidget mViewport;
FloatingMenu mPanel;
// Controls
FloatingMenu mRenderMenu;
ButtonWidget mRenderPathTracer;
ButtonWidget mRenderRaster;
ButtonWidget mRenderDeNoise;
// Navigation
enum NavigationType { SELECT, ORBIT, PAN, ZOOM } mNavigationType = ORBIT;
FloatingMenu mNavigationMenu;
ButtonWidget mNavigationPan;
ButtonWidget mNavigationOrbit;
ButtonWidget mNavigationZoom;
ButtonWidget mNavigationReset;
ButtonWidget mNavigationSelect;
RGBA mBaseColor;
};
}

13
3DScene/CMakeLists.txt Normal file
View file

@ -0,0 +1,13 @@
project(3DScene)
### ---------------------- Static Library --------------------- ###
file(GLOB SOURCES "./private/*.cpp")
file(GLOB HEADERS "./public/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
target_include_directories(${PROJECT_NAME} PRIVATE ../Externals/)
target_link_libraries(${PROJECT_NAME} PUBLIC Math)
target_link_libraries(${PROJECT_NAME} PRIVATE Lua)

View file

@ -0,0 +1,223 @@
#include "Scene.hpp"
extern "C" {
#include "lauxlib.h"
#include "lualib.h"
}
#include <filesystem>
#include <utility>
tp::Vec3F tp::Scene::getVec3(lua_State* state, const char* name) {
int stackSize = lua_gettop(state);
// Access the "pos" field and validate it
lua_getfield(state, -1, name);
if (!lua_istable(state, -1) || lua_rawlen(state, -1) != 3) {
throw IOError(std::string("Invalid vec3 named ") + name);
}
// Read the values from the table
float pos[3];
for (int i = 0; i < 3; i++) {
lua_rawgeti(state, -1, i + 1);
if (lua_isnumber(state, -1)) {
pos[i] = lua_tonumber(state, -1);
} else {
throw IOError("vec3 values must be numbers");
}
lua_pop(state, 1); // pop number
}
lua_pop(state, 1); // pop vec3
ASSERT(stackSize == lua_gettop(state))
return { pos[0], pos[1], pos[2] };
}
tp::Vec2F tp::Scene::getVec2(lua_State* state, const char* name) {
int stackSize = lua_gettop(state);
// Access the "pos" field and validate it
lua_getfield(state, -1, name);
if (!lua_istable(state, -1) || lua_rawlen(state, -1) != 2) {
throw IOError(std::string("Invalid vec2 named ") + name);
}
// Read the values from the table
float pos[2];
for (int i = 0; i < 2; i++) {
lua_rawgeti(state, -1, i + 1);
if (lua_isnumber(state, -1)) {
pos[i] = lua_tonumber(state, -1);
} else {
throw IOError("vec3 values must be numbers");
}
lua_pop(state, 1); // pop number
}
lua_pop(state, 1); // pop vec3
ASSERT(stackSize == lua_gettop(state))
return { pos[0], pos[1] };
}
// Function to read a Lua table representing RenderSettings
int readRenderSettings(lua_State* L, tp::RenderSettings& settings) {
lua_getglobal(L, "RenderSettings");
if (!lua_istable(L, -1)) {
printf("RenderSettings is not a table.\n");
return 0; // Error
}
// Read depth field
lua_getfield(L, -1, "depth");
if (lua_isnumber(L, -1)) {
settings.depth = (int) lua_tonumber(L, -1);
} else {
printf("RenderSettings 'depth' field is missing or not a number.\n");
lua_pop(L, 1); // Pop the 'depth' field
return 0; // Error
}
lua_pop(L, 1); // Pop the 'depth' field
// Read spray field
lua_getfield(L, -1, "spray");
if (lua_isnumber(L, -1)) {
settings.spray = (int) lua_tonumber(L, -1);
} else {
printf("RenderSettings 'spray' field is missing or not a number.\n");
lua_pop(L, 1); // Pop the 'spray' field
return 0; // Error
}
lua_pop(L, 1); // Pop the 'spray' field
// Read depth field
lua_getfield(L, -1, "multisampling");
if (lua_isnumber(L, -1)) {
settings.multisampling = (int) lua_tonumber(L, -1);
} else {
printf("RenderSettings 'depth' field is missing or not a number.\n");
lua_pop(L, 1); // Pop the 'depth' field
return 0; // Error
}
lua_pop(L, 1); // Pop the 'depth' field
return 1; // Success
}
// Function to read a Lua table representing a light
int tp::Scene::readLight(lua_State* L, tp::PointLight* light) {
light->pos = getVec3(L, "pos");
lua_getfield(L, -1, "intensity"); // Get the "intensity" field from the light table
if (!lua_isnumber(L, -1)) {
printf("Light is missing the 'intensity' field or it's not a number.\n");
lua_pop(L, 1); // Pop the 'intensity' field
return 0; // Error
}
light->intensity = lua_tonumber(L, -1);
lua_pop(L, 1); // Pop the 'intensity' field
return 1; // Success
}
bool tp::Scene::loadLuaFormat(const std::string& scenePath) {
lua_State* L = luaL_newstate();
luaL_openlibs(L);
namespace fs = std::filesystem;
fs::path fullPath(scenePath);
// Extract the filename
std::string fileName = fullPath.filename().string();
// Remove the filename from the path
fs::path directoryPath = fullPath.remove_filename();
if (luaL_dofile(L, scenePath.c_str()) != 0) {
lua_close(L);
printf("Cant open scene script.\n");
return false;
}
lua_getglobal(L, "Meshes");
if (lua_isstring(L, -1)) {
std::string meshesPath = lua_tostring(L, -1);
directoryPath /= meshesPath;
if (!loadOBJFormat(directoryPath.string())) {
printf("No 'meshes' loaded - check ur .obj path and validate content of .obj .\n");
return false;
}
} else {
printf("No 'meshes' path given.\n");
return false;
}
// --- camera
{
lua_getglobal(L, "Camera");
if (!lua_istable(L, -1)) {
printf("Camera is not a table.\n");
lua_close(L);
return false;
}
Vec3F camPos = getVec3(L, "pos");
Vec3F camTarget = getVec3(L, "target");
Vec3F camUp = getVec3(L, "up");
Vec2F camSize = getVec2(L, "size");
mRenderSettings.size = camSize;
mCamera.lookAtPoint(camTarget, camPos, camUp);
mCamera.setFOV(3.14 / 4);
mCamera.setFar(100);
mCamera.setRatio((tp::halnf) camSize.y / (tp::halnf) camSize.x);
lua_pop(L, 1);
}
// ---------- LIGHTS
{
lua_getglobal(L, "Lights");
if (!lua_istable(L, -1)) {
printf("Lights is not a table.\n");
lua_close(L);
return false; // Error
}
// Read and process each light in the "Lights" table
int numLights = lua_rawlen(L, -1); // Get the number of lights in the table
for (int i = 1; i <= numLights; i++) {
lua_rawgeti(L, -1, i); // Get the i-th element (light) from the table
if (lua_istable(L, -1)) {
tp::PointLight light;
if (!readLight(L, &light)) {
printf("Cant read lights data\n");
lua_close(L);
return false; // Error
}
mLights.append(light);
}
lua_pop(L, 1); // Pop the i-th light table
}
}
// ----------- settings --------------
if (!readRenderSettings(L, mRenderSettings)) {
printf("Cant Read Render Settings");
lua_close(L);
return false; // Error
}
lua_close(L);
return true;
}

View file

@ -0,0 +1,86 @@
#include "Scene.hpp"
extern "C" {
#include "lauxlib.h"
#include "lualib.h"
}
#include "obj/OBJ_Loader.h"
#include <filesystem>
bool tp::Scene::loadOBJFormat(const std::string& objetsPath) {
using namespace tp;
objl::Loader Loader;
if (!Loader.LoadFile(objetsPath)) {
std::cout << "Failed to Load File. May have failed to find it or it was not an .obj file.\n";
return false;
}
for (auto& curMesh : Loader.LoadedMeshes) {
mObjects.append(Object());
auto object = &mObjects.last();
for (auto& vertex : curMesh.Vertices) {
// printf("{ %f, %f, %f }, \n", vertex.Position.X, vertex.Position.Y, vertex.Position.Z);
object->mTopology.Points.append(Vec3F{ vertex.Position.X, vertex.Position.Y, vertex.Position.Z });
object->mTopology.Normals.append(Vec3F{ vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z });
}
for (int j = 0; j < curMesh.Indices.size(); j += 3) {
auto idx1 = (uhalni) curMesh.Indices[j];
auto idx2 = (uhalni) curMesh.Indices[j + 1];
auto idx3 = (uhalni) curMesh.Indices[j + 2];
// printf("{ %i, %i, %i },\n", idx1, idx2, idx3);
object->mTopology.Indexes.append(Vec3<uhalni>{ idx1, idx2, idx3 });
}
if (object->mTopology.Normals.size() != object->mTopology.Points.size()) {
printf("Logic error loading normals\n");
}
object->mCache.Source = &object->mTopology;
object->mCache.updateCache();
}
return mObjects.size();
}
const tp::RayCastData& tp::Scene::castRay(const Ray& ray, alnf farVal) {
auto& out = mRayCastData;
out.hit = false;
out.obj = nullptr;
farVal *= farVal;
for (auto obj : mObjects) {
for (auto trig : obj->mCache.TrigCaches) {
if (trig->castRay(ray)) {
auto dist = (TrigCache::getHitPos() - ray.pos).length2();
if (farVal > dist && dist > EPSILON) {
out.trig = &trig.data();
out.hitPos = TrigCache::getHitPos();
out.obj = &obj.data();
out.hit = true;
farVal = dist;
}
}
}
}
return mRayCastData;
}
void tp::Scene::updateCache() {
for (auto obj : mObjects) {
obj->mCache.updateCache();
}
}

14
3DScene/private/Scene.cpp Normal file
View file

@ -0,0 +1,14 @@
#include "Scene.hpp"
bool tp::Scene::load(const std::string& scenePath) {
try {
auto res = loadLuaFormat(scenePath);
if (!res) throw IOError("Failed loading lua script");
} catch (const IOError& err) {
printf("Failed loading scene : %s\n", err.description.c_str());
return false;
}
return true;
}

90
3DScene/public/Scene.hpp Normal file
View file

@ -0,0 +1,90 @@
#pragma once
#include "Topology.hpp"
#include "Buffer2D.hpp"
#include "Camera.hpp"
#include <string>
struct lua_State;
namespace tp {
struct RenderSettings {
uhalni depth = 2;
uhalni spray = 1;
ualni multisampling = 1;
Vec2<ualni> size;
};
class GPUBuffers {
public:
GPUBuffers() = default;
virtual ~GPUBuffers() = default;
virtual void drawCall() = 0;
};
class Object {
public:
Object() = default;
~Object() {
delete mGUPBuffers;
};
public:
Topology mTopology;
TopologyCache mCache;
GPUBuffers* mGUPBuffers = nullptr;
};
struct PointLight {
Vec3F pos;
halnf fallOut = 1.f;
halnf intensity = 1.f;
};
struct RayCastData {
Object* obj = nullptr;
TrigCache* trig = nullptr;
Vec3F hitPos = { 0, 0, 0 };
bool hit = false;
bool inv = false;
};
class Scene {
struct IOError : public std::exception {
explicit IOError(std::string in) :
description(std::move(in)) {}
std::string description;
};
public:
Scene() = default;
bool load(const std::string& scenePath);
bool loadLuaFormat(const std::string& scenePath);
bool loadOBJFormat(const std::string& objectsPath);
const RayCastData& castRay(const Ray& ray, alnf farVal);
void updateCache();
private:
Vec3F getVec3(lua_State* state, const char* name);
Vec2F getVec2(lua_State* state, const char* name);
int readLight(lua_State* L, tp::PointLight* light);
public:
Buffer<Object> mObjects;
Buffer<PointLight> mLights;
Camera mCamera;
RenderSettings mRenderSettings;
RayCastData mRayCastData;
};
}

View file

@ -0,0 +1,20 @@
# Blender MTL File: 'scene.blend'
# Material Count: 2
newmtl Material
Ns 323.999994
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
newmtl None
Ns 500
Ka 0.8 0.8 0.8
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2

View file

@ -0,0 +1,112 @@
# Blender v3.0.1 OBJ File: 'scene.blend'
# www.blender.org
mtllib meshes.mtl
o Cube
v -1.039076 1.039076 1.792917
v -1.039076 1.039076 -1.285234
v 1.039076 1.039076 1.792917
v 1.039076 1.039076 -1.285234
v -1.039076 -1.039076 1.792917
v -1.039076 -1.039076 -1.285234
v 1.039076 -1.039076 1.792917
v 1.039076 -1.039076 -1.285234
vt 0.625000 0.500000
vt 0.625000 0.750000
vt 0.875000 0.750000
vt 0.875000 0.500000
vt 0.375000 0.750000
vt 0.375000 1.000000
vt 0.625000 1.000000
vt 0.375000 0.000000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.625000 0.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.375000 0.500000
vn 0.0000 0.0000 -1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 1.0000 0.0000 0.0000
usemtl Material
s off
f 1/1/1 3/2/1 7/3/1 5/4/1
f 4/5/2 8/6/2 7/7/2 3/2/2
f 8/8/3 6/9/3 5/10/3 7/11/3
f 6/12/4 8/13/4 4/5/4 2/14/4
f 6/9/5 2/14/5 1/1/5 5/10/5
o Cube.001
v 0.411013 -0.208216 -1.264212
v 0.411013 -0.208216 -0.612621
v -0.208216 -0.411013 -1.264212
v -0.208216 -0.411013 -0.612621
v 0.208216 0.411013 -1.264212
v 0.208216 0.411013 -0.612621
v -0.411013 0.208216 -1.264212
v -0.411013 0.208216 -0.612621
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
vn 0.3112 -0.9503 0.0000
vn -0.9503 -0.3112 0.0000
vn -0.3112 0.9503 0.0000
vn 0.9503 0.3112 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl None
s off
f 9/15/6 10/16/6 12/17/6 11/18/6
f 11/18/7 12/17/7 16/19/7 15/20/7
f 15/20/8 16/19/8 14/21/8 13/22/8
f 13/22/9 14/21/9 10/23/9 9/24/9
f 11/25/10 15/20/10 13/22/10 9/26/10
f 16/19/11 12/27/11 10/28/11 14/21/11
o Cube.002
v -0.351718 -0.467100 -0.602050
v -0.351718 -0.467100 0.049542
v -0.800825 0.004996 -0.602050
v -0.800825 0.004996 0.049542
v 0.120377 -0.017993 -0.602050
v 0.120377 -0.017993 0.049542
v -0.328730 0.454103 -0.602050
v -0.328730 0.454103 0.049542
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
vn -0.7245 -0.6892 0.0000
vn -0.6892 0.7245 0.0000
vn 0.7245 0.6892 0.0000
vn 0.6892 -0.7245 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl None
s off
f 17/29/12 18/30/12 20/31/12 19/32/12
f 19/32/13 20/31/13 24/33/13 23/34/13
f 23/34/14 24/33/14 22/35/14 21/36/14
f 21/36/15 22/35/15 18/37/15 17/38/15
f 19/39/16 23/34/16 21/36/16 17/40/16
f 24/33/17 20/41/17 18/42/17 22/35/17

View file

@ -0,0 +1,26 @@
Meshes = "meshes.obj"
Camera = {
pos = { 0, 5, 0 },
target = { 0, 0, 0 },
up = { 0, 0, 1 },
size = { 600, 800 },
}
Lights = {
{
pos = { -0.5, 3.5, 1 },
intensity = 1
},
{
pos = { 0, 0, 1 },
intensity = 0.5
},
}
RenderSettings = {
depth = 1,
spray = 1,
multisampling = 1,
}

View file

@ -1,22 +0,0 @@
cmake_minimum_required(VERSION 3.2)
set(CMAKE_CXX_STANDARD 23)
project(Allocators)
### ---------------------- Static Library --------------------- ###
file(GLOB SOURCES "./private/*.cpp")
file(GLOB HEADERS "./public/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
target_link_libraries(${PROJECT_NAME} PUBLIC Utils)
### -------------------------- Tests -------------------------- ###
enable_testing()
file(GLOB TEST_SOURCES "./tests/*.cpp")
add_executable(${PROJECT_NAME}Tests ${TEST_SOURCES})
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME} Utils)
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/lib)

View file

@ -1,42 +0,0 @@
# Profiling
## Memory Leaks
Example program with memory leaks:
```c++
#include "allocators.h"
void test_call22() { new int; }
void test_call21() { new float; }
void test_call11() {
test_call21();
test_call22();
}
int main(char argc, char* argv[]) {
tp::ModuleManifest* ModuleDependencies[] = { &tp::gModuleAllocators, NULL };
tp::ModuleManifest TestModule("Test", NULL, NULL, ModuleDependencies);
TestModule.initialize();
test_call11();
TestModule.deinitialize();
}
```
If memory leaks were detected it will be loged in the output console.
![image](https://user-images.githubusercontent.com/63184036/222794298-3f238de4-c0b8-41fa-b7ec-c0c675da8f05.png)
Also debug.memleaks binary will be generated in the working directory that can be viewved with MemLeaks Viewver.
![image](https://user-images.githubusercontent.com/63184036/222793169-a405effe-72be-42fc-b375-bb06dce0a735.png)
## Memory Usage Analisys
Currently outdated
## Benchmarks
Currently outdated

View file

@ -1,27 +0,0 @@
#include "Allocators.hpp"
#include <cstdlib>
static void deinit(const tp::ModuleManifest* self) {
tp::HeapAllocGlobal::checkLeaks();
}
static tp::ModuleManifest* sModuleDependencies[] = { &tp::gModuleUtils, nullptr };
tp::ModuleManifest tp::gModuleAllocators = ModuleManifest("Allocators", nullptr, deinit, sModuleDependencies);
void* operator new(size_t aSize) { return tp::HeapAllocGlobal::allocate(aSize); }
void* operator new[](size_t aSize) { return tp::HeapAllocGlobal::allocate(aSize); }
void operator delete(void* aPtr) noexcept { tp::HeapAllocGlobal::deallocate(aPtr); }
void operator delete[](void* aPtr) noexcept { tp::HeapAllocGlobal::deallocate(aPtr); }
void* operator new(size_t aSize, tp::HeapAlloc& aAlloc) { return aAlloc.allocate(aSize); }
void* operator new[](size_t aSize, tp::HeapAlloc& aAlloc) { return aAlloc.allocate(aSize); }
void operator delete(void* aPtr, tp::HeapAlloc& aAlloc) { aAlloc.deallocate(aPtr); }
void operator delete[](void* aPtr, tp::HeapAlloc& aAlloc) { aAlloc.deallocate(aPtr); }
void* operator new(size_t aSize, tp::HeapAllocGlobal& aAlloc) { return tp::HeapAllocGlobal::allocate(aSize); }
void* operator new[](size_t aSize, tp::HeapAllocGlobal& aAlloc) { return tp::HeapAllocGlobal::allocate(aSize); }
void operator delete(void* aPtr, tp::HeapAllocGlobal& aAlloc) { tp::HeapAllocGlobal::deallocate(aPtr); }
void operator delete[](void* aPtr, tp::HeapAllocGlobal& aAlloc) { tp::HeapAllocGlobal::deallocate(aPtr); }

Some files were not shown because too many files have changed in this diff Show more