From 6ecf2208918d31d9f5dea9307a9db29079d02b87 Mon Sep 17 00:00:00 2001 From: OmniaX-Dev Date: Wed, 15 Apr 2026 16:18:16 +0200 Subject: [PATCH] Switched to Rust-style numeric type names + other refactors --- .clangd | 4 +- CMakeLists.txt | 4 +- extra/img.png | Bin 0 -> 347172 bytes other/TODO.txt | 5 +- other/build.nr | 2 +- src/ogfx/gui/Events.hpp | 24 +- src/ogfx/gui/RawTextInput.cpp | 46 +- src/ogfx/gui/RawTextInput.hpp | 42 +- src/ogfx/gui/WidgetManager.cpp | 16 +- src/ogfx/gui/WidgetManager.hpp | 4 +- src/ogfx/gui/Window.cpp | 232 +++++---- src/ogfx/gui/Window.hpp | 105 ++-- src/ogfx/gui/WindowOutputHandler.cpp | 126 ++--- src/ogfx/gui/WindowOutputHandler.hpp | 62 +-- src/ogfx/gui/widgets/CheckBox.cpp | 22 +- src/ogfx/gui/widgets/CheckBox.hpp | 22 +- src/ogfx/gui/widgets/Containers.cpp | 8 +- src/ogfx/gui/widgets/Containers.hpp | 4 +- src/ogfx/gui/widgets/Label.cpp | 12 +- src/ogfx/gui/widgets/Label.hpp | 16 +- src/ogfx/gui/widgets/RootWidget.cpp | 6 +- src/ogfx/gui/widgets/Widget.cpp | 14 +- src/ogfx/gui/widgets/Widget.hpp | 42 +- src/ogfx/render/BasicRenderer.cpp | 378 ++++++++------- src/ogfx/render/BasicRenderer.hpp | 116 ++--- src/ogfx/render/FontGlyphAtlas.cpp | 42 +- src/ogfx/render/FontGlyphAtlas.hpp | 32 +- src/ogfx/render/PixelRenderer.cpp | 48 +- src/ogfx/render/PixelRenderer.hpp | 42 +- src/ogfx/resources/Image.cpp | 2 +- src/ogfx/resources/Image.hpp | 8 +- src/ogfx/resources/UbuntuMonoRegularTTF.cpp | 2 +- src/ogfx/resources/UbuntuMonoRegularTTF.hpp | 2 +- src/ogfx/utils/Animation.cpp | 10 +- src/ogfx/utils/Animation.hpp | 62 +-- src/ogfx/utils/Keycodes.hpp | 512 ++++++++++---------- src/ogfx/utils/SDLInclude.hpp | 6 +- src/ostd/data/BaseObject.cpp | 2 +- src/ostd/data/BaseObject.hpp | 14 +- src/ostd/data/Bitfields.hpp | 85 ++-- src/ostd/data/Color.cpp | 68 +-- src/ostd/data/Color.hpp | 67 ++- src/ostd/data/Types.hpp | 92 ++-- src/ostd/io/Console.cpp | 70 +-- src/ostd/io/Console.hpp | 55 ++- src/ostd/io/Errors.cpp | 4 +- src/ostd/io/Errors.hpp | 20 +- src/ostd/io/File.cpp | 2 +- src/ostd/io/File.hpp | 4 +- src/ostd/io/FileSystem.cpp | 46 +- src/ostd/io/FileSystem.hpp | 30 +- src/ostd/io/IOHandlers.hpp | 68 +-- src/ostd/io/Json.cpp | 206 ++++---- src/ostd/io/Json.hpp | 62 +-- src/ostd/io/Keyboard.cpp | 10 +- src/ostd/io/Logger.cpp | 2 +- src/ostd/io/Logger.hpp | 14 +- src/ostd/io/Memory.cpp | 20 +- src/ostd/io/Memory.hpp | 2 +- src/ostd/io/Midi.cpp | 12 +- src/ostd/io/Midi.hpp | 36 +- src/ostd/io/OutputHandlers.cpp | 58 +-- src/ostd/io/Serial.cpp | 32 +- src/ostd/io/Serial.hpp | 34 +- src/ostd/io/Stylesheet.cpp | 100 ++-- src/ostd/io/Stylesheet.hpp | 40 +- src/ostd/math/Geometry.hpp | 301 ++++++------ src/ostd/math/MathUtils.cpp | 4 +- src/ostd/math/MathUtils.hpp | 4 +- src/ostd/math/Random.cpp | 72 +-- src/ostd/math/Random.hpp | 70 +-- src/ostd/math/ShuntingYard.cpp | 20 +- src/ostd/math/SineWave.cpp | 4 +- src/ostd/math/SineWave.hpp | 19 +- src/ostd/math/Spline.cpp | 80 +-- src/ostd/math/Spline.hpp | 22 +- src/ostd/string/String.cpp | 234 ++++----- src/ostd/string/String.hpp | 142 +++--- src/ostd/string/TextStyleParser.cpp | 28 +- src/ostd/string/TextStyleParser.hpp | 28 +- src/ostd/utils/Defines.hpp | 2 +- src/ostd/utils/Hash.cpp | 102 ++-- src/ostd/utils/Hash.hpp | 6 +- src/ostd/utils/Logic.cpp | 59 ++- src/ostd/utils/Logic.hpp | 2 +- src/ostd/utils/PathFinder.cpp | 40 +- src/ostd/utils/PathFinder.hpp | 63 ++- src/ostd/utils/QuadTree.cpp | 6 +- src/ostd/utils/QuadTree.hpp | 11 +- src/ostd/utils/Signals.cpp | 13 +- src/ostd/utils/Signals.hpp | 95 ++-- src/ostd/utils/Time.cpp | 162 +++---- src/ostd/utils/Time.hpp | 92 ++-- src/test/GraphicsWindowTest.cpp | 10 +- src/test/GuiTest.cpp | 26 +- 95 files changed, 2587 insertions(+), 2465 deletions(-) create mode 100644 extra/img.png diff --git a/.clangd b/.clangd index 122ab09..e6defe1 100644 --- a/.clangd +++ b/.clangd @@ -1,2 +1,4 @@ CompileFlags: - CompilationDatabase: bin \ No newline at end of file + CompilationDatabase: bin +Diagnostics: + MissingIncludes: None \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 40c633c..b8632cf 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,9 +139,9 @@ if (WIN32) "${MSYS2_UCRT64}/include/c++/13.2.0/x86_64-w64-mingw32" ) - file(WRITE ${CMAKE_CURRENT_LIST_DIR}/.clangd "CompileFlags:\n CompilationDatabase: bin\n Add: [\"--target=x86_64-w64-mingw32\"]") + file(WRITE ${CMAKE_CURRENT_LIST_DIR}/.clangd "CompileFlags:\n CompilationDatabase: bin\n Add: [\"--target=x86_64-w64-mingw32\"]\nDiagnostics:\n MissingIncludes: None") else() - file(WRITE ${CMAKE_CURRENT_LIST_DIR}/.clangd "CompileFlags:\n CompilationDatabase: bin") + file(WRITE ${CMAKE_CURRENT_LIST_DIR}/.clangd "CompileFlags:\n CompilationDatabase: bin\nDiagnostics:\n MissingIncludes: None") endif() if(CMAKE_BUILD_TYPE STREQUAL "Debug") diff --git a/extra/img.png b/extra/img.png new file mode 100644 index 0000000000000000000000000000000000000000..334eece4259e19e157aec28b10e9593dfda0998a GIT binary patch literal 347172 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�Su2nD0R>WWJZE790OX}jdWDXLdc{c6pgI$7Zv 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 %ki+D}w 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�>~T`0;p1l=Z>B`d6aX? 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 `(U#O3W?fte4?fpodlYvSj{}1v8cZZZD3;+Iz zy`bd+73}HDs2AawB_?0o0`ei%9yRUPJ1YgP`^E4QwJge=Z|&!cIybQ*oO(!Ie?!`4 zLa;^c0x$%cUJO+~=lZ_!nJNKL5Q;>x$a>=sQkJ4EC*FS&6gD&1|EU5@1Su&ZM9Uh( z(BzO#P||=mXJ{9p@n^CigAh8=_NI`0KL0;u!2?!Rd^_&WCh<-O0K)5{;g+0x?~>h8 z(@HOPgot&3joS_SQNiVfk9GQFU-Qig~mnIGz=QsuQb(*4i!n3>zQFcnKg z=zZSU%?--+JYW|8mLdZsNa!KJ5LOK2MRF8tfl--a;aahy{IrDS*a(o`*)n0H(Sw_-W`Hsh;TQF{r*hSMK>mVu;X7K zNs(9fM}@W19?+H(TK3G7;jB!EP?wZ*mE|U(CtOOs#U*b4u`$(&iQzZZX*ch$0wNG1 z*yLMclrK1EdFSqvx422$seVx}=ju;&lJDz@{0T}2-UQV^&z#?Z_a35ltCm5#K<;?R zQSA1LmWY(FoO5D9oWVe1WiOEtQ zxD?fRT%NKDHpc9Q5DfTl-HkXM_4ErPuglyI1_4%m3od)dt4}Ooo|M zgv@sBGm50tZ`6o56P;T^8?YxUM^(sTl?t~`A?5o1j7 zGA8)EPG|2Et=tsQAi_PQ8vDGx1?iObzs!T+H8DyJlq-zY*R9$g=`EY;wWuL@ReDuz z<6a^iSwGP(x_~H2_JR+@Yb|dsGn1ch2#iR9DPFvAwi)pK*fPzN#jc4(D_w92ANXQ+ zRu`GB@EHKWDS;&afVFC0Uv+hVU0QkAIGBLDt zk$1qJt?8+s_UWImuS5B>Yp*o1$tZAt6HvhTh^@tEPL%?1(BVww+mFOQW8Z-KA0GGo zT-v{`kyc7rc|7)?PMQ)eD?F|#H4v?zQks!PqImJhBrowhNZhX)5T^pQKGds3TBp5$ zH`cULRTfCHkEfjap8A6Gvm~&E3vB#=QBaJ9h7HYOTUne`>g44mx}RV<&5M_m97{aC zkz@S|_`7?R^nayh%k^h&YY%0}CszhlP?+i8aSxzIxnPap1T%CnZ7o=hM1(MyteDs7 zvBX+-VXDT1f*XOay~j<)1xw+)L19QxCwUk`0FlLaaJ+Xc1&(9?%caA|mbP-h@MD3a zb_v!K`N~`W)5l$TC;V;rF+~j_*$-wUjqIcmcCMywYtpK;Hy3@)H3$EhO0wxV3ee10 z*bg~vRZ=3rrC{KDzN9;vyRGY^`T*2_a_jiy!m_E?Sxp7GjQAhN;`Z&mQ?4&9QKNur zcrPl=5VaccZQ*sR$U=TUE8fmS{9Qzg zm&wZP-$`;y3c5ibS+?piQLaJoFo7F&+)bjVdYOVh3SM+<2kuuo6Dz{_&y(($zbxMN zSL{P;4?^!n|HctN=~$xKwf_6AP}6?e%$4Y56U=1Fx8<`zrepgWpZ4MkAjVWUiJrVo z)FgWMO#t(wXq@@zDmDu zoeeyZVT8Es9BJs~+He-F9eY~w4`2T}$Sai*;;@3!vH{1U*_iOe?xt%7c00xPfsLwYq%3p2ox z7SJu|z)huH6W%6YEBifO`q*HOImPOR;EYFzucfAdD-a?=9-O>2iI;Xagf`JkAwwv> zVbOlu;j~duJx?^_{LSfjUFF(-*?45toF-B)x|s&dwnwpNU0caA@xb+uKms2WOd{8J z)ymFkl%ZY__d~AP1OP2izDO-3DmR%}voEnSE6L=~?iDkMBP{`ts5?rGZK_?Cl-Eb~ zaR!+#cx(7tj^xvvt3_^^iohm#Xa}ZeLH5l{zHtG&eGkpF$f@&GzI7)ZAtaVwccjrw zy7uBEI=~nm|DUM&+Bq(Vu92oIk|?>l?2G)}U2Y&Hw>rUYQl!+l`I`g(>6%^IL!*Yl zc!~q4*K*jQ`}rZDR5~XJzN{WWy#3lqnm|)Hiu@x!5Zax(MZc zl?EG5#@kuC+-4cEL_%%Ol9n2>kS(r+fx>PWsIoqj{9IIEy+q8VsQm^eud@M7Pq58d z6YzwP_vRo!P&|o{W!>tMKz>q6OTPfp;9j~T>sMK**1CzLRtY{LPVt>`Gd0>2Bm5=* z7h$Y=X`_j1PQ)nTrEtWL(G1W1>0sbuQw<8SUdfHUM$(ri!bW?OpS4b`g044Arc>D&Xa-+$h z0zPsmgBM8@sgfd^;5*aP7DH+vyDL~~%Q;>wxtj5(9E?(yD< zD;c+!PnXVPpPj3X+>oZrA5+Pi8>piPG{g`CgV8KglhzCMyc~_)R~|hO+w_ZH39NjX zP>LbX&de%J5cabk+|4mZe0qCM%HR4L_nd15MiPEK4Tm=&iOr!U*P^u@Z4y#Xa?WJK zjtOf46qPu@H5tV5K$Ym$mZJv8d)T{ETdR6-vKNn~uSR39!?{)gVCcc#9s3US(y-BV+r7)`QXhElo z!t(jlqNY5-j86~8M z6m#P>Jv%>Ho?y*Zv@J9(N#wF=UxoF9Ka>dHz09Q={AY#F(@Jp0E4=>4VJq6J>2h@!_!2{7j2 zP|i->cB1aiZ*Fv~S~fSpd3x#=(c$9oSUf$lQouH64{w8aKmQ0l>KZ+bDne5IVBR&d z`)gk;M=Oy)hfF>}XBs$p2*|M`1vdlwollDmb44q=R2tOv_`B0fl5$b`)4c=(BVl(TA&?5k{j-LpGB)ZV9Qqu`CgHaq=-ZIprgjZapILM7 zcpE7GKB?e?`ngBAgSYk=Y~UoQTV0s#ypean zm*dxYna*oty?7j^xl7pMqMt7zlEL8yjp%G6>zS(F6_5R^tPrFv5Sp2+h?YiFI4?MX ziUuHQyLD&u)4m=c6o~Gqqov;l)(Ct0@p$u_@cXHA!%J;f^OAzBR3u8IcC-`bM7GZ` zFU!+t0qdo&2grX>r9Gb&VcmPF@&0lw8N8uO-7ZK#>F?M)J3w|?wzB@D_j=(75dnUf1hgd{u_#{PdRp>VxHGBu zFqn8^41*41Y;bPsfZHdNuY}hIKu4!u7mCk{O6KzhE-9<_rK8v%SN+Hm@i=)lcl-}i zXG7F{VmYsdn31YHz~sXkx)}yEQu|Zc@`s>{W-WfziNpjGs+i{ehc``l?$4VO(>B4D zFe{M<{WFI?b-&UVD$P}aD}vJt=95t0vV}u^yQm}UN&?O+dzt)h*iTctCUQteYOWxU z)o9@<^Y?&W`eRgB$7Skj75(W^IW_w5Aj z=3c8cjzYl9Q<9}EJhAeB{kb9VjTGGkLMRdakNc`h zx?zR(c6)xEAIEqs*E=Y1YzAXh&n;4vUS*MF(ssJQocEVpe1ROu)B{bLGZ4y6+H{4sMu6Fjt(a6;Pt2-= zI;B@!-s7%Vv-$Ow2wxvD{p)KzE@$+1-aD28JDj2WVMY_I8*T6)wF^wqkq@*)Pk$@z z69H0Lf71t+5*|JP{xNM&`da0eCV{ozn&*}t_&R?oa?E%g4R~5~V%*+y=A;kzIA|^kQ z4Y(_5zo@+pYW zDIRA8BL@?J22n4wlM5RZ7j47k2J#LW!Ve$^-fAa^#bFbn$2r7ZIx zo0ynQ%%*_K^CYtprI-jnQMA=|)4?0opJAa{2j2^da-t8zKV`m3-V<~nKZk_*W7kj` z5*CO)Zh7!@Bjlin5KhH(+$9ZLN|l4fo$W>bGZ!I&poV47HNk~P4Bmq{n_FFX1sL;X ztjcjh&&4xuZV9H^ys%Y|IFLglN0{xOSd>F=Z)s|ZLt57;WT7y1LWor*q?YOF!KN(B zB^r#W*jWM5V~AwAk;(oBUbuj&`Ib$aEx`#%Cz8)|j;$wObt)lFs|40lG#5CtoF||7 zqK415=zHr6%|EewlX8nFTb04dZs;;~?$Ig}bC}njF4lxsXIw1z!xvE7K^d|6QXrcc zG7G%!d_+vzMh%Gz+^{Dw&r$C`kN zQ!kOa&WtBHjdIYQlGjKfi?U^6upp_Rmse}YjaKwLksR3j6VV@cUgy7~YlHG~QEFqu zvf&t59GK-^O@%54X3kW@1HpHXLc5!IUew&puOV2*glI;oI$wv~LL zAnS}V_n*2Si%0Y~X+JJbzb!b4w|h8#%&Xh&r>R*ry0SV#JnWv#SAZ^CnX;MwKKsIq zf1)ZYtO>Be+vnW=0-V3c@7jI_yi-uC=Fro{{+v_gXNk#?AHgR+WRo&ibxq9sty+*% zyyO~s_42RJK~-!`Ap3+6>)8oMj>kk<)ym(@+wrt)+X7Ir{6qklUkacU7yI&S5Z{-@ zBR;`|@&v&Z<=M6(TV5k;d+$abd_u~lBI-zUoJCM=dF;~6L;vP4kSA1TTL)IDOL@Yl zJLQcB`dn9N$99C+6KAc(m9o)=Fd&57oa8UnyqIeU|9XU zvEQaoc<`EM$Q+9d-ip0VZQHhs2(Oy|)Ye;Cn*c!aE?n~_JhRh(06M-^H%&&N@^poJ z#_b-U0uVF!Vt-vTv_m?#^Wn9kKh$(k)Y`>{Ggx7A(k%A^YB+HzyW;;LDh&d^W@ezeCeUB&qwK zlmjBy&#X|$sDDkU*+AY}+vo=#R*#?fm3HhspGob;h6MG@zxAJ{z=#gk?De#ScVt@I z1ck0)k7xmRi;BpBZIwCqQ+?+PEHp(>3ej6b9xA?18A0~V*n zGGEIgQVIRHzOOzEb{!U4cj+ayK~8P8=(j2j?j59^E?SN*5dwX_4^CBE{B(#|cSRfh z>AVKImYq8~LkmD{L1??BR{?Fct0`sfB@*%7Gf~$I|60m-kEYqcFJCwvb8qW@W>-d` zu;Fs+V94d2wLV<=5zF#7P|w?7X368e){nVxl?zTQHh7q5M!~T$<8=pG3E75wTZ{r; z@qaag&rBL@dV#?ka4dW9d3zoUeWz6>wvy9L&o`id#2IH=?5x{%=DGDxwIAtAA>+)@ zP^7xFD-5(Z2GKnna1YF5dEWvoG}QTE-R-bYwU+bd4Qi@=D!cwf(T)u-f7!qKj*ttX zq_T50buV628#=Nrn#XA&n6|fuwPt;~Pxxoq5xNhB^06{LgJvto;2}YiX)hfek56*U z?FNHOJq4qntUZAR_|9>|&OuI2_Bc5wU}ZvS0uo$VleEReH@EL z7z<9)kKZl>cNYXeh)Ba9f!jf1reeG!SW1p4I{N9sMF7AiFg0{H9-c>y-&}X{&|DeU zMti$RYo!_;etZ{>EWB8_G(JE7aQtP+1=_M5kNL-UG>SgnP>+bqx-E}_W z;^Ly2Y}%=x&w+nUP--N$@)Udm1?I`QfjY7e154z^wD|ia#Z>6on_A?8N<5 zo{iB6sy~7KHbatcgEG=YVcDFdYv%aJhs0HbRH1hiY($J?8Lr$1XG;+4w@8m80sD;v zCDKOj9_=Ho%O)2p`Gw*2yU6-+z?X*}z%dDle!zxhe8I&2|t1p;uS$HTM{Kx(?g|rm~KF(owd3@XG(6 zL$F)YDU+ifH($(!@%e268A>7LpjH=_t=U+&!yajeb6A>neEO3JaS?Iyu6_PpOVIM! zsU`c!6mci9GFW)BZzS;JJIj4izon)&p^<<$9|&W#0DS#@fc8B7z^6xQ%(Y7*i2 z>nDIWem&=-|osa&wB;z7)_Dm<1?hfwh}Z%!lx4!D)K&B zuK;TB$D~KPmk`?y-t_Ub8KJva+$+I?zr=>v9sntOg7LNT4FqHaTuKp}c{!Mv>db%H zMv;F1RsIu?t@;c&X(JSq{CVEa_4?ZjQh|zcVX@hq=y}Lxm8JF(eA2V``h_gPD;9mh zH|krh&gF9fQTLg2Y4go@|E9g)wDM8$Sk045RvO%Nx81-VZdIJy(MXBC2v{u!-r%wG z&Lw(EhmE#C9i_Ee?>{PfOKx;;q(tX#jk+_X{t6s8={=COi`Xg8MY7}s)S%8f+b&iy z!sjFE0tSZ|M@5K@$|oulGLs+!365m3INb zJBz;B?>tHqJrdPReUG6>8mHdSmFN9~W)V~=+dorJ&RNpJQ_wQ|KR$sP?yW%R4DBP8 zI@yP0lTN0D_HM;!$fqmnXJu`eX;gpiC+HbUXbveq;q37?^WdhC^TcMsFYvv7UeAu) zGi~S4LnY?ztf0B*%&`ZQO3wXSG~ZN?*&qGZXji2QK2kgy8u9nmxg@+A^Th2$vFH5k zVr-tnCA*&)IwRhv!Y66v1^ry1&)~Ad9Zf`c=^wY(4?UG7E+Ws+Qt+>}cF#WZ-Qi!Q zTs+_P+Ep**I<$K262vuWX4vRMH<0@2asOdBza|pY+?f!|ZL(zlg^^ClJl zN_aoC>Ip%?t+g5}pY~VhG|Nr>tW+_31Yww`q#W6bE>z|DoR?=gl6*8Tfv2s-mL6k3 zAGob8e4|Qz-t_or0Wn7O)~>|G5b3Dwm6wCZc-GePW>%!SVWVes)yU}${lVpfk}G}@ z#>@M+Lc|!H72)1hIoSDR@J$r7H;W=k=;gg4zu5}fEI{L|W8a~g4;&HOx5Qugv@5fTmzL`f;C~Wm_$4}(edE4U&Bt2fx+ejziU^g% zTPJo@A`B+h?EgUC8OQAa91FW}|C%NtD-aw6t*0KYHo8F+J^Q&U|5f12_~FC1tai>b zb5E?a^nM%ky6=g>aXwoVjp)4p(6`Sc+7YPzT042XGw+yHwyl$9sBTdJ@ICD6U0Zs{ zb1eys=@!+kK>pfKC(=JVD=POr{KN%reE9o)U}~p$he)2#`yn>3Pwq%CFDNY5I%4tf@%*#dsU1%J z%_qcuMEJjQIB_(xDm85ChLjItH7~4`uVjWFN1fP;-6KDER0p`f?sqVO9#Z!2i=oR% z8*AUNyNfcLMTqorB9^2zTqPX~7 z>u<4;)$0vExICZ{Mb)opuIfa4qkyb_(>}yN?OO8HTIr$CvH*^Ngb3%wU|!)Q?JrTT z9$HO5O~Ar2s%j}Y-b;s|NBU!nm)+2UDz-r#O%x}%s%?3^h5IHU*de&xl9hfa^=DAdq8a$J9I zH!wkRd+o|QHggDn-6F{@31HVgz)D`zEoL3jnC{L!4qO5!moYcutqzv`~3GCG#hII6+JQ~B2B43Pl3qUk3VE@QR;l!g!uQ4c0R1;Zar185ONdJ znk;!v&ovtm zi7T}=s9IofDPYb%<1S0c=TVo$wc^3JqfoOpMh(?o>`9f94PDdA;P>L!j+DS> zWMK)iyH#8ZBp{(f^FyB#G>A}YsM+&y9Gj+y%R2VOiCxB)4U64R;0vOau!a~|isp8? zp<{3@45d`&Tcuh5^Y_!;T8r?i4PL9R+{`3F3g))topFgwJ+ZrC!ERG3ZUZhi4!YsH+?;nTX`@cT4k1#UgnhEvl*)|xK&DJEWS=?=y=hNYTiPI-Jg^T<^Wi+Z*SGu77J$BbL1c1Fgu69z0 zfW1Cd@9h~VH$KppS!{!B3&eu%xt6(w4LnW4@V2RBlg(V}2t>n-WzByMbQk6qjNo+9 zxx)YGrdaE#3fRpE__vIVxNTw8znMNvh4grjIT3|N()^4+t<>&+G}>dry<{8?QNzFD z0VwEPrE3&NvS{I1-% z2W;?fbL>FV0M5+yOs!MXY~(+--J!v}gJ``SLTqiMbScL}X38I!{#Z&W4q9pq+QKB@ z&LX&+dZq~DKqdKQ!Ru4UiST?EwwmNaY}}-+4UTmsx3IS1pt+w;S|1H48PF?U!tJ9b zL;U(XhqEm}l}e?j`r(DwF@O2TKbf!<|BF*eLqP03Gm~G-ii1`6blT{g>KkbRA%IlF zn=gnyY<<6Rl~pIeHXHgL2;Orja7$W$cpsD;rI~bKnbZfEEVY00Sdp1Po?iPP?&s)z z;i1$g*DOew@SB>5efr8LBVIii`@#Di743Rm+bT^lnnVr#aabO_m??hQ8@RMvbusiz z>{g{?2IvZt-HA`{-?xGa-Y!+B-ctay@oHAijiJJIStuw!r;1V?gOBXW4s!U#_6wDB zrR~y#?fYw9cbQiz3nHrCoA2yZ%-3H4(TTJd1t{V2Oel{3Vbp4x1e}g(yLMexP_7tc zKUI;Ox>0?!|0+o!$Yl-!bJUyodqFjJE*kVFwTH(kh$Ft|1wKq<*yw(GAl9B9!LgsW{nZ8A49h6Tf~Z#f;E)BRRPkx z#Jeo-_Fr%IvM5GsuLf(oVOBkOFVNf6=8aum_?>0n_q7!r#P)lQm0>asFKr~n`HyZ> ztM;9R(DOVG!+NA%1XM*}k**5M0%2}s!IXtUh{mvJFcBxC<`C&z7WZ>nZI`$pcoP0e$O_O~Oq-F~Fn zZKNvx(nwWRcE!!vo(@SDF&K@e+{`ntqqxFvMiP^`{f3%oi}KJ6meIbFiE6l^YhNsC0{J@92Dw zfQVT1ip^YRs}IoSxXe|YgDz^~ud8!^{9HQPceG4UnUyRQt-j&FD!I^3_yJcu(S{q% zav(`a`5kO@tsi^relRrgqed&k{tLm6)#BqaH&{-B#UpIM*l#=#r&^E^;Lv@sWMBW+ z;Ag!rqLS001M*VP4ikFsO{_2mrVH|Ju&x#T_sDRVLuKHe-rT}%Ly3pdoRywGxF@mN zLw@o&(oV!UZHXP;xFEZbMd(AY{`FS^iV9zoNtdbY7#y(Ca^vHNsY?;Kt}j3O+x?wW z9?26#{RLxew6eLFZ3#TgHI~eq*XYXPVjiF#(bIuj<7{n)W<1%W)TE%7>kbogR+lS~ zdP$|ImaMh_22_a^i?4V6yrk0e3EOvLXVP9TV$C| z;PJo4>E-9KHz5 z7a-HoanbYVT7}qofe=a5i@*K9m&)+43ghDLgkRLeL()nXT6vZl=yg316wa;;RaK*3 z1e%cT_D&Q+!4Xx_)yW6FfSMjVuX3!rT+5K{@f4&9z8osWbs7-EzOND5CbhlDAC9KD z+$Q$Tt?Ng+qD&f}b*iC|NL*q4}R_u0+ zyJ1Uyd=&UFo}XOAGAEnxZ#k3u8~ojIC`a9`-5V|-&jj#eXjSL;%W~LJ1nbsX$d*jb zLG1X&OMGYc{X^EQZ`{C6dy{o?%V?qsH?W9Or7 z;C!td7-)75MjYQZ^rGK_nibj?N-Eh;)#Eq2s2XuZUuEr~-}BHlG4!v4J8;48_KVer zDf5(|{`Q3`9pjUaatBL4#*LGG_j8YOmlK{n289R`0gI0T`VpK(*E*eE^CX?9@9kx` z56SSv;BtW?XDXmTv0S)G(&ZGOS@qLj`tg((aJ{8*FbY9Z!$Hm&8?kubDTp++E_wg& z1^nAm?PDs_2Xq0#@A(7D$Dch9Z|e*C%MFm6gfabOrVg{D+&FA=nqWa^r+03eXule3 zU%q@u^&OTm#pcMDdY{rvFFVpk*yL_glifK_E=)~kbK?OQgPmnXX291(dT2`Rc3h_7 zRMpXlbfYr)403j%w>X9IpMdUKvY6Ma)(Pc`WqzVQBaqZ*i-R zU0Zglnx~-^OyCb2@0Y&~ zwdC)(h=B4R)pL>k$GMmFPv2j2fq@#%6sTXqBj2CsaTJv#$)&NK=hk|HZD#Cj>ZMF) z*IU&$-M-d&zpdKO^IUVEOsW+BBcWKRMwXhr!*eu|xr#J9SItLZ8cAZ9Fi`3G5QE1W zl+SIR?|G8=iSR7AJa?y2!s(lNpgq~=~s*C%8Bn|+@l^dB5lVDQmZ>n`hp&3Ebm zL(+R+vS?__*_}K$p^wh?Dpqr3O4en``8bx+KBsg10II~l(w(bD9jzO|gvxs(Z6n9( zl@O=K7%r+@y3e_jcqi4=O_i#iege4S|9q~Mt-gjLYykl$jN-A`p}=+I{wMMWm;>eE!NQ{+hF?dI%?^BKqZs;yY`tc*?A4SZ>h+a zk+lBio(eqQcbqvZr#;W5{2R$#B;07j{OrZWcAiK z_>C<8;&2x3lKyz~?XxVRz+K>_Vp*ivYqGlLwNTe;yS-rOYw(Z{y+UaY*anJ&bhsNMr zdU5btd~_${(_^~==MN19Cx?ZV$wHq+#L-H7_`K{hk^x|w`!(=^v)`^N&0mXgae;u1 zeGAL{-gG&6vS=LG>z{LUJmh94A~qOOU~80xvU8K5KahKhn&IjZdOE(wj86je`$k2b znvt{rKBY4nCdiUiaM<@#O|PUD54;!b_DC!O4B5WiQLkkYvMuEQ(*oS|dl&VPi`q#B zuGA(r$$;D)b{rYKPpduQ0%?%l)abj*Ir{`tr?u!CWF@ZNzQfk|E&o?`J3OuZnFQWF zQ|JgAM$r4Z*S0VCA4}&i=#N(Q0%5#*^>>?k+yVRisqm=GL@_p z%m2`bS$d0(ECJmey2nd>m*d7)j_|gc1EO<|fy_j=cgVG?Na6vD%CEL;5V}nzXrb=J z)xcs+oDi%H?$(EjKAxgVk}Ok@Anu%&Vj>6}n)EG{fyHXBHe>E>UwP`^2`+EobBPUe ztb)wp^;7T6hMfq}GO_7ylFeT00YjC+dFR;x?RMN<6BYITL|jvjEty}LwPKVg3hfs@ z8}f{N%I>y{HR_Sax-@La@`^pEDqy~JR*FGSz}h1rx2%|q0JfjU{?#n10nvS{^HWF#*g3H_;vIlRV{kaw>v zZAhXjr_GIA{l}9pP`Z?PHJFzR)|3_5ph)kwDSG-t1Rn&tyTVMCbXtwf9N%9mOykwshD`O^+|QP zsiUf#(95I|Y@WsRSQl1e<1PxYn{}#~WX&OGwQ<*+2WS z!9Sdy`g*LCXArhjW3U@#OMYrl^fzu9A?vS3owjnv*lvE4ixadJ6B3R-=etILgw)<& zh&#ju_A57cT`)Wkxm|_;;*r-jz}s4-MPb7kII=`(ZfWMneUnou`#|;Cu~`c1s64g& zUBlhPl7ccyk&3Ng$V;CBq~4d)OCDB)y8fc>0v_ilbJaa?NVyUNO^W|rk*A(+oA9Q8 znRhh)zj6?;=CQdiwFWdE+p+Z`aXs+=D8lT{6n_Nqw&0_^p}vU7!56zo)*3b3afW|- z`Z+{$Z=bxa_bXh^uHyOIHa%WH(IbE>CDz2_FM?p=R+l=|RB5`XIxF&lHh9cF_hHyI z1i)WR;j2-M;8Z?PmvP%QpD~$qj8&~gIj>hag>dD8?rNblUfV$QrzU;whJkQv4m!?^?|&PBL>_S*6tqDHk_u`vY1HBkLa`e^8%4EENq4KBPhjy;Do z_D&A350z6kEtqD6np}0c!-P!7^&msYQj>w4@iUhL}iFzi@Y-B^M|VCZ~SJ!7)9D+T#lM7dsgzxg zDF<35NplBsh^o*GJsVQk-IAP|l;|uqC@rS?s|6oPjDuyYpA9X3s65mu_}CM%w3(v1 z*i0P{mk;<9r$jrq0)cU$(hRCE+lqe_#gNEd`{hpm2XbvdOKe+l{#NVA7-;YKh--Cp z_XE1ODTlg2SFgMwNx^*K0<1Y6XvR)9&zzSw(7z4wc8NUVj2#P_Sq20=|Cbh09(pQffR{hX4KeHJb(rhb#Li<%? zjVO_VT3MS=*n2nSSQrCds@c4xJ`J`~y7ICOQ7wkSkN+~Q`e>f3Yg{m2VJ)P-FPJ2r z>Z!>*;&1zn{Nc(~_i~!QH(C5DYkxJ}P!$<40Aa6H`G)r_iVaZK`ujqpYA@qEMFSaD z)t+34f!lp>%^%~z{-Ur9JkDzeTpK7QWei@5#<^%rYezZ*pg?t`zsw(W8|yCcz&z}I z#wwS==;i8if+fVFt(|LK@T&?a66SQ{XBVse%T>)v!8z8d62FBto@XY|n`fxbmPK}Q zYbrohy7^5^#Lxj#)G#yiyG1u)y*19WxHI#9*GVA$RS8#8(EuC6q|bVbIz7M77>m4n zo^|04H{0W6r@@AN-F<_4CE4{;$KKu{)M{)Tvi#(!DgR*5`KGW&7K z?FY6x=ibn2%zlaGm!BTWOCY+4sUB;33V_frPL675`FVpW{v|Mc9gif-~ z=|q-!R*5GN{!jzxW7P^w&KP4KsApk$8AJaqUx{tlW#jtR0mnHAZB41>4NL;?sGfO{ z;_C^#^G6~9nj<&UJ+XSZ?bS=&xizDc_8Ru7Hf^5bIS-|XX_FqSQSRs(*Cb3mV#VlNh^HFSaOufAJF5ZKP;qp7ZwDw+53wD64m4Uww(LJ^MrpG_0uURI@y2`4;-D= zbzSBoKm3|_FW(`J$<5Vzqdi)+w(_pmxjf38!)to*>9Q9nM|`LPJ~PyE|FWaZdJt%! z|N1Os`#K5Q&%X;O^lT5sG&I-Y_psKaDRZ%H@Yel|+Upz?u}p|a`sevRpdaL? z*8gT!z0%3oL(O)qO6Cqa>5m6B@^MeyTh@NC_>_KFJwWmy>j!!b+^A zsUKgN&jP8$k;w_ zR0cAgWUjou6wku6Ha3*ULJbRA_Q1`X)0gTUD01QIBGc2FEIKuqbIu>*K>GD^k)>yU zRV0%jybkL1HwnKr+P+6HB;y(8-jS2mu52%f*}$mgI1`Gmlhb)N4zlIViswgr5|W3V zjoQzJo|%Mi%~K|bMbp=b6Cz*FA+Dk>M6UHqn%`jv;mWT!v8=&6bziApc>JFcwI0GG zR!~*p5pcjpw=J8ca-d5@og#tE-L{CA0m1hYES1dkV>zH?EW&NOdZNPrLDc!% zn~XOrW!>27l7g{0-WVu{)l-(*6&Av>5^Tqf9iXO1zldSox0jMNG-AKjAF;HpS>%`+ zaQhkb7nUz7bqJaK)7Q}O;gJR_F0uc@ZKWYW*YW6QnyaBq#I2B}GZ^IbilojS?Hd?J zGvKV!#QVvFZ&ha@@k(dWY>U|kB{Z&Ve49F?n%v`sDlNLPukv&YRg$V{Iz9Z+r8VXn zx%KM|>OSZ=yfB6n@lpxMVL)yzGE92SgtwW}-c`2&N9hHety0usb%()d(ulsKq*RRo z418t{W1P#D0ha}li`Zymf-K%FSP}i&XldVlwhkhNkHnzAHMuPdCy=b@L~Xw6LyotCve^)q4ByM-Glk9)Kx(? zm4~*B$lJeZHyoFIE?LW^D86n zvCN5q$VW8fBDZ>1?GaKRHzDzgLAQ5|&)KDI84=Ngb-g&eXoRK)2+W%^ZY|uJ0yxJz zPbd$_!^k;_28vFLfBf;Xh`}n>*01~FHsMDDW!lcO9~L@!V<({lR2WqOE)p<4!MY{T zQ)S`vL%~Tb?%Dm0_SSoHvH5|seHg7<*6*@$RcK&0Q^#X!%aWHztPbWiwD{cvZTFk~ z={eNPyZu%-58cNV!u#jX>?IigW%vWITyowwr!#)8j@NKnCNfOGQ~gD|c}}K!Zr5Yp ztuu|;gLoJyN%0v$e&g3yH>@_N^6Q@;l0p~?&#?%2K{fz}(+*h!s;U>0F^}G0{qU_f z&qhCS%!yH*1u>r;_NMW@q*^2d_{33_Oc0T#9_3Ct4weE)>9SEeNx21bq-V~Ie~jws z;b`|`&wqnUY2 zZsGfXsbjc7R4{S2&Fwiw;sO!q1yLd5XQ<1Py9D0lj}1SU5y^ARf-mx00Ehbdz_yae zztJ-yEei*D+4@u@6t|#o{N?<&-+57%*_s~iBq#*IJg|JrrHr8@;ym)>@F58uE&R)w z{61aRQ=bTA!Rz#{CEQ0F_iJ1w0P?}&YVr#z*|h{o#z`JpERSH&_u~0$ZLm zH?0jdy#3XG>WErn4;mIP25V$BljICbluS4uR)gIgqw$~?PQz04!3!_9^|&&Com~`9kZ!jE%ph^ z3|+^@f7@`d-%%SQx?7fJDeB$*hSN!=zvXDzUSPm`e9f?=0m%ij0QjxGy=4TABf(TY zTIH#u4Yj5borD6o;^$FskXfwiE1UWr5w77_E9|3`L#k5Ib(Sw!L)qVo787qPYFS3q zck`F(LfG#^E0n)F_cT1?1YfL}f8Gc(ry}u>RhX$i8@}Y@t+9jXTwogE^swZ^Z^c`r z?(mHT5OWAO+g7+EP^!oBKwRY zW$kK^*CBfmU4@zkJ2E5PeP8atYJJs<;t^1^6lI@HX>}8$>+iw(kj@9U3sSC;f)p4; zBbu+}y&fF?1~YVZ=HZ0)D`tVFSi$@5)zI|+`W#cme}FE+>`u&uhPOC@cgrV7xkoqI zkgx8?gt>@yiuslLOWz#i5RCkoI?US7{{CN-6@i5(wQ-+rjo#+ za$FwNqwJFYCSvj9@0O18(8eS9bfvO9PUX`o$-Lv@H2$NXvQIRx*1rgjcvxxQ+H?qm zb~g4Xcgw#0^E~4cI14F@mh}r{8KE1|>dXL*W`t>41Ag&y)6c*i1VQtQH6MtbC^%^&38794# zKU?2J==0q`PT%&6tEkS3*8q*U#DNOqozev^8E^`SFBT=@vryP5=y59ih`147LvVP* zgf3Tk<^TbU(6rbv*VFUph7(fHYphD?+n{z;&_V~OrdO$o5{B$=73xo!GZX{eV@=-D zly(`=1s~0c#a?~F4h=6l=Y9Da<`$*W^AT06)FL>ky?8>k*cf*IclXylEtO|Wkp$k; zj3Z=5q@w`lMtFA5(cjVQ|4PT~q2Ru=?96}SH0#|FXh=Mv`ba)BE@IcF{dE}Yf}y*i zJVIe7Sbkx@JV{T4;aI+G=!Xb__CNjXA`~g87`&ajP!^%k+2!oE)Z6sPM;uUvf?wyH zZ)SP6`&{DK8e-+a&PY&s=SM+Aj!wGSYZeeBB(D?@S27Z zlg%d9(c7?A21&7B}cwXl(mYjfDRiID4cuhw3^cGb7WVfUV_z9ZGKh{ z2?Xkbev0LX+4S*0xwKX20@pjTwTakVII`q?_|9&NPmEz8{g$r(qGvGO4(>Uwto57O zp&l$myPxPbQ)QpscW>Qc+{GQ)1w2`b8A8|0anTq|-oBz2*<0^jH(t_$qWqoSpD?Wr zmT2Kzb_d1V;(x-kzC4SV#P+LF%@pH&Ur{CmK2{$q66xwp-|K#>^81n!`3m8L!%Xa~ zJDDB|;%=~Ulw_*SQQ+5#o2A8=UqH#65yMLUfOlwh8R(etDvQ$$D3|!0@>991;3OiEzX#OSy8n$! z-zs|ZkEU-N3pfH&Jjf1aJ2&!UM|~#pM~@%=bds-EFC{bwSA=jt_R+h>}E? z(?5CHFD@+qa*MYG#BeOg7CH|9-W6nV4;*&Lg-ALRL-PkWBm3IyaiGCVdfewPX7@VM z*BR*H2r}873`$hB?RR4|a5?>bL=yvCrMWu8@?9F9ft6`Wi=%~IIhmp?BTcze^JjHG z5W(7{hL77)RtboQO9STmf``>;Lo}c8>aTm!`SQo2e#&8OC15Uvcm!AM7VXM=eba*l zxpK%J0`%Jr7I0rG;&@Uw0aVa%)T%&5xp2&GW^6kPX!qHzzkdeWTF}2qt!FK_gx9Th zw*<0+D^WL)KGzQp_VSNO9gC4-gdrI?yxF5knLN;Gr3>9IBDzrgV91(&yBx2dprO6` z8J3(L-TOl2(ig2T3C_V7X-JvSwK(~R$Cz9KK+J#NzAWH7ZVb zFOJr0x&&rP;!9`2dbz1Db_TK}m~7QC3A)z>&QMNl)BTeq?WCg+z8_|u+k2MVZdPa! znvk+DHRR&m0jJ@b=1b5Z>TXK!RJf z%04(RbizzY+KXJR>Z7~4IN?YA;W|Ig){_a`-Dl?ebu)pzvB_orv2GwW6n^lb86TDM z6?Aa5Aa~Y4tk^WiL%*+I$rKll%*b|y?AEz05|8vUiyc)?;)j?&B=2sS%;xzE?V9s1 z&-AuXBw)Yvdx77BbE)YA{+|7^8y)8w^gyoG)GNgN*RC2Y)B}Bnu`F-*{e>II(&E~N zUkI^>QK4h;9wP5JE3z^pg!bx$>>OixfV+s!5yQ5b)O9haMOX5O6Q?eEc$7blDq9?Y69KAn`qg+3hVtfOBP#5cPRlg;$1ajZ>i@~m9;PYSsZ9!|JF>K|lpRrl+-608l z;d&=L3zUcK96;$A;>wkqBVV{_oRo8pga8~d{Zvzm<#dd`|E*t)Dzuxv6L6RUj82zd+FJdzQ&WVz_)FGp zME6{~kyGyO`08{>05;snK@_N_W;{6otfuC)dZ3|thKqz7@Z!zTsZIKVebvqmdVE#~ zd;Q8pSfy@hPH2ZiS9$8d)1szSOA-RI`gB;6d~XY9Vwtu7ieb2q3|JTb0GmOM1UbgW@3VF#={M7=x=XLIq9-_@3ypSINYTPkW#@p z-xGBv3j_rIPYW>9vD~98h!tr#i>Z=fTRE+G_358>?^Cm%V;-ZMVsRBwCR^Q&qOmMq zl)@q(W>laE$QJWp>0<14wu!9m&*}T7jzafT{#O6$-)igL8({W6u4cuo&-9V~_ySt| z>YqH~cKxX}`|~;Iuab!51CRVuI7U>b)JK=xiA5kEa+ih@grgZR(&kT%s9HV7oBv-W zWr^y;XW@0fYIVh1Ak#oo$jXO9TrnDdHc%IQVu~;fG1B*(XD2$oeB{E6oMZ;PX}`RZ z6J|9GTrpsAQKp#RMgv>IgrVD!LlH?x9Z_aOSxr}QSD+*=KTRZ>5}Xd*XT*`v4}W_& z4za$QUGVBEKMUzD+t(xixPWm)C!p>kvz@rktf_;gDbS{#2mHBFG|(dZ*Zgi^eY>ng zSZW%}lkF1394Qq!=V)Qri`9MsET2@3XNgHS^V3_9PjsOTY)^d)#Hsz<&w~n&1Fu~z zW};i49Xl81C6LA`LqZ7Dm7GzW7%ud&X?r znK2`(N>@7J6S7u!z3F9At3p_?D(9o;?C?ohgKaB!k&L&E$g9Qr<2GmA`2Q#lu(?Y} zw^~MI8usz$eUaI6_Q{4Vr2(wHW)1l3Y0(1S%B2iVhGTC2QWCx$9xM4r`#G_%0KV;K zCMIwFSmx;B6mY$Zx{-Msxz){SsPgb9PgUZJof&oTahPF87uV&{cPHx4mrwLhqthi9 z2oP;P#-pJoU*yxp;YZ~M~4!mfzN z2L4J`sAIkRV}!bcmJ|ZFVmkwRZIdBD3g;E4ddTG1@u59cj1f7tM}GI z%QNql`JlqG%~PDHg#Y-_!*gkuspfh;*lK-4qD)-J=OOqb+&$Q&ewmIprn>VvTG0&TR>+EJ|vtm`iNkXw>^EIjvI@OS~ibWxp)J=+}E zmffrV*QR@Y;f4Xa2Stiv0VlKl`A}ip?{He6?gbP=^Bw-BtANOt;Q5hOsAHV{*8atz zKt4B6)qusz@jrxVJDZEID9ih`b-Q>As*cIMUe~dhmp77LZ#AW=q1_GTb_!a=?t;kC zZNzFiF;V^l;o0&qW%~tUyRwF9-c2 z(o*!6HcXab!CZdB@})OGZMS{?uBY6>DYV5nIrbP;@dN3nBD^`!(uZ!Xhm2ujVV?+sqT!i zYsom`xF`1z{Z{n4^rlD&Vm^u>uT8qg3w%G;B!RqJng+gP=Zw!nyrG-1s$jCG&SN8& zQ81ZxtE&?a60twoxehCScT_Pk^S!oTyD%0s>OL5;?p{SQ`a-JY0(3>~e{wrr96Dft zIWKqVN=Jnam>o1CoyaelCbfbMqKInv#DPBDF?#Ed8~PwXJ=SS%FLB?8N@C3+w+f8J zrp8?*lUVFdnp2Yr*@=|E>?0IY&T;+G^{kHdsT$XQv2fRwe^FmJyU6i)uZEN$>5z{< zp5m#8YNxZ8>&uWuBu}X*++EmYtP|)KlZ6BWgD3G2`$Xy zHy_-Kbl(|Nh+`?MVn?LOtrFNUh!D1ss~XVaZ*)`}U*Js@AXZEvb*l6P=?3~v{cmG6 zGMY|edi$_HL}_G1UivcV(+b`(j&B> z@d+Ds;(Lo;;@j$-Gu5y&v0=OA`ooDJ2TKsy1~hb=Car$LLwQZ#a)}+C8%>WKOJapb zPi!IdB?_V0kvgUHAZqYzQ5{ZYB0B>7dZf9Rh59(hSy|+~9gBcg)60{$?{0c$p@M0( zQ>6bCWbd%Eocr^|ja5`za;NdIB14xM*Vc)^&`gGQ+~#o9Y)N;5j44xs#GTaJqnjib z(||#CkYffvo_$qn=6j28sNovgT9#&IOn3&rvZk^TE+L>rA+RV@uwpNoye=guPM-E& z(jS5@OiFtGEU}+%c(HthbZ@3y9UQi#W<%y=OulyDDVy%?k+I(Zd4@88`KF=7m|k=TLo+ND~l#+Vo2Vv+~0ofi?9t!u1hs_zO>sHg*VtL6NaV zNSXdP<-_wGne34zAQ_*yd4@p%-N`OPx2Lu|A50x(GmIIx%^IKP8{)+KMI%#DEBiGz zDL3x)eTmjZ?|pDL;25^1(`E8*y3#>X-`U#r+LB-C@K=)rNqPex_qEOSL5}7S<5mg@ zWI=^-0q@+&REfQ|dOU-9><(6XYfg^Zb{?Jfi5_x@?b8n7kbE5?hPPrXmMhc>35dYW zTjui*@=h)AN;!=VcB2hrQ}@D>SoIjuYblM0=V{t4l=2p7VMZj0EXDcmRl4uulOMCF zXqJr#6YQ|-nB)OzAyc6<=^r zyc||ecHei2t2|NaICp#Mh_g)J5a)x4nYo4>OZm)3mO91VCk6ATN5nJ2IsZI`AtS6n zCyv&rpx-a$Zhbn*-_B)EHg}?aDx`*8h3Vs3`?*LA+de(pwyx3zL1i4cM@XhC*l*}7 z(olG}G2p#Nn8jls|DL=9TXoWnNxXsfcKZXI8GHnf zw1>Si3;KO&e0rcc8N@(wfEkDG&22z|3s`1^jQzL-f`|@9t0qm#e^eVOdYGd(HMLug0QSRtz?$7HDxi5V+4(gAXO$hn+nAAWOVQ-z@>>oCpM&F_;8o z=~=msbMRLdi>(%uP@Te?5latsv4+)&Z9<4X6b;Jpl=(&U{i_qoJ3>aSp6{`$dl(KG zA=f`5JP{+0wy4Wca)&a{L(KmCA`R7F3KR^{g4VE)g#W&3H+#`D+DCV2*Dv9@r2{O3 zc;}2l7YiL;0T*RPolJ0bhVoexlegJZk@PR_XX)Zh|r;4@b?m2fA?Bcqx+OZGn=rIT?=g9HVBCtKE zYkbz4aY$gousn&6x`TAvOda_5(W7MUG1u0haTl--Uk6kv1A%Z(oS2~D?`;w*h|0^z zqVa3yeZ~%;bGk)gqZWPFsEwQKfOsBXk1&*27|iPjzoT?wS9B4nZH))_Q8p!Wssb2D zcr@XX@h+P;ZPT=XoX#w?dE2O4!PTE~zCLf$-o)Wr1@K1;_}72T^A>eW3|G!`Nrw zMS{mEHJHXU&{bWFV8!e5W9Z$E{Y3(BJIFEMcM?#oge6Cx7|n3uzS4q`<5Yn*cIQRu z8`Ray>m*M^M!u=XvM1Z6UYeV356A!pqYhzmLGj9~5H|$ajco`>#7QGqiubBP)MxFJ zT(xlqh(eYeGW(r&rJLK;T{Qp!;awG9ZP$kbV9=1lKOnOwK|MwM(6(q3$Z02PW>JTI z1bS1JbcVDH{~#P9^P(EH8#=kQB*M9j;>3I%?InDbjLLJcBon~k&B3*X!nD+UMhhWZ zSHtVKHLDUy3+#9Xbn+$YEd#3PIWTVPnX0=q!z2y443CJ?r62-7H%Tyt3&omf@s1ci zc!ndK=`ng?Q@jNL0v&k4Ls1&RxJ`Jb3GBg#HmPgeoLP{a5~VE2|f!BTGP<>uID1pnon%IGo7Y3g+j6G{Fa`_DZSmh=K7D2roX zDBIPOEsL)C7Rf!ptcyGm`b3UGVg|>F#j3vePpjEurh*#I;7#6)!x7sK&F$H;hXO;P zBg4%Fx>Hh+%X+ZT>YWGoy-Pmpo*K-)($3LejDMJ#Qo|6QrrXU$?C_@!mg__^k0jg} zr)nb>li3lA6p;pOtGq;x&lMn_o4im8@?{GY$0z$WhHT$&pIiYlilH1$8gvz;nSZ%T5I8}6^xs}eTy8f^c zr@PFt1lgm>RxiW+j={0eC-{@HYPu2i6qDkO>Jl+ov)zk9kP4R%J7F3z*QsfjeTsQU zA2ob_SG|FRSsA>N_k9I{;V$P-UL;8)C z|7#GCnp3a1xfDq3Zjn%mZN}%MSN29T-;}RCzEtZL@S+4 z&ULDC#ynOs26D{L@CQhwcVbJI0rHn#>Cic^f7I*+f^G`w9c82G+uIRdugIG z^LH%6@kH8*#?U1e4`{&{TO^In{L2UYX$B^aNInR;XJe`GZXusKzB&X ztjQl~A3(+y@E_qHJVm{vdWb|2S(YO^k&Ay?;7q)t^EmW>F9p@E54AvuHcWSAaZw- zKq4B^BOAMV*gsP3cb758b2=AZa}pj*GjclfQ;B%0Dd)X)O*Fr-F~^*>iMgB*QtfpJ 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 0) { - ostd::String tmpStr1 = ""; - ostd::String tmpStr2 = ""; + String tmpStr1 = ""; + String tmpStr2 = ""; bool found = false; - for (int32_t i = 0; i < text.len(); i++) + for (i32 i = 0; i < text.len(); i++) { tmpStr2 = ""; char c = text[i]; tmpStr1 += c; - int32_t strWidth1 = parent.m_gfx->getStringDimensions(tmpStr1, parent.m_fontSize).x; + i32 strWidth1 = parent.m_gfx->getStringDimensions(tmpStr1, parent.m_fontSize).x; if (relativePosition.x > strWidth1) continue; found = true; tmpStr2 = tmpStr1.new_substr(0, tmpStr1.len() - 1); - int32_t strWidth2 = (tmpStr2.len() > 0 ? parent.m_gfx->getStringDimensions(tmpStr2, parent.m_fontSize).x : 0); - int32_t d1 = (int32_t)std::abs(relativePosition.x - strWidth2); - int32_t d2 = (int32_t)std::abs(strWidth1 - relativePosition.x); + i32 strWidth2 = (tmpStr2.len() > 0 ? parent.m_gfx->getStringDimensions(tmpStr2, parent.m_fontSize).x : 0); + i32 d1 = (i32)std::abs(relativePosition.x - strWidth2); + i32 d2 = (i32)std::abs(strWidth1 - relativePosition.x); if (d1 > d2) parent.m_cursorPosition = tmpStr1.len(); else @@ -196,7 +196,7 @@ namespace ogfx - RawTextInput& RawTextInput::create(const ostd::Vec2& position, const ostd::Vec2& size, const ostd::String& name) + RawTextInput& RawTextInput::create(const ostd::Vec2& position, const ostd::Vec2& size, const String& name) { setPosition(position); setSize(size); @@ -212,15 +212,15 @@ namespace ogfx void RawTextInput::render(ogfx::BasicRenderer2D& gfx) { m_gfx = &gfx; - double text_size_scale = 0.66666666666666; + f64 text_size_scale = 0.66666666666666; m_paddingX = (4.0f * geth()) / 30.0f; - m_fontSize = (int32_t)(geth() * 0.66); - float cursor_height_scale = 0.75f; + m_fontSize = (i32)(geth() * 0.66); + f32 cursor_height_scale = 0.75f; ostd::IPoint strSize { 0, 0 }; if (m_cursorPosition > 0 && m_text != "") { - ostd::String s1 = m_text.new_substr(0, m_cursorPosition); + String s1 = m_text.new_substr(0, m_cursorPosition); strSize = gfx.getStringDimensions(s1, m_fontSize); } @@ -229,7 +229,7 @@ namespace ogfx gfx.drawString(m_text, getPosition() + ostd::Vec2 { m_paddingX + m_theme.extraPaddingLeft, m_paddingX + m_theme.extraPaddingTop}, m_theme.textColor, m_fontSize); if (m_cursorState || !m_theme.cursorBlink) - gfx.fillRect({ getx() + m_paddingX + m_theme.extraPaddingLeft + strSize.x - 1, gety() + m_paddingX + m_theme.extraPaddingTop, (float)m_theme.cursorWidth, (float)m_fontSize * cursor_height_scale }, m_theme.cursorColor); + gfx.fillRect({ getx() + m_paddingX + m_theme.extraPaddingLeft + strSize.x - 1, gety() + m_paddingX + m_theme.extraPaddingTop, (f32)m_theme.cursorWidth, (f32)m_fontSize * cursor_height_scale }, m_theme.cursorColor); onRender(gfx); } @@ -254,19 +254,19 @@ namespace ogfx onFixedUpdate(); } - void RawTextInput::setText(const ostd::String& text) + void RawTextInput::setText(const String& text) { m_text = text; m_cursorPosition = m_text.len(); } - void RawTextInput::appendText(const ostd::String& text) + void RawTextInput::appendText(const String& text) { m_text.add(text); m_cursorPosition = m_text.len(); } - void RawTextInput::setCursorPosition(uint16_t cursorPos) + void RawTextInput::setCursorPosition(u16 cursorPos) { if (cursorPos > m_text.len()) cursorPos = m_text.len(); diff --git a/src/ogfx/gui/RawTextInput.hpp b/src/ogfx/gui/RawTextInput.hpp index 76074e3..7713f34 100644 --- a/src/ogfx/gui/RawTextInput.hpp +++ b/src/ogfx/gui/RawTextInput.hpp @@ -55,9 +55,9 @@ namespace ogfx ostd::Color backgroundColor { 0, 0, 0, 0 }; ostd::Color cursorColor { 0, 0, 0, 0 }; - uint8_t cursorWidth { 0 }; - uint8_t extraPaddingTop { 0 }; - uint8_t extraPaddingLeft { 0 }; + u8 cursorWidth { 0 }; + u8 extraPaddingTop { 0 }; + u8 extraPaddingLeft { 0 }; bool cursorBlink { true }; ostd::Counter cursorBlinkCounter { 30 }; @@ -95,7 +95,7 @@ namespace ogfx public: class ActionEventData : public ostd::BaseObject { public: - inline ActionEventData(RawTextInput& _sender, const ostd::String& _senderName, eActionEventType _eventType, ostd::BaseObject& _userData) : + inline ActionEventData(RawTextInput& _sender, const String& _senderName, eActionEventType _eventType, ostd::BaseObject& _userData) : sender(_sender), senderName(_senderName), eventType(_eventType), @@ -107,15 +107,15 @@ namespace ogfx public: RawTextInput& sender; - ostd::String senderName { "" }; + String senderName { "" }; eActionEventType eventType { eActionEventType::None }; ostd::BaseObject& userData { ostd::BaseObject::InvalidRef() }; }; public: inline RawTextInput(void) { create({ 0.0f, 0.0f }, { 200.0f, 30.0f }, "UnnamedRawTextInput"); } - inline RawTextInput(const ostd::Vec2& position, const ostd::Vec2& size, const ostd::String& name) { create(position, size, name); } - RawTextInput& create(const ostd::Vec2& position, const ostd::Vec2& size, const ostd::String& name); + inline RawTextInput(const ostd::Vec2& position, const ostd::Vec2& size, const String& name) { create(position, size, name); } + RawTextInput& create(const ostd::Vec2& position, const ostd::Vec2& size, const String& name); virtual void render(ogfx::BasicRenderer2D& gfx); virtual void update(void); @@ -125,47 +125,47 @@ namespace ogfx virtual inline void onUpdate(void) { } virtual inline void onFixedUpdate(void) { } - void setText(const ostd::String& text); - void appendText(const ostd::String& text); - void setCursorPosition(uint16_t cursorPos); + void setText(const String& text); + void appendText(const String& text); + void setCursorPosition(u16 cursorPos); void setTheme(Theme theme); inline void setEventListener(EventListener& evtl) { m_eventListener = &evtl; } inline void setCharacterFilter(CharacterFilter& chrf) { m_charFilter = &chrf; } - inline void setName(const ostd::String& name) { m_name = name; } + inline void setName(const String& name) { m_name = name; } inline EventListener* getEventListener(void) const { return m_eventListener; } inline CharacterFilter* getCharacterFilter(void) const { return m_charFilter; } - inline ostd::String getText(void) const { return m_text; } - inline uint16_t getCursorPosition(void) const { return m_cursorPosition; } + inline String getText(void) const { return m_text; } + inline u16 getCursorPosition(void) const { return m_cursorPosition; } inline Theme& getTheme(void) { return m_theme; } - inline ostd::String getName(void) const { return m_name; } + inline String getName(void) const { return m_name; } inline bool isMouseInside(void) const { return m_mouseInside; } private: EventListener* m_eventListener { nullptr }; CharacterFilter* m_charFilter { nullptr }; ogfx::BasicRenderer2D* m_gfx { nullptr }; - int32_t m_fontSize { 20 }; - float m_paddingX { 0 }; + i32 m_fontSize { 20 }; + f32 m_paddingX { 0 }; protected: - ostd::String m_name { "" }; + String m_name { "" }; - ostd::String m_text { "" }; - uint16_t m_cursorPosition { 0 }; + String m_text { "" }; + u16 m_cursorPosition { 0 }; bool m_cursorState { true }; ostd::Counter m_keyRepeatCounter { 1 }; char m_lastChar { 0 }; - int32_t m_lastKeyCode { 0 }; + i32 m_lastKeyCode { 0 }; Theme m_theme; bool m_mouseInside { false }; public: - inline static const uint32_t actionEventSignalID { ostd::SignalHandler::newCustomSignal(11400) }; + inline static const u32 actionEventSignalID { ostd::SignalHandler::newCustomSignal(11400) }; }; class RawTextInputEventListener : public RawTextInput::EventListener { diff --git a/src/ogfx/gui/WidgetManager.cpp b/src/ogfx/gui/WidgetManager.cpp index bc7747c..47d9efc 100644 --- a/src/ogfx/gui/WidgetManager.cpp +++ b/src/ogfx/gui/WidgetManager.cpp @@ -81,10 +81,10 @@ namespace ogfx Widget* next = nullptr; Widget* smallest = nullptr; - int32_t currentTabIndex = (m_focused != nullptr ? m_focused->m_tabIndex : std::numeric_limits::max()); + i32 currentTabIndex = (m_focused != nullptr ? m_focused->m_tabIndex : std::numeric_limits::max()); for (Widget* w : m_widgetList) { - int tab_i = w->m_tabIndex; + i32 tab_i = w->m_tabIndex; if (tab_i < 0) continue; if (!smallest || tab_i < smallest->m_tabIndex) smallest = w; @@ -133,7 +133,7 @@ namespace ogfx void WidgetManager::onMousePressed(const Event& event) { - for (int32_t i = m_widgetList.size() - 1; i >= 0; i--) + for (i32 i = m_widgetList.size() - 1; i >= 0; i--) { Widget* w = m_widgetList[i]; if (w == nullptr) continue; @@ -155,7 +155,7 @@ namespace ogfx m_mousePressedOnWidget->__onMouseReleased(event); // processDragAndDrop(m_mousePressedOnWidget, event); } - for (int32_t i = m_widgetList.size() - 1; i >= 0; i--) + for (i32 i = m_widgetList.size() - 1; i >= 0; i--) { Widget* w = m_widgetList[i]; if (w == nullptr) continue; @@ -173,7 +173,7 @@ namespace ogfx void WidgetManager::onMouseMoved(const Event& event) { - for (int32_t i = m_widgetList.size() - 1; i >= 0; i--) + for (i32 i = m_widgetList.size() - 1; i >= 0; i--) { Widget* w = m_widgetList[i]; if (w == nullptr) continue; @@ -202,7 +202,7 @@ namespace ogfx if (event.isHandled() || w->m_stopEvents) { bool mouseOut = false; - for (int32_t j = i - 1; j >= 0; j--) + for (i32 j = i - 1; j >= 0; j--) { Widget* ww = m_widgetList[j]; if (ww->m_mouseInside) @@ -218,7 +218,7 @@ namespace ogfx void WidgetManager::onMouseScrolled(const Event& event) { - for (int32_t i = m_widgetList.size() - 1; i >= 0; i--) + for (i32 i = m_widgetList.size() - 1; i >= 0; i--) { Widget* w = m_widgetList[i]; if (w == nullptr) continue; @@ -233,7 +233,7 @@ namespace ogfx void WidgetManager::onMouseDragged(const Event& event) { - for (int32_t i = m_widgetList.size() - 1; i >= 0; i--) + for (i32 i = m_widgetList.size() - 1; i >= 0; i--) { Widget* w = m_widgetList[i]; if (w == nullptr) continue; diff --git a/src/ogfx/gui/WidgetManager.hpp b/src/ogfx/gui/WidgetManager.hpp index 1a65a9e..325760b 100644 --- a/src/ogfx/gui/WidgetManager.hpp +++ b/src/ogfx/gui/WidgetManager.hpp @@ -59,7 +59,7 @@ namespace ogfx void onWindowFocused(const Event& event); void onWindowFocusLost(const Event& event); - inline int32_t widgetCount(void) const { return m_widgetList.size(); } + inline i32 widgetCount(void) const { return m_widgetList.size(); } inline WindowCore& getWindow(void) { return m_window; } private: @@ -68,7 +68,7 @@ namespace ogfx private: WindowCore& m_window; Widget& m_owner; - std::vector m_widgetList; + stdvec m_widgetList; Widget* m_focused { nullptr }; bool m_tabNavigationEnabled { true }; Widget* m_mousePressedOnWidget { nullptr }; diff --git a/src/ogfx/gui/Window.cpp b/src/ogfx/gui/Window.cpp index 5f161ac..cac5189 100644 --- a/src/ogfx/gui/Window.cpp +++ b/src/ogfx/gui/Window.cpp @@ -27,7 +27,8 @@ namespace ogfx { const Uint32 REDRAW_EVENT = SDL_RegisterEvents(1); - inline static const ostd::String DefaultThemeStyle = \ + //TODO: Temporary + inline static const String DefaultThemeStyle = \ "window.backgroundColor = Color(#000000FF)\n" \ "label.textColor = Color(#FFFFFFFF)\n" \ "label.backgroundColor = Color(#00000000)\n" \ @@ -69,7 +70,7 @@ namespace ogfx SDLSysten::release(); } - void WindowCore::initialize(int32_t width, int32_t height, const ostd::String& title) + void WindowCore::initialize(i32 width, i32 height, const String& title) { if (m_initialized) return; SDLSysten::acquire(); @@ -158,14 +159,14 @@ namespace ogfx ostd::SignalHandler::emitSignal(ostd::BuiltinSignals::WindowClosed, ostd::Signal::Priority::Normal, *this); } - void WindowCore::setSize(int32_t width, int32_t height) + void WindowCore::setSize(i32 width, i32 height) { if (!isInitialized()) return; SDL_SetWindowSize(m_window, width, height); ostd::SignalHandler::emitSignal(ostd::BuiltinSignals::WindowResized, ostd::Signal::Priority::RealTime); } - void WindowCore::setTitle(const ostd::String& title) + void WindowCore::setTitle(const String& title) { if (!isInitialized()) return; m_title = title; @@ -174,72 +175,72 @@ namespace ogfx void WindowCore::setCursor(eCursor cursor) { - switch (cursor) - { - case eCursor::Default: - SDL_SetCursor(m_cursor_Default); - break; - case eCursor::Text: - SDL_SetCursor(m_cursor_Text); - break; - case eCursor::Wait: - SDL_SetCursor(m_cursor_Wait); - break; - case eCursor::Crosshair: - SDL_SetCursor(m_cursor_Crosshair); - break; - case eCursor::Progress: - SDL_SetCursor(m_cursor_Progress); - break; - case eCursor::NWSE_Resize: - SDL_SetCursor(m_cursor_NWSE_Resize); - break; - case eCursor::NESW_Resize: - SDL_SetCursor(m_cursor_NESW_Resize); - break; - case eCursor::EW_Resize: - SDL_SetCursor(m_cursor_EW_Resize); - break; - case eCursor::NS_Resize: - SDL_SetCursor(m_cursor_NS_Resize); - break; - case eCursor::Move: - SDL_SetCursor(m_cursor_Move); - break; - case eCursor::NotAllowed: - SDL_SetCursor(m_cursor_NotAllowed); - break; - case eCursor::Pointer: - SDL_SetCursor(m_cursor_Pointer); - break; - case eCursor::NW_Resize: - SDL_SetCursor(m_cursor_NW_Resize); - break; - case eCursor::N_Resize: - SDL_SetCursor(m_cursor_N_Resize); - break; - case eCursor::NE_Resize: - SDL_SetCursor(m_cursor_NE_Resize); - break; - case eCursor::E_Resize: - SDL_SetCursor(m_cursor_E_Resize); - break; - case eCursor::SE_Resize: - SDL_SetCursor(m_cursor_SE_Resize); - break; - case eCursor::S_Resize: - SDL_SetCursor(m_cursor_S_Resize); - break; - case eCursor::SW_Resize: - SDL_SetCursor(m_cursor_SW_Resize); - break; - case eCursor::W_Resize: - SDL_SetCursor(m_cursor_W_Resize); - break; - default: - SDL_SetCursor(m_cursor_Default); - break; - } + switch (cursor) + { + case eCursor::Default: + SDL_SetCursor(m_cursor_Default); + break; + case eCursor::Text: + SDL_SetCursor(m_cursor_Text); + break; + case eCursor::Wait: + SDL_SetCursor(m_cursor_Wait); + break; + case eCursor::Crosshair: + SDL_SetCursor(m_cursor_Crosshair); + break; + case eCursor::Progress: + SDL_SetCursor(m_cursor_Progress); + break; + case eCursor::NWSE_Resize: + SDL_SetCursor(m_cursor_NWSE_Resize); + break; + case eCursor::NESW_Resize: + SDL_SetCursor(m_cursor_NESW_Resize); + break; + case eCursor::EW_Resize: + SDL_SetCursor(m_cursor_EW_Resize); + break; + case eCursor::NS_Resize: + SDL_SetCursor(m_cursor_NS_Resize); + break; + case eCursor::Move: + SDL_SetCursor(m_cursor_Move); + break; + case eCursor::NotAllowed: + SDL_SetCursor(m_cursor_NotAllowed); + break; + case eCursor::Pointer: + SDL_SetCursor(m_cursor_Pointer); + break; + case eCursor::NW_Resize: + SDL_SetCursor(m_cursor_NW_Resize); + break; + case eCursor::N_Resize: + SDL_SetCursor(m_cursor_N_Resize); + break; + case eCursor::NE_Resize: + SDL_SetCursor(m_cursor_NE_Resize); + break; + case eCursor::E_Resize: + SDL_SetCursor(m_cursor_E_Resize); + break; + case eCursor::SE_Resize: + SDL_SetCursor(m_cursor_SE_Resize); + break; + case eCursor::S_Resize: + SDL_SetCursor(m_cursor_S_Resize); + break; + case eCursor::SW_Resize: + SDL_SetCursor(m_cursor_SW_Resize); + break; + case eCursor::W_Resize: + SDL_SetCursor(m_cursor_W_Resize); + break; + default: + SDL_SetCursor(m_cursor_Default); + break; + } } void WindowCore::enableResizable(bool enable) @@ -248,7 +249,7 @@ namespace ogfx m_resizeable = enable; } - void WindowCore::setIcon(const ostd::String& iconFilePath) + void WindowCore::setIcon(const String& iconFilePath) { SDL_Surface* appIcon = IMG_Load(iconFilePath); if (appIcon == nullptr) @@ -260,14 +261,14 @@ namespace ogfx SDL_DestroySurface(appIcon); } - void WindowCore::setBlockingEventsRefreshFPS(uint32_t fps) + void WindowCore::setBlockingEventsRefreshFPS(u32 fps) { if (fps == 0 || fps > MaxBlockingEventsFPS) { setBlockingEventsRefreshFPS(DefaultBlockingEventsFPS); return; } - m_blockingEventsDelay = static_cast(std::floor((1.0 / (double)fps) * 1000)); + m_blockingEventsDelay = cast(std::floor((1.0 / (f64)fps) * 1000)); } void WindowCore::requestRedraw(void) @@ -285,8 +286,8 @@ namespace ogfx MouseEventData WindowCore::get_mouse_state(void) { - float mx = 0, my = 0; - uint32_t btn = SDL_GetMouseState(&mx, &my); + f32 mx = 0, my = 0; + u32 btn = SDL_GetMouseState(&mx, &my); MouseEventData::eButton button = MouseEventData::eButton::None; switch (btn) { @@ -403,12 +404,12 @@ namespace ogfx } else if (event.type == SDL_EVENT_KEY_DOWN) { - KeyEventData ked(*this, (int32_t)event.key.key, 0, KeyEventData::eKeyEvent::Pressed); + KeyEventData ked(*this, (i32)event.key.key, 0, KeyEventData::eKeyEvent::Pressed); ostd::SignalHandler::emitSignal(ostd::BuiltinSignals::KeyPressed, ostd::Signal::Priority::RealTime, ked); } else if (event.type == SDL_EVENT_KEY_UP) { - KeyEventData ked(*this, (int32_t)event.key.key, 0, KeyEventData::eKeyEvent::Released); + KeyEventData ked(*this, (i32)event.key.key, 0, KeyEventData::eKeyEvent::Released); ostd::SignalHandler::emitSignal(ostd::BuiltinSignals::KeyReleased, ostd::Signal::Priority::RealTime, ked); } else if (event.type == SDL_EVENT_TEXT_INPUT) @@ -422,26 +423,26 @@ namespace ogfx void WindowCore::__load_default_stylesheet_variables(void) { // Cursors - m_defaultStylesheetVariables["cursor_default"] = { ostd::String("").add(static_cast(eCursor::Default)), true }; - m_defaultStylesheetVariables["cursor_text"] = { ostd::String("").add(static_cast(eCursor::Text)), true }; - m_defaultStylesheetVariables["cursor_wait"] = { ostd::String("").add(static_cast(eCursor::Wait)), true }; - m_defaultStylesheetVariables["cursor_crosshair"] = { ostd::String("").add(static_cast(eCursor::Crosshair)), true }; - m_defaultStylesheetVariables["cursor_progress"] = { ostd::String("").add(static_cast(eCursor::Progress)), true }; - m_defaultStylesheetVariables["cursor_nwse_resize"] = { ostd::String("").add(static_cast(eCursor::NWSE_Resize)), true }; - m_defaultStylesheetVariables["cursor_nesw_resize"] = { ostd::String("").add(static_cast(eCursor::NESW_Resize)), true }; - m_defaultStylesheetVariables["cursor_ew_resize"] = { ostd::String("").add(static_cast(eCursor::EW_Resize)), true }; - m_defaultStylesheetVariables["cursor_ns_resize"] = { ostd::String("").add(static_cast(eCursor::NS_Resize)), true }; - m_defaultStylesheetVariables["cursor_move"] = { ostd::String("").add(static_cast(eCursor::Move)), true }; - m_defaultStylesheetVariables["cursor_no_allowed"] = { ostd::String("").add(static_cast(eCursor::NotAllowed)), true }; - m_defaultStylesheetVariables["cursor_pointer"] = { ostd::String("").add(static_cast(eCursor::Pointer)), true }; - m_defaultStylesheetVariables["cursor_nw_resize"] = { ostd::String("").add(static_cast(eCursor::NW_Resize)), true }; - m_defaultStylesheetVariables["cursor_n_resize"] = { ostd::String("").add(static_cast(eCursor::N_Resize)), true }; - m_defaultStylesheetVariables["cursor_ne_resize"] = { ostd::String("").add(static_cast(eCursor::NE_Resize)), true }; - m_defaultStylesheetVariables["cursor_e_resize"] = { ostd::String("").add(static_cast(eCursor::E_Resize)), true }; - m_defaultStylesheetVariables["cursor_se_resize"] = { ostd::String("").add(static_cast(eCursor::SE_Resize)), true }; - m_defaultStylesheetVariables["cursor_s_resize"] = { ostd::String("").add(static_cast(eCursor::S_Resize)), true }; - m_defaultStylesheetVariables["cursor_sw_resize"] = { ostd::String("").add(static_cast(eCursor::SW_Resize)), true }; - m_defaultStylesheetVariables["cursor_w_resize"] = { ostd::String("").add(static_cast(eCursor::W_Resize)), true }; + m_defaultStylesheetVariables["cursor_default"] = { String("").add(cast(eCursor::Default)), true }; + m_defaultStylesheetVariables["cursor_text"] = { String("").add(cast(eCursor::Text)), true }; + m_defaultStylesheetVariables["cursor_wait"] = { String("").add(cast(eCursor::Wait)), true }; + m_defaultStylesheetVariables["cursor_crosshair"] = { String("").add(cast(eCursor::Crosshair)), true }; + m_defaultStylesheetVariables["cursor_progress"] = { String("").add(cast(eCursor::Progress)), true }; + m_defaultStylesheetVariables["cursor_nwse_resize"] = { String("").add(cast(eCursor::NWSE_Resize)), true }; + m_defaultStylesheetVariables["cursor_nesw_resize"] = { String("").add(cast(eCursor::NESW_Resize)), true }; + m_defaultStylesheetVariables["cursor_ew_resize"] = { String("").add(cast(eCursor::EW_Resize)), true }; + m_defaultStylesheetVariables["cursor_ns_resize"] = { String("").add(cast(eCursor::NS_Resize)), true }; + m_defaultStylesheetVariables["cursor_move"] = { String("").add(cast(eCursor::Move)), true }; + m_defaultStylesheetVariables["cursor_no_allowed"] = { String("").add(cast(eCursor::NotAllowed)), true }; + m_defaultStylesheetVariables["cursor_pointer"] = { String("").add(cast(eCursor::Pointer)), true }; + m_defaultStylesheetVariables["cursor_nw_resize"] = { String("").add(cast(eCursor::NW_Resize)), true }; + m_defaultStylesheetVariables["cursor_n_resize"] = { String("").add(cast(eCursor::N_Resize)), true }; + m_defaultStylesheetVariables["cursor_ne_resize"] = { String("").add(cast(eCursor::NE_Resize)), true }; + m_defaultStylesheetVariables["cursor_e_resize"] = { String("").add(cast(eCursor::E_Resize)), true }; + m_defaultStylesheetVariables["cursor_se_resize"] = { String("").add(cast(eCursor::SE_Resize)), true }; + m_defaultStylesheetVariables["cursor_s_resize"] = { String("").add(cast(eCursor::S_Resize)), true }; + m_defaultStylesheetVariables["cursor_sw_resize"] = { String("").add(cast(eCursor::SW_Resize)), true }; + m_defaultStylesheetVariables["cursor_w_resize"] = { String("").add(cast(eCursor::W_Resize)), true }; // Colors m_defaultStylesheetVariables["color_transparent"] = { "Color(" + ostd::Colors::Transparent.hexString(true, "#") + ")", true }; @@ -499,18 +500,18 @@ namespace ogfx - void GraphicsWindow::__on_window_init(int32_t width, int32_t height, const ostd::String& title) + void GraphicsWindow::__on_window_init(i32 width, i32 height, const String& title) { SDL_SetWindowResizable(m_window, false); - m_fixedUpdateTImer.create(60.0, [this](double frameTime_s){ + m_fixedUpdateTImer.create(60.0, [this](f64 frameTime_s){ this->onFixedUpdate(frameTime_s); }); - m_fpsUpdateTimer.create(1.0, [this](double frameTime_s){ + m_fpsUpdateTimer.create(1.0, [this](f64 frameTime_s){ if (this->m_frameCount == 0) return; if (this->m_frameTimeAcc == 0) return; - this->m_fps = (int32_t)(1.0f / (static_cast(this->m_frameTimeAcc) / static_cast(this->m_frameCount))); + this->m_fps = (i32)(1.0f / (cast(this->m_frameTimeAcc) / cast(this->m_frameCount))); this->m_frameTimeAcc = 0; this->m_frameCount = 0; }); @@ -569,14 +570,19 @@ namespace ogfx m_rootWidget.__applyTheme(theme, true); } - void Window::__on_window_init(int32_t width, int32_t height, const ostd::String& title) + void Window::__on_window_init(i32 width, i32 height, const String& title) { enableBlockingEvents(); setTypeName("ogfx::gui::Window"); m_gfx.init(*this); loadDefaultTHeme(); + + m_fixedUpdateTimer.create(60.0, [this](f64 dt) { + __on_fixed_update(); + }); + m_lastFrameTime = ostd::StepTimer::Clock::now(); onInitialize(); - m_rootWidget.setSize(static_cast(width), static_cast(height)); + m_rootWidget.setSize(cast(width), cast(height)); } void Window::__on_window_close(void) @@ -588,6 +594,16 @@ namespace ogfx { while (isRunning()) { + auto now = ostd::StepTimer::Clock::now(); + f64 delta = std::chrono::duration(now - m_lastFrameTime).count(); + m_lastFrameTime = now; + + if (delta > 0.25) + delta = 0.25; + + m_fixedUpdateTimer.update(); + __on_update(delta); + handle_events(); before_render(); m_rootWidget.__update(); @@ -688,6 +704,16 @@ namespace ogfx onSignal(signal); } + void Window::__on_update(f64 delta) + { + onUpdate(delta); + } + + void Window::__on_fixed_update(void) + { + onFixedUpdate(); + } + void Window::__on_event(SDL_Event& event) { onSDLEvent(event); diff --git a/src/ogfx/gui/Window.hpp b/src/ogfx/gui/Window.hpp index ad32664..b45b450 100644 --- a/src/ogfx/gui/Window.hpp +++ b/src/ogfx/gui/Window.hpp @@ -34,44 +34,44 @@ namespace ogfx { class WindowCore : public ostd::BaseObject { - public: enum class eCursor : uint8_t + public: enum class eCursor : u8 { - Default = 0, - Text, - Wait, - Crosshair, - Progress, - NWSE_Resize, - NESW_Resize, - EW_Resize, - NS_Resize, - Move, - NotAllowed, - Pointer, - NW_Resize, - N_Resize, - NE_Resize, - E_Resize, - SE_Resize, - S_Resize, - SW_Resize, - W_Resize, + Default = 0, + Text, + Wait, + Crosshair, + Progress, + NWSE_Resize, + NESW_Resize, + EW_Resize, + NS_Resize, + Move, + NotAllowed, + Pointer, + NW_Resize, + N_Resize, + NE_Resize, + E_Resize, + SE_Resize, + S_Resize, + SW_Resize, + W_Resize, - Count + Count }; public: inline WindowCore(void) { } virtual ~WindowCore(void); - inline WindowCore(int32_t width, int32_t height, const ostd::String& title) { initialize(width, height, title); } - void initialize(int32_t width, int32_t height, const ostd::String& title); + inline WindowCore(i32 width, i32 height, const String& title) { initialize(width, height, title); } + void initialize(i32 width, i32 height, const String& title); void mainLoop(void); void close(void); - void setSize(int32_t width, int32_t height); - void setTitle(const ostd::String& title); + void setSize(i32 width, i32 height); + void setTitle(const String& title); void setCursor(eCursor cursor); void enableResizable(bool enable = true); - void setIcon(const ostd::String& iconFilePath); - void setBlockingEventsRefreshFPS(uint32_t fps); + void setIcon(const String& iconFilePath); + void setBlockingEventsRefreshFPS(u32 fps); void requestRedraw(void); void handleSignal(ostd::Signal& signal) override; @@ -86,9 +86,9 @@ namespace ogfx inline bool isResizeable(void) const { return m_resizeable; } inline void hide(void) { SDL_HideWindow(m_window); m_visible = false; } inline void show(void) { SDL_ShowWindow(m_window); m_visible = true; } - inline ostd::String getTitle(void) const { return m_title; } - inline int32_t getWindowWidth(void) const { return m_windowWidth; } - inline int32_t getWindowHeight(void) const { return m_windowHeight; } + inline String getTitle(void) const { return m_title; } + inline i32 getWindowWidth(void) const { return m_windowWidth; } + inline i32 getWindowHeight(void) const { return m_windowHeight; } inline ostd::Color getClearColor(void) const { return m_clearColor; } inline void setClearColor(const ostd::Color& color) { m_clearColor = color; } inline SDL_Renderer* getSDLRenderer(void) { return m_renderer; } @@ -103,10 +103,12 @@ namespace ogfx virtual void before_render(void); virtual void after_render(void); inline virtual void __on_event(SDL_Event& event) { } - inline virtual void __on_window_init(int32_t width, int32_t height, const ostd::String& title) { } + inline virtual void __on_window_init(i32 width, i32 height, const String& title) { } inline virtual void __on_window_destroy(void) { } inline virtual void __on_window_close(void) { } inline virtual void __on_signal(ostd::Signal& signal) { } + inline virtual void __on_update(f64 delta) { } + inline virtual void __on_fixed_update(void) { } inline virtual void __main_loop(void) = 0; private: @@ -123,10 +125,10 @@ namespace ogfx private: ostd::Color m_clearColor { 10, 10, 10, 255 }; - int32_t m_windowWidth { 0 }; - int32_t m_windowHeight { 0 }; - ostd::String m_title { "" }; - int32_t m_blockingEventsDelay { 33 }; + i32 m_windowWidth { 0 }; + i32 m_windowHeight { 0 }; + String m_title { "" }; + i32 m_blockingEventsDelay { 33 }; bool m_running { false }; bool m_initialized { false }; @@ -157,33 +159,33 @@ namespace ogfx SDL_Cursor* m_cursor_W_Resize { nullptr }; public: - inline static constexpr int32_t MaxBlockingEventsFPS { 240 }; - inline static constexpr int32_t DefaultBlockingEventsFPS { 30 }; + inline static constexpr i32 MaxBlockingEventsFPS { 240 }; + inline static constexpr i32 DefaultBlockingEventsFPS { 30 }; private: inline static ostd::Stylesheet DefaultTheme; - std::unordered_map> m_defaultStylesheetVariables; + stdumap> m_defaultStylesheetVariables; }; class GraphicsWindow : public WindowCore { public: inline GraphicsWindow(void) { } - inline GraphicsWindow(int32_t width, int32_t height, const ostd::String& title) { initialize(width, height, title); } + inline GraphicsWindow(i32 width, i32 height, const String& title) { initialize(width, height, title); } inline virtual void onRender(void) { } inline virtual void onUpdate(void) { } - inline virtual void onFixedUpdate(double frameTime_s) { } + inline virtual void onFixedUpdate(f64 frameTime_s) { } inline virtual void onInitialize(void) { } inline virtual void onDestroy(void) { } inline virtual void onClose(void) { } inline virtual void onSDLEvent(SDL_Event& event) { } inline virtual void onSignal(ostd::Signal& signal) { } - inline int32_t getFPS(void) const { return m_fps; } + inline i32 getFPS(void) const { return m_fps; } protected: - void __on_window_init(int32_t width, int32_t height, const ostd::String& title) override; + void __on_window_init(i32 width, i32 height, const String& title) override; void __on_event(SDL_Event& event) override; void __on_window_destroy(void) override; void __on_window_close(void) override; @@ -191,12 +193,12 @@ namespace ogfx void __on_signal(ostd::Signal& signal) override; private: - int32_t m_fps { 0 }; + i32 m_fps { 0 }; ostd::StepTimer m_fixedUpdateTImer; ostd::StepTimer m_fpsUpdateTimer; ostd::Timer m_fpsUpdateClock; - uint64_t m_frameTimeAcc { 0 }; - int32_t m_frameCount { 0 }; + u64 m_frameTimeAcc { 0 }; + i32 m_frameCount { 0 }; }; namespace gui { @@ -204,7 +206,7 @@ namespace ogfx { public: inline Window(void) { } - inline Window(int32_t width, int32_t height, const ostd::String& title) { initialize(width, height, title); } + inline Window(i32 width, i32 height, const String& title) { initialize(width, height, title); } void addWidget(Widget& widget); void setTheme(const ostd::Stylesheet& theme) override; @@ -213,20 +215,25 @@ namespace ogfx inline virtual void onClose(void) { } inline virtual void onSDLEvent(SDL_Event& event) { } inline virtual void onRedraw(BasicRenderer2D& gfx) { } - inline virtual void onUpdate(double delta) { } + inline virtual void onUpdate(f64 delta) { } + inline virtual void onFixedUpdate(void) { } inline virtual void onSignal(ostd::Signal& signal) { } protected: - void __on_window_init(int32_t width, int32_t height, const ostd::String& title) override; + void __on_window_init(i32 width, i32 height, const String& title) override; void __on_event(SDL_Event& event) override; void __on_window_destroy(void) override; void __on_window_close(void) override; void __main_loop(void) override; void __on_signal(ostd::Signal& signal) override; + void __on_update(f64 delta) override; + void __on_fixed_update(void) override; protected: BasicRenderer2D m_gfx; widgets::RootWidget m_rootWidget { *this }; + ostd::StepTimer m_fixedUpdateTimer; + ostd::StepTimer::TimePoint m_lastFrameTime; }; } } diff --git a/src/ogfx/gui/WindowOutputHandler.cpp b/src/ogfx/gui/WindowOutputHandler.cpp index 05baf7a..f30bd23 100644 --- a/src/ogfx/gui/WindowOutputHandler.cpp +++ b/src/ogfx/gui/WindowOutputHandler.cpp @@ -108,7 +108,7 @@ namespace ogfx m_defaultForegroundColor = color; } - void GraphicsWindowOutputHandler::setTabWidth(uint8_t tw) + void GraphicsWindowOutputHandler::setTabWidth(u8 tw) { m_tabWidth = tw; } @@ -116,24 +116,24 @@ namespace ogfx - void GraphicsWindowOutputHandler::setFontSize(int32_t fontSize) + void GraphicsWindowOutputHandler::setFontSize(i32 fontSize) { m_fontSize = fontSize; m_renderer.setFontSize(m_fontSize); __update_char_size(); } - int32_t GraphicsWindowOutputHandler::getFontSize(void) + i32 GraphicsWindowOutputHandler::getFontSize(void) { return m_fontSize; } - Vec2 GraphicsWindowOutputHandler::getCharacterSize(int32_t fontSize) + Vec2 GraphicsWindowOutputHandler::getCharacterSize(i32 fontSize) { if (fontSize > 0) { auto size = m_renderer.getStringDimensions("A", fontSize); - return { (float)size.x, (float)size.y }; + return { (f32)size.x, (f32)size.y }; } return m_charSize; } @@ -163,15 +163,15 @@ namespace ogfx return m_defaultForegroundColor; } - uint8_t GraphicsWindowOutputHandler::getTabWidth(void) + u8 GraphicsWindowOutputHandler::getTabWidth(void) { return m_tabWidth; } Rectangle GraphicsWindowOutputHandler::getConsoleBounds(void) { - float console_w = ((float)m_consoleSize.x * getCharacterSize().x) + getPadding().x + getPadding().w; - float console_h = ((float)m_consoleSize.y * getCharacterSize().y) + getPadding().y + getPadding().h; + f32 console_w = ((f32)m_consoleSize.x * getCharacterSize().x) + getPadding().x + getPadding().w; + f32 console_h = ((f32)m_consoleSize.y * getCharacterSize().y) + getPadding().y + getPadding().h; return { getConsolePosition().x - getPadding().x, getConsolePosition().y - getPadding().y, console_w, console_h }; } @@ -216,7 +216,7 @@ namespace ogfx GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::pChar(char c) { - __print_string(ostd::String("").addChar(c)); + __print_string(String("").addChar(c)); return *this; } @@ -230,7 +230,7 @@ namespace ogfx if (!styled.validate()) return *this; Color oldBgCol = m_backgroundColor; Color oldFgCol = m_foregroundColor; - for (int32_t i = 0; i < styled.text.len(); i++) + for (i32 i = 0; i < styled.text.len(); i++) bg(styled.backgroundColors[i].fullColor).fg(styled.foregroundColors[i].fullColor).pChar(styled.text[i]); m_backgroundColor = oldBgCol; m_foregroundColor = oldFgCol; @@ -261,63 +261,63 @@ namespace ogfx return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(uint8_t i) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(u8 i) { - __print_string(ostd::String("").add(i)); + __print_string(String("").add(i)); return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(int8_t i) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(i8 i) { - __print_string(ostd::String("").add(i)); + __print_string(String("").add(i)); return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(uint16_t i) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(u16 i) { - __print_string(ostd::String("").add(i)); + __print_string(String("").add(i)); return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(int16_t i) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(i16 i) { - __print_string(ostd::String("").add(i)); + __print_string(String("").add(i)); return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(uint32_t i) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(u32 i) { - __print_string(ostd::String("").add(i)); + __print_string(String("").add(i)); return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(int32_t i) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(i32 i) { - __print_string(ostd::String("").add(i)); + __print_string(String("").add(i)); return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(uint64_t i) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(u64 i) { - __print_string(ostd::String("").add(i)); + __print_string(String("").add(i)); return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(int64_t i) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(i64 i) { - __print_string(ostd::String("").add(i)); + __print_string(String("").add(i)); return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(float f, uint8_t precision) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(f32 f, u8 precision) { - __print_string(ostd::String("").add(f, precision)); + __print_string(String("").add(f, precision)); return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(double f, uint8_t precision) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::p(f64 f, u8 precision) { - __print_string(ostd::String("").add(f, precision)); + __print_string(String("").add(f, precision)); return *this; } @@ -333,14 +333,14 @@ namespace ogfx { if (m_curosrPosition.x == 0) { - __print_string(ostd::String("").fixedLength(m_tabWidth, ' ', "")); + __print_string(String("").fixedLength(m_tabWidth, ' ', "")); return *this; } - int32_t restTab = m_tabWidth - ((int32_t)m_curosrPosition.x % m_tabWidth); + i32 restTab = m_tabWidth - ((i32)m_curosrPosition.x % m_tabWidth); if (m_curosrPosition.x + restTab > m_consoleSize.x) restTab = m_consoleSize.x - m_curosrPosition.x; if (restTab == 0) return *this; - __print_string(ostd::String("").fixedLength(restTab, ' ', "")); + __print_string(String("").fixedLength(restTab, ' ', "")); return *this; } @@ -362,53 +362,53 @@ namespace ogfx GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::xy(IPoint position) { - m_curosrPosition = { (float)position.x, (float)position.y }; + m_curosrPosition = { (f32)position.x, (f32)position.y }; return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::xy(int32_t x, int32_t y) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::xy(i32 x, i32 y) { - m_curosrPosition = { (float)x, (float)y }; + m_curosrPosition = { (f32)x, (f32)y }; return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::x(int32_t x) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::x(i32 x) { - m_curosrPosition.x = (float)x; + m_curosrPosition.x = (f32)x; return *this; } - GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::y(int32_t y) + GraphicsWindowOutputHandler& GraphicsWindowOutputHandler::y(i32 y) { - m_curosrPosition.y = (float)y; + m_curosrPosition.y = (f32)y; return *this; } IPoint GraphicsWindowOutputHandler::getCursorPosition(void) { - return { (int32_t)std::round(m_curosrPosition.x), (int32_t)std::round(m_curosrPosition.y) }; + return { (i32)std::round(m_curosrPosition.x), (i32)std::round(m_curosrPosition.y) }; } - void GraphicsWindowOutputHandler::getCursorPosition(int32_t& outX, int32_t& outY) + void GraphicsWindowOutputHandler::getCursorPosition(i32& outX, i32& outY) { - outX = (int32_t)std::round(m_curosrPosition.x); - outY = (int32_t)std::round(m_curosrPosition.y); + outX = (i32)std::round(m_curosrPosition.x); + outY = (i32)std::round(m_curosrPosition.y); } - int32_t GraphicsWindowOutputHandler::getCursorX(void) + i32 GraphicsWindowOutputHandler::getCursorX(void) { - return (int32_t)std::round(m_curosrPosition.x); + return (i32)std::round(m_curosrPosition.x); } - int32_t GraphicsWindowOutputHandler::getCursorY(void) + i32 GraphicsWindowOutputHandler::getCursorY(void) { - return (int32_t)std::round(m_curosrPosition.y); + return (i32)std::round(m_curosrPosition.y); } - void GraphicsWindowOutputHandler::getConsoleSize(int32_t& outColumns, int32_t& outRows) + void GraphicsWindowOutputHandler::getConsoleSize(i32& outColumns, i32& outRows) { - int32_t console_rows = std::numeric_limits::max(); - int32_t console_cols = std::numeric_limits::max(); + i32 console_rows = std::numeric_limits::max(); + i32 console_cols = std::numeric_limits::max(); if (m_consoleSize.x > 0) console_cols = m_consoleSize.x; if (m_consoleSize.y > 0) console_rows = m_consoleSize.y; outColumns = console_cols; @@ -417,8 +417,8 @@ namespace ogfx IPoint GraphicsWindowOutputHandler::getConsoleSize(void) { - int32_t console_rows = std::numeric_limits::max(); - int32_t console_cols = std::numeric_limits::max(); + i32 console_rows = std::numeric_limits::max(); + i32 console_cols = std::numeric_limits::max(); if (m_consoleSize.x > 0) console_cols = m_consoleSize.x; if (m_consoleSize.y > 0) console_rows = m_consoleSize.y; return { console_cols, console_rows }; @@ -427,7 +427,7 @@ namespace ogfx void GraphicsWindowOutputHandler::__update_char_size(void) { auto size = m_renderer.getStringDimensions("A", m_fontSize); - m_charSize = { (float)size.x, (float)size.y }; + m_charSize = { (f32)size.x, (f32)size.y }; } void GraphicsWindowOutputHandler::__print_string(const String& str) @@ -439,7 +439,7 @@ namespace ogfx auto l_print = [&](const String& string) { if (l_endOfConsole()) return; if (string.len() == 0) return; - float vertical_margin = 4; + f32 vertical_margin = 4; Vec2 pos = m_consolePosition + ostd::Vec2 { m_charSize.x * m_curosrPosition.x, m_charSize.y * m_curosrPosition.y }; if (m_backgroundColor.a > 0) m_renderer.fillRect({ pos.x, pos.y + vertical_margin, m_charSize.x * string.len(), m_charSize.y - vertical_margin }, m_backgroundColor); @@ -449,8 +449,8 @@ namespace ogfx if (m_curosrPosition.x >= getConsoleSize().x) nl(); }; - int32_t string_length = str.len(); - int32_t lineLen = m_curosrPosition.x + string_length; + i32 string_length = str.len(); + i32 lineLen = m_curosrPosition.x + string_length; if (lineLen <= getConsoleSize().x) { l_print(str); @@ -458,24 +458,24 @@ namespace ogfx } if (m_wrapMode == eWrapMode::TripleDots) { - int32_t fixedLen = getConsoleSize().x - m_curosrPosition.x; + i32 fixedLen = getConsoleSize().x - m_curosrPosition.x; l_print(str.new_fixedLength(fixedLen, ' ', "...")); } else if (m_wrapMode == eWrapMode::NewLine) { - int32_t restOfLine = getConsoleSize().x - m_curosrPosition.x; - ostd::String tmp = str.new_substr(0, restOfLine); + i32 restOfLine = getConsoleSize().x - m_curosrPosition.x; + String tmp = str.new_substr(0, restOfLine); l_print(tmp); tmp = str.new_substr(restOfLine); - int32_t nlines = tmp.len() / getConsoleSize().x; + i32 nlines = tmp.len() / getConsoleSize().x; if (nlines == 0) { l_print(tmp); return; } - for (int32_t i = 0; i < nlines; i++) + for (i32 i = 0; i < nlines; i++) { - ostd::String line = tmp.new_substr(0, getConsoleSize().x); + String line = tmp.new_substr(0, getConsoleSize().x); l_print(line); tmp.substr(getConsoleSize().x); } diff --git a/src/ogfx/gui/WindowOutputHandler.hpp b/src/ogfx/gui/WindowOutputHandler.hpp index 8c6423f..5355222 100644 --- a/src/ogfx/gui/WindowOutputHandler.hpp +++ b/src/ogfx/gui/WindowOutputHandler.hpp @@ -33,56 +33,56 @@ namespace ogfx public: GraphicsWindowOutputHandler(void); void attachWindow(WindowCore& window); - void setMonospaceFont(const ostd::String& filePath); - ostd::Vec2 getStringSize(const ostd::String& str); + void setMonospaceFont(const String& filePath); + ostd::Vec2 getStringSize(const String& str); bool isReady(void); void resetCursorPosition(void); void resetColors(void); void beginFrame(void); - void setFontSize(int32_t fontSize); + void setFontSize(i32 fontSize); void setConsoleMaxCharacters(const ostd::IPoint& size); void setConsolePosition(const ostd::Vec2& pos); void setWrapMode(eWrapMode wrapMode); void setPadding(const ostd::Rectangle& rect); void setDefaultForegroundColor(const ostd::Color& color); void setDefaultBackgorundColor(const ostd::Color& color); - void setTabWidth(uint8_t tw); + void setTabWidth(u8 tw); - int32_t getFontSize(void); - ostd::Vec2 getCharacterSize(int32_t fontSize = 0); + i32 getFontSize(void); + ostd::Vec2 getCharacterSize(i32 fontSize = 0); ostd::Vec2 getConsolePosition(void); eWrapMode getWrapMode(void); ostd::Rectangle getPadding(void); ostd::Color getDefaultBackgroundColor(void); ostd::Color getDefaultForegroundColor(void); - uint8_t getTabWidth(void); + u8 getTabWidth(void); ostd::Rectangle getConsoleBounds(void); GraphicsWindowOutputHandler& bg(const ostd::Color& color) override; GraphicsWindowOutputHandler& bg(const ostd::ConsoleColors::tConsoleColor& color) override; - GraphicsWindowOutputHandler& bg(const ostd::String& color) override; + GraphicsWindowOutputHandler& bg(const String& color) override; GraphicsWindowOutputHandler& fg(const ostd::Color& color) override; GraphicsWindowOutputHandler& fg(const ostd::ConsoleColors::tConsoleColor& color) override; - GraphicsWindowOutputHandler& fg(const ostd::String& color) override; + GraphicsWindowOutputHandler& fg(const String& color) override; GraphicsWindowOutputHandler& pChar(char c) override; - GraphicsWindowOutputHandler& pStyled(const ostd::String& styled) override; + GraphicsWindowOutputHandler& pStyled(const String& styled) override; GraphicsWindowOutputHandler& pStyled(const ostd::TextStyleParser::tStyledString& styled) override; GraphicsWindowOutputHandler& pStyled(ostd::TextStyleBuilder::IRichStringBase& styled) override; GraphicsWindowOutputHandler& pObject(const ostd::BaseObject& bo) override; - GraphicsWindowOutputHandler& p(const ostd::String& se) override; - GraphicsWindowOutputHandler& p(uint8_t i) override; - GraphicsWindowOutputHandler& p(int8_t i) override; - GraphicsWindowOutputHandler& p(uint16_t i) override; - GraphicsWindowOutputHandler& p(int16_t i) override; - GraphicsWindowOutputHandler& p(uint32_t i) override; - GraphicsWindowOutputHandler& p(int32_t i) override; - GraphicsWindowOutputHandler& p(uint64_t i) override; - GraphicsWindowOutputHandler& p(int64_t i) override; - GraphicsWindowOutputHandler& p(float f, uint8_t precision = 0) override; - GraphicsWindowOutputHandler& p(double f, uint8_t precision = 0) override; + GraphicsWindowOutputHandler& p(const String& se) override; + GraphicsWindowOutputHandler& p(u8 i) override; + GraphicsWindowOutputHandler& p(i8 i) override; + GraphicsWindowOutputHandler& p(u16 i) override; + GraphicsWindowOutputHandler& p(i16 i) override; + GraphicsWindowOutputHandler& p(u32 i) override; + GraphicsWindowOutputHandler& p(i32 i) override; + GraphicsWindowOutputHandler& p(u64 i) override; + GraphicsWindowOutputHandler& p(i64 i) override; + GraphicsWindowOutputHandler& p(f32 f, u8 precision = 0) override; + GraphicsWindowOutputHandler& p(f64 f, u8 precision = 0) override; GraphicsWindowOutputHandler& nl(void) override; GraphicsWindowOutputHandler& tab(void) override; @@ -91,21 +91,21 @@ namespace ogfx GraphicsWindowOutputHandler& reset(void) override; GraphicsWindowOutputHandler& xy(ostd::IPoint position) override; - GraphicsWindowOutputHandler& xy(int32_t x, int32_t y) override; - GraphicsWindowOutputHandler& x(int32_t x) override; - GraphicsWindowOutputHandler& y(int32_t y) override; + GraphicsWindowOutputHandler& xy(i32 x, i32 y) override; + GraphicsWindowOutputHandler& x(i32 x) override; + GraphicsWindowOutputHandler& y(i32 y) override; ostd::IPoint getCursorPosition(void) override; - void getCursorPosition(int32_t& outX, int32_t& outY) override; - int32_t getCursorX(void) override; - int32_t getCursorY(void) override; + void getCursorPosition(i32& outX, i32& outY) override; + i32 getCursorX(void) override; + i32 getCursorY(void) override; - void getConsoleSize(int32_t& outColumns, int32_t& outRows) override; + void getConsoleSize(i32& outColumns, i32& outRows) override; ostd::IPoint getConsoleSize(void) override; private: void __update_char_size(void); - void __print_string(const ostd::String& str); + void __print_string(const String& str); private: ostd::Color m_backgroundColor; @@ -115,13 +115,13 @@ namespace ogfx ostd::Vec2 m_curosrPosition; BasicRenderer2D m_renderer; WindowCore* m_window { nullptr }; - int32_t m_fontSize { 20 }; + i32 m_fontSize { 20 }; ostd::Vec2 m_charSize; ostd::IPoint m_consoleSize { 0, 0 }; bool m_ready { false }; ostd::Vec2 m_consolePosition { 0.0f, 0.0f }; eWrapMode m_wrapMode { eWrapMode::TripleDots }; ostd::Rectangle m_padding { 10, 10, 10, 10 }; - uint8_t m_tabWidth { 8 }; + u8 m_tabWidth { 8 }; }; } diff --git a/src/ogfx/gui/widgets/CheckBox.cpp b/src/ogfx/gui/widgets/CheckBox.cpp index 433f045..b610de4 100644 --- a/src/ogfx/gui/widgets/CheckBox.cpp +++ b/src/ogfx/gui/widgets/CheckBox.cpp @@ -27,7 +27,7 @@ namespace ogfx { namespace widgets { - CheckBox& CheckBox::create(const ostd::String& text) + CheckBox& CheckBox::create(const String& text) { setText(text); setPadding({ 5, 5, 5, 5 }); @@ -45,16 +45,16 @@ namespace ogfx setCheckBoxColor(getThemeValue(theme, "checkbox.checkBoxColor", ostd::Colors::White)); setTextColor(getThemeValue(theme, "checkbox.textColor", ostd::Colors::Black)); setBackGroundColor(getThemeValue(theme, "checkbox.backgroundColor", ostd::Colors::Transparent)); - setFontSize(getThemeValue(theme, "checkbox.fontSize", 28)); - setBorderRadius(getThemeValue(theme, "checkbox.borderRadius", 10)); - setBorderWidth(getThemeValue(theme, "checkbox.borderWidth", 2)); + setFontSize(getThemeValue(theme, "checkbox.fontSize", 28)); + setBorderRadius(getThemeValue(theme, "checkbox.borderRadius", 10)); + setBorderWidth(getThemeValue(theme, "checkbox.borderWidth", 2)); enableBorder(getThemeValue(theme, "checkbox.showBorder", false)); setBorderColor(getThemeValue(theme, "checkbox.borderColor", ostd::Colors::White)); enableBackground(getThemeValue(theme, "checkbox.showBackground", false)); setPadding(getThemeValue(theme, "checkbox.padding", { 5, 5, 5, 5 })); setMargin(getThemeValue(theme, "checkbox.margin", { 0, 0, 0, 0 })); - m_checkBorderRadius = getThemeValue(theme, "checkbox.checkBorderRadius", 5); - m_checkBorderWidth = getThemeValue(theme, "checkbox.checkBorderWidth", 1); + m_checkBorderRadius = getThemeValue(theme, "checkbox.checkBorderRadius", 5); + m_checkBorderWidth = getThemeValue(theme, "checkbox.checkBorderWidth", 1); } void CheckBox::onDraw(ogfx::BasicRenderer2D& gfx) @@ -74,7 +74,7 @@ namespace ogfx setChecked(!isChecked()); } - void CheckBox::setText(const ostd::String& text) + void CheckBox::setText(const String& text) { m_text = text; m_textChanged = true; @@ -82,7 +82,9 @@ namespace ogfx void CheckBox::setChecked(bool checked) { - m_checked = !m_checked; + if (m_checked == checked) + return; + m_checked = checked; setThemeQualifier("active", m_checked); if (callback_onStateChanged) callback_onStateChanged(*this, m_checked); @@ -91,13 +93,13 @@ namespace ogfx void CheckBox::__update_size(ogfx::BasicRenderer2D& gfx) { auto size = gfx.getStringDimensions(getText(), getFontSize()); - m_checkSize = { static_cast(size.y), static_cast(size.y) }; + m_checkSize = { cast(size.y), cast(size.y) }; size.x += m_spacing + m_checkSize.x; size.x += getPadding().left(); size.x += getPadding().right(); size.y += getPadding().top(); size.y += getPadding().bottom(); - setSize({ static_cast(size.x), static_cast(size.y) }); + setSize({ cast(size.x), cast(size.y) }); m_textChanged = false; } } diff --git a/src/ogfx/gui/widgets/CheckBox.hpp b/src/ogfx/gui/widgets/CheckBox.hpp index e3b8a5f..de48b62 100644 --- a/src/ogfx/gui/widgets/CheckBox.hpp +++ b/src/ogfx/gui/widgets/CheckBox.hpp @@ -34,22 +34,22 @@ namespace ogfx { public: inline CheckBox(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); } - inline CheckBox(WindowCore& window, const ostd::String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); } - CheckBox& create(const ostd::String& text); + inline CheckBox(WindowCore& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); } + CheckBox& create(const String& text); void applyTheme(const ostd::Stylesheet& theme) override; void onDraw(ogfx::BasicRenderer2D& gfx) override; void onMouseReleased(const Event& event) override; - void setText(const ostd::String& text); + void setText(const String& text); void setChecked(bool checked); - inline ostd::String getText(void) const { return m_text; } + inline String getText(void) const { return m_text; } inline ostd::Color getCheckBorderColor(void) const { return m_checkBorderColor; } inline void setCheckBorderColor(const ostd::Color& color) { m_checkBorderColor = color; } inline ostd::Color getCheckBoxColor(void) const { return m_checkBoxColor; } inline void setCheckBoxColor(const ostd::Color& color) { m_checkBoxColor = color; } inline ostd::Color getTextColor(void) const { return m_textColor; } inline void setTextColor(const ostd::Color& color) { m_textColor = color; } - inline int32_t getFontSize(void) const { return m_fontSize; } - inline void setFontSize(int32_t fontSize) { m_fontSize = fontSize; } + inline i32 getFontSize(void) const { return m_fontSize; } + inline void setFontSize(i32 fontSize) { m_fontSize = fontSize; } inline bool isChecked(void) const { return m_checked; } inline void setStateChangedCallback(std::function callback) { callback_onStateChanged = callback; } @@ -58,14 +58,14 @@ namespace ogfx private: bool m_checked { false }; - ostd::String m_text { "" }; + String m_text { "" }; bool m_textChanged { false }; - int32_t m_fontSize { 20 }; + i32 m_fontSize { 20 }; ostd::Color m_textColor { 255, 255, 255 }; - float m_spacing { 10 }; + f32 m_spacing { 10 }; ostd::Vec2 m_checkSize { 0, 0 }; - int32_t m_checkBorderRadius { 5 }; - int32_t m_checkBorderWidth { 1 }; + i32 m_checkBorderRadius { 5 }; + i32 m_checkBorderWidth { 1 }; ostd::Color m_checkBorderColor { 255, 255, 255 }; ostd::Color m_checkBoxColor { 255, 255, 255 }; diff --git a/src/ogfx/gui/widgets/Containers.cpp b/src/ogfx/gui/widgets/Containers.cpp index 3612303..33bc6dc 100644 --- a/src/ogfx/gui/widgets/Containers.cpp +++ b/src/ogfx/gui/widgets/Containers.cpp @@ -41,15 +41,15 @@ namespace ogfx void Panel::applyTheme(const ostd::Stylesheet& theme) { setBackGroundColor(getThemeValue(theme, "panel.backgroundColor", ostd::Colors::Gray)); - setBorderRadius(getThemeValue(theme, "panel.borderRadius", 8)); - setBorderWidth(getThemeValue(theme, "panel.borderWidth", 2)); + setBorderRadius(getThemeValue(theme, "panel.borderRadius", 8)); + setBorderWidth(getThemeValue(theme, "panel.borderWidth", 2)); enableBorder(getThemeValue(theme, "panel.showBorder", true)); enableBackground(getThemeValue(theme, "panel.showBackground", true)); setBorderColor(getThemeValue(theme, "panel.borderColor", ostd::Colors::Black)); m_titleColor = getThemeValue(theme, "panel.titleColor", ostd::Colors::Black); m_showTitle = getThemeValue(theme, "panel.showTitle", false); - m_titleHeight = getThemeValue(theme, "panel.titleHeight", 30); - m_titleType = getThemeValue(theme, "panel.titleHeight", "text"); + m_titleHeight = getThemeValue(theme, "panel.titleHeight", 30); + m_titleType = getThemeValue(theme, "panel.titleHeight", "text"); setPadding(getThemeValue(theme, "panel.padding", { 15, 15, 15, 15 })); } diff --git a/src/ogfx/gui/widgets/Containers.hpp b/src/ogfx/gui/widgets/Containers.hpp index c8951ca..d841c3e 100644 --- a/src/ogfx/gui/widgets/Containers.hpp +++ b/src/ogfx/gui/widgets/Containers.hpp @@ -41,8 +41,8 @@ namespace ogfx private: ostd::Color m_titleColor { 0, 0, 0 }; bool m_showTitle { false }; - ostd::String m_titleType = "full"; - float m_titleHeight { 30 }; + String m_titleType = "full"; + f32 m_titleHeight { 30 }; }; } } diff --git a/src/ogfx/gui/widgets/Label.cpp b/src/ogfx/gui/widgets/Label.cpp index 3426336..36f6e92 100644 --- a/src/ogfx/gui/widgets/Label.cpp +++ b/src/ogfx/gui/widgets/Label.cpp @@ -27,7 +27,7 @@ namespace ogfx { namespace widgets { - Label& Label::create(const ostd::String& text) + Label& Label::create(const String& text) { setText(text); setPadding({ 5, 5, 5, 5 }); @@ -43,9 +43,9 @@ namespace ogfx { setColor(getThemeValue(theme, "label.textColor", ostd::Colors::White)); setBackGroundColor(getThemeValue(theme, "label.backgroundColor", ostd::Colors::Transparent)); - setFontSize(getThemeValue(theme, "label.fontSize", 20)); - setBorderRadius(getThemeValue(theme, "label.borderRadius", 10)); - setBorderWidth(getThemeValue(theme, "label.borderWidth", 2)); + setFontSize(getThemeValue(theme, "label.fontSize", 20)); + setBorderRadius(getThemeValue(theme, "label.borderRadius", 10)); + setBorderWidth(getThemeValue(theme, "label.borderWidth", 2)); enableBorder(getThemeValue(theme, "label.showBorder", false)); setBorderColor(getThemeValue(theme, "label.borderColor", ostd::Colors::White)); enableBackground(getThemeValue(theme, "label.showBackground", false)); @@ -60,7 +60,7 @@ namespace ogfx gfx.drawString(getText(), getGlobalContentPosition(), getColor(), getFontSize()); } - void Label::setText(const ostd::String& text) + void Label::setText(const String& text) { m_text = text; m_textChanged = true; @@ -73,7 +73,7 @@ namespace ogfx size.x += getPadding().right(); size.y += getPadding().top(); size.y += getPadding().bottom(); - setSize({ static_cast(size.x), static_cast(size.y) }); + setSize({ cast(size.x), cast(size.y) }); m_textChanged = false; } } diff --git a/src/ogfx/gui/widgets/Label.hpp b/src/ogfx/gui/widgets/Label.hpp index 529c6c5..455adcf 100644 --- a/src/ogfx/gui/widgets/Label.hpp +++ b/src/ogfx/gui/widgets/Label.hpp @@ -33,24 +33,24 @@ namespace ogfx { public: inline Label(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); } - inline Label(WindowCore& window, const ostd::String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); } - Label& create(const ostd::String& text); + inline Label(WindowCore& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); } + Label& create(const String& text); void applyTheme(const ostd::Stylesheet& theme) override; void onDraw(ogfx::BasicRenderer2D& gfx) override; - void setText(const ostd::String& text); - inline ostd::String getText(void) const { return m_text; } + void setText(const String& text); + inline String getText(void) const { return m_text; } inline ostd::Color getColor(void) const { return m_color; } inline void setColor(const ostd::Color& color) { m_color = color; } - inline int32_t getFontSize(void) const { return m_fontSize; } - inline void setFontSize(int32_t fontSize) { m_fontSize = fontSize; } + inline i32 getFontSize(void) const { return m_fontSize; } + inline void setFontSize(i32 fontSize) { m_fontSize = fontSize; } private: void __update_size(ogfx::BasicRenderer2D& gfx); private: - ostd::String m_text { "" }; + String m_text { "" }; bool m_textChanged { false }; - int32_t m_fontSize { 20 }; + i32 m_fontSize { 20 }; ostd::Color m_color { 255, 255, 255 }; }; } diff --git a/src/ogfx/gui/widgets/RootWidget.cpp b/src/ogfx/gui/widgets/RootWidget.cpp index 098ca12..3840368 100644 --- a/src/ogfx/gui/widgets/RootWidget.cpp +++ b/src/ogfx/gui/widgets/RootWidget.cpp @@ -32,13 +32,13 @@ namespace ogfx { disableDrawBox(); m_rootChild = true; - setSize(static_cast(window.getWindowWidth()), static_cast(window.getWindowHeight())); + setSize(cast(window.getWindowWidth()), cast(window.getWindowHeight())); setTypeName("ogfx::gui::widgets::RootWidget"); } void RootWidget::onWindowResized(const Event& event) { - setSize(static_cast(event.windowResized->new_width), static_cast(event.windowResized->new_height)); + setSize(cast(event.windowResized->new_width), cast(event.windowResized->new_height)); } void RootWidget::applyTheme(const ostd::Stylesheet& theme) @@ -48,7 +48,7 @@ namespace ogfx void RootWidget::onDraw(ogfx::BasicRenderer2D& gfx) { - gfx.fillRect({ 0, 0, static_cast(getWindow().getWindowWidth()), static_cast(getWindow().getWindowHeight()) }, m_color); + gfx.fillRect({ 0, 0, cast(getWindow().getWindowWidth()), cast(getWindow().getWindowHeight()) }, m_color); } } } diff --git a/src/ogfx/gui/widgets/Widget.cpp b/src/ogfx/gui/widgets/Widget.cpp index a6471e4..6f4956b 100644 --- a/src/ogfx/gui/widgets/Widget.cpp +++ b/src/ogfx/gui/widgets/Widget.cpp @@ -86,7 +86,7 @@ namespace ogfx setThemeQualifier("disabled", !enable); } - void Widget::addThemeOverride(const ostd::String& fullKey, ostd::Stylesheet::TypeVariant value) + void Widget::addThemeOverride(const String& fullKey, ostd::Stylesheet::TypeVariant value) { m_themeOverrides.push_back({ fullKey, value }); } @@ -103,10 +103,10 @@ namespace ogfx struct tBackup { const ostd::Stylesheet::TypeVariant* ptr; ostd::Stylesheet::TypeVariant val; - ostd::String key; + String key; }; - std::vector backup; + stdvec backup; for (auto& rule : m_themeOverrides) { auto currentValuePtr = theme.getFull(rule.fullKey); @@ -126,7 +126,7 @@ namespace ogfx } } - void Widget::setThemeQualifier(const ostd::String& qualifier, bool value) + void Widget::setThemeQualifier(const String& qualifier, bool value) { for (auto& [name, state] : m_qualifierList) { @@ -140,7 +140,7 @@ namespace ogfx } } - bool Widget::getThemeQualifier(const ostd::String& qualifier) const + bool Widget::getThemeQualifier(const String& qualifier) const { for (auto& [name, state] : m_qualifierList) { @@ -150,7 +150,7 @@ namespace ogfx return false; } - bool Widget::addThemeID(const ostd::String& id) + bool Widget::addThemeID(const String& id) { if (STDVEC_CONTAINS(m_themeIDList, id)) return false; @@ -158,7 +158,7 @@ namespace ogfx return true; } - bool Widget::removeThemeID(const ostd::String& id) + bool Widget::removeThemeID(const String& id) { if (!STDVEC_CONTAINS(m_themeIDList, id)) return false; diff --git a/src/ogfx/gui/widgets/Widget.hpp b/src/ogfx/gui/widgets/Widget.hpp index 9cf5c7c..40f5e87 100644 --- a/src/ogfx/gui/widgets/Widget.hpp +++ b/src/ogfx/gui/widgets/Widget.hpp @@ -35,7 +35,7 @@ namespace ogfx { private: struct ThemeOverride { - ostd::String fullKey; + String fullKey; ostd::Stylesheet::TypeVariant value; }; public: using EventCallback = std::function; @@ -51,12 +51,12 @@ namespace ogfx bool contains(ostd::Vec2 p, bool includeBounds = false) const override; void enable(bool enable = true); virtual void applyTheme(const ostd::Stylesheet& theme) = 0; - void addThemeOverride(const ostd::String& fullKey, ostd::Stylesheet::TypeVariant value); + void addThemeOverride(const String& fullKey, ostd::Stylesheet::TypeVariant value); void reloadTheme(void); - void setThemeQualifier(const ostd::String& qualifier, bool value = true); - bool getThemeQualifier(const ostd::String& qualifier) const; - bool addThemeID(const ostd::String& id); - bool removeThemeID(const ostd::String& id); + void setThemeQualifier(const String& qualifier, bool value = true); + bool getThemeQualifier(const String& qualifier) const; + bool addThemeID(const String& id); + bool removeThemeID(const String& id); inline const ostd::Stylesheet::QualifierList& getThemeQualifierList(void) const { return m_qualifierList; } inline virtual void onDraw(ogfx::BasicRenderer2D& gfx) { } @@ -117,12 +117,12 @@ namespace ogfx inline bool hasChildren(void) const { return m_allowChildren && m_widgets.widgetCount() > 0; } inline virtual bool isInvalid(void) const override { return ostd::BaseObject::isInvalid() || (m_parent == nullptr && !m_rootChild); } - inline void setTabIndex(int32_t tabIndex) { m_tabIndex = tabIndex; } - inline int32_t getTabIndex(void) const { return m_tabIndex; } + inline void setTabIndex(i32 tabIndex) { m_tabIndex = tabIndex; } + inline i32 getTabIndex(void) const { return m_tabIndex; } inline bool isFocused(void) const { return m_focused; } inline WindowCore& getWindow(void) { return *m_window; } inline Widget* getParent(void) { return m_parent; } - inline int32_t getZIndex(void) const { return m_zIndex; } + inline i32 getZIndex(void) const { return m_zIndex; } inline bool isChildrenEnabled(void) const { return m_allowChildren; } inline void setPadding(const ostd::Rectangle& pad) { m_padding = pad; } inline void setMargin(const ostd::Rectangle& margin) { m_margin = margin; } @@ -130,7 +130,7 @@ namespace ogfx inline Rectangle getMargin(void) const { return m_margin; } inline bool isMouseInside(void) const { return m_mouseInside; } inline ogfx::MouseEventData::eButton getPressedMouseButton(void) const { return m_pressedButton; } - inline const std::vector& getThemeIDList(void) const { return m_themeIDList; } + inline const stdvec& getThemeIDList(void) const { return m_themeIDList; } inline bool isEnabled(void) const { return m_enabled; } inline bool isFocusEnabled(void) const { return m_allowFocus; } inline void enableFocus(bool enable = true) { m_allowFocus = enable; } @@ -148,13 +148,13 @@ namespace ogfx inline ostd::Color getBorderColor(void) { return m_borderColor; } inline void enableBorder(bool enable = true) { m_showBorder = enable; } inline bool isBorderEnabled(void) const { return m_showBorder; } - inline void setBorderRadius(int32_t br) { m_borderRadius = br; } - inline int32_t getBorderRadius(void) const { return m_borderRadius; } - inline void setBorderWidth(int32_t bw) { m_borderWidth = bw; } - inline int32_t getBorderWidth(void) const { return m_borderWidth; } + inline void setBorderRadius(i32 br) { m_borderRadius = br; } + inline i32 getBorderRadius(void) const { return m_borderRadius; } + inline void setBorderWidth(i32 bw) { m_borderWidth = bw; } + inline i32 getBorderWidth(void) const { return m_borderWidth; } template - inline T getThemeValue(const ostd::Stylesheet &theme, const ostd::String& key, const T& fallback) + inline T getThemeValue(const ostd::Stylesheet &theme, const String& key, const T& fallback) { return theme.get(key, fallback, getThemeIDList(), getThemeQualifierList()); } @@ -173,8 +173,8 @@ namespace ogfx protected: bool m_rootChild { false }; - int32_t m_borderRadius { 10 }; - int32_t m_borderWidth { 2 }; + i32 m_borderRadius { 10 }; + i32 m_borderWidth { 2 }; ostd::Color m_borderColor { 255, 255, 255 }; bool m_showBorder { false }; ostd::Color m_backgroundColor { ostd::Colors::Transparent }; @@ -200,8 +200,8 @@ namespace ogfx WindowCore* m_window { nullptr }; Widget* m_parent { nullptr }; bool m_focused { false }; - int32_t m_tabIndex { -1 }; - int32_t m_zIndex { -1 }; + i32 m_tabIndex { -1 }; + i32 m_zIndex { -1 }; WidgetManager m_widgets; bool m_allowChildren { true }; bool m_mouseInside { false }; @@ -212,7 +212,7 @@ namespace ogfx bool m_acceptDragAndDrop { false }; MouseEventData::eButton m_pressedButton { MouseEventData::eButton::None }; - std::vector m_themeIDList; + stdvec m_themeIDList; ostd::Stylesheet::QualifierList m_qualifierList { { "disabled", false }, { "pressed", false }, @@ -220,7 +220,7 @@ namespace ogfx { "focused", false }, { "active", false } }; - std::vector m_themeOverrides; + stdvec m_themeOverrides; bool m_drawBox { true }; ostd::Color m_drawBoxColor { 255, 0, 0 }; diff --git a/src/ogfx/render/BasicRenderer.cpp b/src/ogfx/render/BasicRenderer.cpp index 7f29435..29966a8 100644 --- a/src/ogfx/render/BasicRenderer.cpp +++ b/src/ogfx/render/BasicRenderer.cpp @@ -56,7 +56,7 @@ namespace ogfx closeFont(); } - int32_t BasicRenderer2D::init(WindowCore& window) + i32 BasicRenderer2D::init(WindowCore& window) { m_window = &window; if (m_initialized) return set_error_state(tErrors::NoError); @@ -107,10 +107,10 @@ namespace ogfx m_clipStack.push_back(finalRect); SDL_Rect r; - r.x = (int)std::round(finalRect.x); - r.y = (int)std::round(finalRect.y); - r.w = (int)std::round(finalRect.w); - r.h = (int)std::round(finalRect.h); + r.x = (i32)std::round(finalRect.x); + r.y = (i32)std::round(finalRect.y); + r.w = (i32)std::round(finalRect.w); + r.h = (i32)std::round(finalRect.h); SDL_SetRenderClipRect(m_window->getSDLRenderer(), &r); } @@ -132,15 +132,15 @@ namespace ogfx const auto& rect = m_clipStack.back(); SDL_Rect r; - r.x = (int)std::round(rect.x); - r.y = (int)std::round(rect.y); - r.w = (int)std::round(rect.w); - r.h = (int)std::round(rect.h); + r.x = (i32)std::round(rect.x); + r.y = (i32)std::round(rect.y); + r.w = (i32)std::round(rect.w); + r.h = (i32)std::round(rect.h); SDL_SetRenderClipRect(m_window->getSDLRenderer(), &r); } - int32_t BasicRenderer2D::loadDefaultFont(int32_t fontSize) + i32 BasicRenderer2D::loadDefaultFont(i32 fontSize) { return openFont(ubuntu_mono_regular_ttf_data, ubuntu_mono_regular_ttf_size, fontSize); } @@ -157,7 +157,7 @@ namespace ogfx set_error_state(tErrors::NoError); } - int32_t BasicRenderer2D::openFont(const ostd::String& fontPath, int32_t fontSize) + i32 BasicRenderer2D::openFont(const String& fontPath, i32 fontSize) { if (!m_initialized) return set_error_state(tErrors::Uninitialized); if (m_fontOpen) closeFont(); @@ -176,7 +176,7 @@ namespace ogfx return set_error_state(tErrors::NoError); } - int32_t BasicRenderer2D::openFont(const ostd::UByte resource_data[], uint32_t data_size, int32_t fontSize) + i32 BasicRenderer2D::openFont(const ostd::UByte resource_data[], u32 data_size, i32 fontSize) { if (!m_initialized) return set_error_state(tErrors::Uninitialized); if (data_size < 100) // Arbitrary 100 bytes @@ -198,7 +198,7 @@ namespace ogfx return set_error_state(tErrors::NoError); } - int32_t BasicRenderer2D::setFontSize(int32_t fontSize) + i32 BasicRenderer2D::setFontSize(i32 fontSize) { if (!m_initialized) return set_error_state(tErrors::Uninitialized); @@ -212,24 +212,24 @@ namespace ogfx return set_error_state(tErrors::NoError); } - ostd::Vec2 BasicRenderer2D::getStringDimensions(const ostd::String& message, int32_t fontSize, TTF_Font* font) + ostd::Vec2 BasicRenderer2D::getStringDimensions(const String& message, i32 fontSize, TTF_Font* font) { if (!isValid()) return { 0, 0 }; if (fontSize <= 0) fontSize = m_fontSize; if (!font) font = m_font; - int32_t oldFontSize = getFontSize(); + i32 oldFontSize = getFontSize(); setFontSize(fontSize); auto glyphs = m_fontGlyphAtlas.processString(message, font, fontSize); if (glyphs.empty()) return { 0, 0 }; - float totalWidth = 0; + f32 totalWidth = 0; for (size_t i = 0; i < glyphs.size(); i++) { totalWidth += glyphs[i]->advance; if (i > 0) { - int kern = 0; + i32 kern = 0; TTF_GetGlyphKerning(font, glyphs[i - 1]->codepoint, glyphs[i]->codepoint, &kern); totalWidth += kern; } @@ -256,7 +256,7 @@ namespace ogfx ostd::Vec2 texSize = image.getSize(); // 1. Resolve source rectangle - float sx, sy, sw, sh; + f32 sx, sy, sw, sh; if (srcRect.w == 0 && srcRect.h == 0) { // Use entire texture @@ -274,14 +274,14 @@ namespace ogfx } // 2. Resolve destination rectangle - float dx = position.x; - float dy = position.y; - float dw = (size.x == 0) ? sw : size.x; - float dh = (size.y == 0) ? sh : size.y; - float x1 = dx; - float y1 = dy; - float x2 = dx + dw; - float y2 = dy + dh; + f32 dx = position.x; + f32 dy = position.y; + f32 dw = (size.x == 0) ? sw : size.x; + f32 dh = (size.y == 0) ? sh : size.y; + f32 x1 = dx; + f32 y1 = dy; + f32 x2 = dx + dw; + f32 y2 = dy + dh; // 3. Build quad vertices ostd::Vec2 verts[4] = { @@ -300,7 +300,7 @@ namespace ogfx }; // 5. Push quad - uint32_t inds[6] = QUAD_INDICES_ARR; + u32 inds[6] = QUAD_INDICES_ARR; push_polygon(verts, uvs, 4, inds, 6, ostd::Colors::White, tex); } @@ -313,19 +313,19 @@ namespace ogfx drawImage(img, position, size, anim.getFrameRect()); } - void BasicRenderer2D::drawString(const ostd::String& str, const ostd::Vec2& position, const ostd::Color& color, int32_t fontSize, float scale) + void BasicRenderer2D::drawString(const String& str, const ostd::Vec2& position, const ostd::Color& color, i32 fontSize, f32 scale) { if (!isValid()) return; if (fontSize <= 0) fontSize = m_fontSize; - int32_t oldFontSize = m_fontSize; + i32 oldFontSize = m_fontSize; setFontSize(fontSize); auto glyphs = m_fontGlyphAtlas.processString(str, m_font, fontSize); if (glyphs.empty()) return; - float x = position.x; - float y = position.y; + f32 x = position.x; + f32 y = position.y; for (size_t i = 0; i < glyphs.size(); i++) @@ -345,7 +345,7 @@ namespace ogfx { x + g->size.x * scale, y + g->size.y * scale }, { x, y + g->size.y * scale } }; - uint32_t inds[6] = QUAD_INDICES_ARR; + u32 inds[6] = QUAD_INDICES_ARR; push_polygon(verts, g->uvs, 4, inds, 6, color, g->atlas); x += (g->advance * scale); @@ -353,13 +353,13 @@ namespace ogfx setFontSize(oldFontSize); } - void BasicRenderer2D::drawCenteredString(const ostd::String& str, const ostd::Vec2& center, const ostd::Color& color, int32_t fontSize, float scale) + void BasicRenderer2D::drawCenteredString(const String& str, const ostd::Vec2& center, const ostd::Color& color, i32 fontSize, f32 scale) { auto dims = getStringDimensions(str, fontSize); drawString(str, { center.x - (dims.x * scale) * 0.5f, center.y - (dims.y * scale) * 0.5f }, color, fontSize, scale); } - void BasicRenderer2D::drawCenteredString(const ostd::String& str, const ostd::Rectangle& bounds, const ostd::Color& color, int32_t fontSize, float scale) + void BasicRenderer2D::drawCenteredString(const String& str, const ostd::Rectangle& bounds, const ostd::Color& color, i32 fontSize, f32 scale) { drawCenteredString(str, ostd::Vec2 { bounds.x + bounds.w * 0.5f, bounds.y + bounds.h * 0.5f }, color, fontSize, scale); } @@ -370,7 +370,7 @@ namespace ogfx // ===================================================== PRIMITIVES ===================================================== - void BasicRenderer2D::drawLine(const ostd::FLine& line, const ostd::Color& color, int32_t thickness, bool rounded) + void BasicRenderer2D::drawLine(const ostd::FLine& line, const ostd::Color& color, i32 thickness, bool rounded) { if (!m_initialized || thickness <= 0) return; @@ -381,7 +381,7 @@ namespace ogfx Vec2 dir = (p2 - p1).normalize(); Vec2 perp = { -dir.y, dir.x }; // 90° rotation - float half = thickness * 0.5f; + f32 half = thickness * 0.5f; Vec2 off = perp * half; std::array verts = {{ @@ -390,30 +390,30 @@ namespace ogfx p2 + off, p2 - off }}; - std::array inds = QUAD_INDICES_ARR; + std::array inds = QUAD_INDICES_ARR; push_polygon(verts.data(), nullptr, 4, inds.data(), 6, color, nullptr); if (!rounded || thickness < 4) return; - int segments = std::max(6, int(thickness * 0.75f)); + i32 segments = std::max(6, i32(thickness * 0.75f)); generate_half_circle(p1, -dir, half, segments, color); generate_half_circle(p2, dir, half, segments, color); } - void BasicRenderer2D::drawRect(const ostd::Rectangle& rect, const ostd::Color& color, int32_t thickness) + void BasicRenderer2D::drawRect(const ostd::Rectangle& rect, const ostd::Color& color, i32 thickness) { if (!m_initialized || thickness <= 0) return; - float half = thickness * 0.5f; + f32 half = thickness * 0.5f; // Inset rectangle so the outline stays inside the original bounds - float x1 = rect.x + half; - float y1 = rect.y + half; - float x2 = rect.x + rect.w - half; - float y2 = rect.y + rect.h - half; + f32 x1 = rect.x + half; + f32 y1 = rect.y + half; + f32 x2 = rect.x + rect.w - half; + f32 y2 = rect.y + rect.h - half; // Top drawLine({ {x1, y1}, {x2, y1} }, color, thickness, false); @@ -428,7 +428,12 @@ namespace ogfx drawLine({ {x1, y2 + half}, {x1, y1 - half} }, color, thickness, false); } - void BasicRenderer2D::drawRoundRect(const ostd::Rectangle& rect, const ostd::Color& color, float radius, int32_t thickness) + void BasicRenderer2D::drawRect(const ostd::Vec2& center, const ostd::Vec2& size, const ostd::Color& color, i32 thickness) + { + drawRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, color, thickness); + } + + void BasicRenderer2D::drawRoundRect(const ostd::Rectangle& rect, const ostd::Color& color, f32 radius, i32 thickness) { if (!m_initialized || thickness <= 0) return; @@ -436,13 +441,13 @@ namespace ogfx // Clamp radius so it never exceeds half the smallest dimension radius = std::max(0.0f, std::min(radius, std::min(rect.w, rect.h) * 0.5f)); - float half = thickness * 0.5f; + f32 half = thickness * 0.5f; // Inset rectangle so the border stays INSIDE the given bounds - float x1 = rect.x + half; - float y1 = rect.y + half; - float x2 = rect.x + rect.w - half; - float y2 = rect.y + rect.h - half; + f32 x1 = rect.x + half; + f32 y1 = rect.y + half; + f32 x2 = rect.x + rect.w - half; + f32 y2 = rect.y + rect.h - half; // Corner centers ostd::Vec2 TL { x1 + radius, y1 + radius }; @@ -457,7 +462,7 @@ namespace ogfx drawLine({ {x1, y2 - radius}, {x1, y1 + radius} }, color, thickness, false); // left // Number of segments for smooth arcs - int segments = std::max(6, int(radius * 0.75f)); + i32 segments = std::max(6, i32(radius * 0.75f)); // Quarter‑ellipse strokes (each is 90°) generate_ellipse_stroke(TL, radius, radius, thickness, M_PI, M_PI + M_PI * 0.5f, color, segments); // TL @@ -466,15 +471,20 @@ namespace ogfx generate_ellipse_stroke(BL, radius, radius, thickness, M_PI * 0.5f, M_PI, color, segments); // BL } - void BasicRenderer2D::drawCircle(const ostd::Vec2& center, float radius, const ostd::Color& color, int32_t thickness) + void BasicRenderer2D::drawRoundRect(const ostd::Vec2& center, const ostd::Vec2& size, const ostd::Color& color, f32 radius, i32 thickness) + { + drawRoundRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, color, radius, thickness); + } + + void BasicRenderer2D::drawCircle(const ostd::Vec2& center, f32 radius, const ostd::Color& color, i32 thickness) { if (!m_initialized || thickness <= 0) return; - int segments = std::max(12, int(radius * 0.75f)); + i32 segments = std::max(12, i32(radius * 0.75f)); generate_ellipse_stroke(center, radius, radius, thickness, 0.0f, 2.0f * M_PI, color, segments); } - void BasicRenderer2D::drawCircle(const ostd::Rectangle& rect, const ostd::Color& color, int32_t thickness) + void BasicRenderer2D::drawCircle(const ostd::Rectangle& rect, const ostd::Color& color, i32 thickness) { if (!m_initialized || thickness <= 0) return; @@ -484,20 +494,20 @@ namespace ogfx rect.y + rect.h * 0.5f }; - float radius = std::min(rect.w, rect.h) * 0.5f; + f32 radius = std::min(rect.w, rect.h) * 0.5f; drawCircle(center, radius, color, thickness); } - void BasicRenderer2D::drawEllipse(const ostd::Rectangle& rect, const ostd::Color& color, int32_t thickness) + void BasicRenderer2D::drawEllipse(const ostd::Rectangle& rect, const ostd::Color& color, i32 thickness) { if (!m_initialized || thickness <= 0) return; ostd::Vec2 center = { rect.x + rect.w*0.5f, rect.y + rect.h*0.5f }; - float rx = rect.w * 0.5f; - float ry = rect.h * 0.5f; + f32 rx = rect.w * 0.5f; + f32 ry = rect.h * 0.5f; - int segments = std::max(12, int(std::max(rx, ry) * 0.75f)); + i32 segments = std::max(12, i32(std::max(rx, ry) * 0.75f)); generate_ellipse_stroke(center, rx, ry, thickness, 0.0f, 2.0f * M_PI, color, segments); } @@ -506,10 +516,10 @@ namespace ogfx if (!m_initialized) return; - float x1 = rect.x; - float y1 = rect.y; - float x2 = rect.x + rect.w; - float y2 = rect.y + rect.h; + f32 x1 = rect.x; + f32 y1 = rect.y; + f32 x2 = rect.x + rect.w; + f32 y2 = rect.y + rect.h; ostd::Vec2 verts[4] = { { x1, y1 }, @@ -517,11 +527,16 @@ namespace ogfx { x2, y2 }, { x1, y2 } }; - uint32_t inds[6] = QUAD_INDICES_ARR; + u32 inds[6] = QUAD_INDICES_ARR; push_polygon(verts, nullptr, 4, inds, 6, color, nullptr); } - void BasicRenderer2D::fillRoundRect(const ostd::Rectangle& rect, const ostd::Color& color, float radius) + void BasicRenderer2D::fillRect(const ostd::Vec2& center, const ostd::Vec2& size, const ostd::Color& color) + { + fillRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, color); + } + + void BasicRenderer2D::fillRoundRect(const ostd::Rectangle& rect, const ostd::Color& color, f32 radius) { if (!m_initialized) return; @@ -529,18 +544,18 @@ namespace ogfx // Clamp radius radius = std::max(0.0f, std::min(radius, std::min(rect.w, rect.h) * 0.5f)); - float x1 = rect.x; - float y1 = rect.y; - float x2 = rect.x + rect.w; - float y2 = rect.y + rect.h; + f32 x1 = rect.x; + f32 y1 = rect.y; + f32 x2 = rect.x + rect.w; + f32 y2 = rect.y + rect.h; - float cx1 = x1 + radius; - float cy1 = y1 + radius; - float cx2 = x2 - radius; - float cy2 = y2 - radius; + f32 cx1 = x1 + radius; + f32 cy1 = y1 + radius; + f32 cx2 = x2 - radius; + f32 cy2 = y2 - radius; // Number of segments for smooth corners - int segments = std::max(6, int(radius * 0.75f)); + i32 segments = std::max(6, i32(radius * 0.75f)); // // 1. Fill the center rectangle @@ -552,7 +567,7 @@ namespace ogfx { cx2, cy2 }, { cx1, cy2 } }; - uint32_t inds[6] = { 0,1,2, 2,3,0 }; + u32 inds[6] = { 0,1,2, 2,3,0 }; push_polygon(verts, nullptr, 4, inds, 6, color, nullptr); } @@ -569,7 +584,7 @@ namespace ogfx { x2 - radius, y1 + radius }, { x1 + radius, y1 + radius } }; - uint32_t inds[6] = { 0,1,2, 2,3,0 }; + u32 inds[6] = { 0,1,2, 2,3,0 }; push_polygon(verts, nullptr, 4, inds, 6, color, nullptr); } @@ -581,7 +596,7 @@ namespace ogfx { x2 - radius, y2 }, { x1 + radius, y2 } }; - uint32_t inds[6] = { 0,1,2, 2,3,0 }; + u32 inds[6] = { 0,1,2, 2,3,0 }; push_polygon(verts, nullptr, 4, inds, 6, color, nullptr); } @@ -593,7 +608,7 @@ namespace ogfx { x1 + radius, y2 - radius }, { x1, y2 - radius } }; - uint32_t inds[6] = { 0,1,2, 2,3,0 }; + u32 inds[6] = { 0,1,2, 2,3,0 }; push_polygon(verts, nullptr, 4, inds, 6, color, nullptr); } @@ -605,7 +620,7 @@ namespace ogfx { x2, y2 - radius }, { x2 - radius, y2 - radius } }; - uint32_t inds[6] = { 0,1,2, 2,3,0 }; + u32 inds[6] = { 0,1,2, 2,3,0 }; push_polygon(verts, nullptr, 4, inds, 6, color, nullptr); } @@ -619,12 +634,17 @@ namespace ogfx generate_filled_ellipse_stroke({cx1, cy2}, radius, radius, 0.5f * M_PI, color, segments); // BL } - void BasicRenderer2D::fillCircle(const ostd::Vec2& center, float radius, const ostd::Color& color) + void BasicRenderer2D::fillRoundRect(const ostd::Vec2& center, const ostd::Vec2& size, const ostd::Color& color, f32 radius) + { + fillRoundRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, color, radius); + } + + void BasicRenderer2D::fillCircle(const ostd::Vec2& center, f32 radius, const ostd::Color& color) { if (!m_initialized) return; - int segments = std::max(12, int(radius * 0.75f)); + i32 segments = std::max(12, i32(radius * 0.75f)); generate_filled_ellipse(center, radius, radius, color, segments); } @@ -638,7 +658,7 @@ namespace ogfx rect.y + rect.h * 0.5f }; - float radius = std::min(rect.w, rect.h) * 0.5f; + f32 radius = std::min(rect.w, rect.h) * 0.5f; fillCircle(center, radius, color); } @@ -652,14 +672,14 @@ namespace ogfx rect.y + rect.h * 0.5f }; - float radiusX = rect.w * 0.5f; - float radiusY = rect.h * 0.5f; + f32 radiusX = rect.w * 0.5f; + f32 radiusY = rect.h * 0.5f; - int segments = std::max(12, int(std::max(radiusX, radiusY) * 0.75f)); + i32 segments = std::max(12, i32(std::max(radiusX, radiusY) * 0.75f)); generate_filled_ellipse(center, radiusX, radiusY, color, segments); } - void BasicRenderer2D::outlinedRect(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, int32_t outlineThickness) + void BasicRenderer2D::outlinedRect(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, i32 outlineThickness) { if (!m_initialized) return; ostd::Rectangle offset = { 1, 1, -2, -2 }; @@ -667,7 +687,12 @@ namespace ogfx drawRect(rect, outlineColor, outlineThickness); } - void BasicRenderer2D::outlinedRoundRect(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, float radius, int32_t outlineThickness) + void BasicRenderer2D::outlinedRect(const ostd::Vec2& center, const ostd::Vec2& size, const ostd::Color& fillColor, const ostd::Color& outlineColor, i32 outlineThickness) + { + outlinedRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, fillColor, outlineColor, outlineThickness); + } + + void BasicRenderer2D::outlinedRoundRect(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, f32 radius, i32 outlineThickness) { if (!m_initialized) return; ostd::Rectangle offset = { 1, 1, -2, -2 }; @@ -675,14 +700,19 @@ namespace ogfx drawRoundRect(rect, outlineColor, radius, outlineThickness); } - void BasicRenderer2D::outlinedCircle(const ostd::Vec2& center, float radius, const ostd::Color& fillColor, const ostd::Color& outlineColor, int32_t outlineThickness) + void BasicRenderer2D::outlinedRoundRect(const ostd::Vec2& center, const ostd::Vec2& size, const ostd::Color& fillColor, const ostd::Color& outlineColor, f32 radius, i32 outlineThickness) + { + outlinedRoundRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, fillColor, outlineColor, radius, outlineThickness); + } + + void BasicRenderer2D::outlinedCircle(const ostd::Vec2& center, f32 radius, const ostd::Color& fillColor, const ostd::Color& outlineColor, i32 outlineThickness) { if (!m_initialized) return; fillCircle(center, radius - 1, fillColor); drawCircle(center, radius, outlineColor, outlineThickness); } - void BasicRenderer2D::outlinedCircle(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, int32_t outlineThickness) + void BasicRenderer2D::outlinedCircle(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, i32 outlineThickness) { if (!m_initialized) return; @@ -692,11 +722,11 @@ namespace ogfx rect.y + rect.h * 0.5f }; - float radius = std::min(rect.w, rect.h) * 0.5f; + f32 radius = std::min(rect.w, rect.h) * 0.5f; outlinedCircle(center, radius, fillColor, outlineColor, outlineThickness); } - void BasicRenderer2D::outlinedEllipse(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, int32_t outlineThickness) + void BasicRenderer2D::outlinedEllipse(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, i32 outlineThickness) { if (!m_initialized) return; ostd::Rectangle offset = { 1, 1, -2, -2 }; @@ -722,7 +752,7 @@ namespace ogfx i = 0; } - void BasicRenderer2D::generate_half_circle(const ostd::Vec2& center, const ostd::Vec2& dir, float radius, int segments, const ostd::Color& color) + void BasicRenderer2D::generate_half_circle(const ostd::Vec2& center, const ostd::Vec2& dir, f32 radius, i32 segments, const ostd::Color& color) { // Ensure we have room if (m_vertexCount + segments + 2 >= MaxVertices || m_indexCount + segments * 3 >= MaxIndices) @@ -731,7 +761,7 @@ namespace ogfx SDL_FColor col = COLOR_CAST(color); // Index of the center vertex - int centerIndex = m_vertexCount; + i32 centerIndex = m_vertexCount; // Push center vertex m_vertices[m_vertexCount++] = { @@ -741,20 +771,20 @@ namespace ogfx }; // Compute the base angle from the direction vector - float baseAngle = std::atan2(dir.y, dir.x); + f32 baseAngle = std::atan2(dir.y, dir.x); // Half circle spans 180 degrees - float startAngle = baseAngle - M_PI * 0.5f; - float endAngle = baseAngle + M_PI * 0.5f; + f32 startAngle = baseAngle - M_PI * 0.5f; + f32 endAngle = baseAngle + M_PI * 0.5f; // Generate arc vertices - for (int i = 0; i <= segments; i++) + for (i32 i = 0; i <= segments; i++) { - float t = float(i) / float(segments); - float angle = startAngle + t * (endAngle - startAngle); + f32 t = f32(i) / f32(segments); + f32 angle = startAngle + t * (endAngle - startAngle); - float x = center.x + std::cos(angle) * radius; - float y = center.y + std::sin(angle) * radius; + f32 x = center.x + std::cos(angle) * radius; + f32 y = center.y + std::sin(angle) * radius; m_vertices[m_vertexCount++] = { { x, y }, @@ -764,7 +794,7 @@ namespace ogfx } // Generate triangle fan indices - for (int i = 0; i < segments; i++) + for (i32 i = 0; i < segments; i++) { m_indices[m_indexCount++] = centerIndex; m_indices[m_indexCount++] = centerIndex + 1 + i; @@ -772,12 +802,12 @@ namespace ogfx } } - void BasicRenderer2D::generate_quarter_circle(const ostd::Vec2& center, float radius, float thickness, float startAngle, const ostd::Color& color, int segments) + void BasicRenderer2D::generate_quarter_circle(const ostd::Vec2& center, f32 radius, f32 thickness, f32 startAngle, const ostd::Color& color, i32 segments) { - float half = thickness * 0.5f; + f32 half = thickness * 0.5f; - float outerR = radius + half; - float innerR = radius - half; + f32 outerR = radius + half; + f32 innerR = radius - half; if (innerR < 0.0f) innerR = 0.0f; @@ -788,18 +818,18 @@ namespace ogfx SDL_FColor col = COLOR_CAST(color); - int base = m_vertexCount; + i32 base = m_vertexCount; - float endAngle = startAngle + M_PI * 0.5f; + f32 endAngle = startAngle + M_PI * 0.5f; // Generate vertices: outer arc + inner arc - for (int i = 0; i <= segments; i++) + for (i32 i = 0; i <= segments; i++) { - float t = float(i) / float(segments); - float angle = startAngle + t * (endAngle - startAngle); + f32 t = f32(i) / f32(segments); + f32 angle = startAngle + t * (endAngle - startAngle); - float cs = std::cos(angle); - float sn = std::sin(angle); + f32 cs = std::cos(angle); + f32 sn = std::sin(angle); // Outer arc m_vertices[m_vertexCount++] = { @@ -817,12 +847,12 @@ namespace ogfx } // Generate indices (triangle strip converted to triangles) - for (int i = 0; i < segments; i++) + for (i32 i = 0; i < segments; i++) { - int o0 = base + i * 2; - int i0 = o0 + 1; - int o1 = o0 + 2; - int i1 = o0 + 3; + i32 o0 = base + i * 2; + i32 i0 = o0 + 1; + i32 o1 = o0 + 2; + i32 i1 = o0 + 3; // Triangle 1 m_indices[m_indexCount++] = o0; @@ -836,12 +866,12 @@ namespace ogfx } } - void BasicRenderer2D::generate_circle_stroke(const ostd::Vec2& center, float radius, float thickness, const ostd::Color& color, int segments) + void BasicRenderer2D::generate_circle_stroke(const ostd::Vec2& center, f32 radius, f32 thickness, const ostd::Color& color, i32 segments) { - float half = thickness * 0.5f; + f32 half = thickness * 0.5f; - float outerR = radius + half; - float innerR = radius - half; + f32 outerR = radius + half; + f32 innerR = radius - half; if (innerR < 0.0f) innerR = 0.0f; @@ -851,16 +881,16 @@ namespace ogfx SDL_FColor col = COLOR_CAST(color); - int base = m_vertexCount; + i32 base = m_vertexCount; // Generate vertices: outer arc + inner arc - for (int i = 0; i <= segments; i++) + for (i32 i = 0; i <= segments; i++) { - float t = float(i) / float(segments); - float angle = t * (2.0f * M_PI); + f32 t = f32(i) / f32(segments); + f32 angle = t * (2.0f * M_PI); - float cs = std::cos(angle); - float sn = std::sin(angle); + f32 cs = std::cos(angle); + f32 sn = std::sin(angle); // Outer arc m_vertices[m_vertexCount++] = { @@ -878,12 +908,12 @@ namespace ogfx } // Generate indices (triangle strip → triangles) - for (int i = 0; i < segments; i++) + for (i32 i = 0; i < segments; i++) { - int o0 = base + i * 2; - int i0 = o0 + 1; - int o1 = o0 + 2; - int i1 = o0 + 3; + i32 o0 = base + i * 2; + i32 i0 = o0 + 1; + i32 o1 = o0 + 2; + i32 i1 = o0 + 3; // Triangle 1 m_indices[m_indexCount++] = o0; @@ -897,14 +927,14 @@ namespace ogfx } } - void BasicRenderer2D::generate_ellipse_stroke(const ostd::Vec2& center, float radiusX, float radiusY, float thickness, float startAngle, float endAngle, const ostd::Color& color, int segments) + void BasicRenderer2D::generate_ellipse_stroke(const ostd::Vec2& center, f32 radiusX, f32 radiusY, f32 thickness, f32 startAngle, f32 endAngle, const ostd::Color& color, i32 segments) { - float half = thickness * 0.5f; + f32 half = thickness * 0.5f; - float outerRX = radiusX + half; - float outerRY = radiusY + half; - float innerRX = std::max(0.0f, radiusX - half); - float innerRY = std::max(0.0f, radiusY - half); + f32 outerRX = radiusX + half; + f32 outerRY = radiusY + half; + f32 innerRX = std::max(0.0f, radiusX - half); + f32 innerRY = std::max(0.0f, radiusY - half); // Ensure capacity if (m_vertexCount + (segments + 1) * 2 >= MaxVertices || @@ -915,18 +945,18 @@ namespace ogfx SDL_FColor col = COLOR_CAST(color); - int base = m_vertexCount; + i32 base = m_vertexCount; - float angleRange = endAngle - startAngle; + f32 angleRange = endAngle - startAngle; // Generate vertices: outer arc + inner arc - for (int i = 0; i <= segments; i++) + for (i32 i = 0; i <= segments; i++) { - float t = float(i) / float(segments); - float angle = startAngle + t * angleRange; + f32 t = f32(i) / f32(segments); + f32 angle = startAngle + t * angleRange; - float cs = std::cos(angle); - float sn = std::sin(angle); + f32 cs = std::cos(angle); + f32 sn = std::sin(angle); // Outer arc m_vertices[m_vertexCount++] = { @@ -944,12 +974,12 @@ namespace ogfx } // Generate indices (triangle strip → triangles) - for (int i = 0; i < segments; i++) + for (i32 i = 0; i < segments; i++) { - int o0 = base + i * 2; - int i0 = o0 + 1; - int o1 = o0 + 2; - int i1 = o0 + 3; + i32 o0 = base + i * 2; + i32 i0 = o0 + 1; + i32 o1 = o0 + 2; + i32 i1 = o0 + 3; // Triangle 1 m_indices[m_indexCount++] = o0; @@ -963,7 +993,7 @@ namespace ogfx } } - void BasicRenderer2D::generate_filled_ellipse_stroke(const ostd::Vec2& center, float radiusX, float radiusY, float startAngle, const ostd::Color& color, int segments) + void BasicRenderer2D::generate_filled_ellipse_stroke(const ostd::Vec2& center, f32 radiusX, f32 radiusY, f32 startAngle, const ostd::Color& color, i32 segments) { // Ensure capacity if (m_vertexCount + segments + 2 >= MaxVertices || m_indexCount + segments * 3 >= MaxIndices) @@ -971,7 +1001,7 @@ namespace ogfx SDL_FColor col = COLOR_CAST(color); - int base = m_vertexCount; + i32 base = m_vertexCount; // Center vertex m_vertices[m_vertexCount++] = { @@ -980,15 +1010,15 @@ namespace ogfx { 0, 0 } }; - float endAngle = startAngle + M_PI * 0.5f; + f32 endAngle = startAngle + M_PI * 0.5f; - for (int i = 0; i <= segments; i++) + for (i32 i = 0; i <= segments; i++) { - float t = float(i) / float(segments); - float angle = startAngle + t * (endAngle - startAngle); + f32 t = f32(i) / f32(segments); + f32 angle = startAngle + t * (endAngle - startAngle); - float x = center.x + std::cos(angle) * radiusX; - float y = center.y + std::sin(angle) * radiusY; + f32 x = center.x + std::cos(angle) * radiusX; + f32 y = center.y + std::sin(angle) * radiusY; m_vertices[m_vertexCount++] = { { x, y }, @@ -998,7 +1028,7 @@ namespace ogfx } // Triangle fan indices - for (int i = 0; i < segments; i++) + for (i32 i = 0; i < segments; i++) { m_indices[m_indexCount++] = base; m_indices[m_indexCount++] = base + 1 + i; @@ -1006,7 +1036,7 @@ namespace ogfx } } - void BasicRenderer2D::generate_filled_ellipse(const ostd::Vec2& center, float radiusX, float radiusY, const ostd::Color& color, int segments) + void BasicRenderer2D::generate_filled_ellipse(const ostd::Vec2& center, f32 radiusX, f32 radiusY, const ostd::Color& color, i32 segments) { // Ensure capacity if (m_vertexCount + segments + 2 >= MaxVertices || m_indexCount + segments * 3 >= MaxIndices) @@ -1014,7 +1044,7 @@ namespace ogfx SDL_FColor col = COLOR_CAST(color); - int base = m_vertexCount; + i32 base = m_vertexCount; // Center vertex m_vertices[m_vertexCount++] = { @@ -1024,13 +1054,13 @@ namespace ogfx }; // Outer ring vertices - for (int i = 0; i <= segments; i++) + for (i32 i = 0; i <= segments; i++) { - float t = float(i) / float(segments); - float angle = t * (2.0f * M_PI); + f32 t = f32(i) / f32(segments); + f32 angle = t * (2.0f * M_PI); - float x = center.x + std::cos(angle) * radiusX; - float y = center.y + std::sin(angle) * radiusY; + f32 x = center.x + std::cos(angle) * radiusX; + f32 y = center.y + std::sin(angle) * radiusY; m_vertices[m_vertexCount++] = { { x, y }, @@ -1040,7 +1070,7 @@ namespace ogfx } // Triangle fan indices - for (int i = 0; i < segments; i++) + for (i32 i = 0; i < segments; i++) { m_indices[m_indexCount++] = base; m_indices[m_indexCount++] = base + 1 + i; @@ -1048,7 +1078,7 @@ namespace ogfx } } - void BasicRenderer2D::push_polygon(const ostd::Vec2* verts, const ostd::Vec2* texCoords, uint32_t vertCount, const uint32_t* inds, uint32_t indexCount, const ostd::Color& color, SDL_Texture* texture) + void BasicRenderer2D::push_polygon(const ostd::Vec2* verts, const ostd::Vec2* texCoords, u32 vertCount, const u32* inds, u32 indexCount, const ostd::Color& color, SDL_Texture* texture) { if (!m_initialized || vertCount <= 0 || indexCount <= 0) return; @@ -1066,9 +1096,9 @@ namespace ogfx SDL_FColor col = COLOR_CAST(color); - int base = m_vertexCount; + i32 base = m_vertexCount; bool hasTexCoords = texCoords != nullptr; - for (int i = 0; i < vertCount; i++) + for (i32 i = 0; i < vertCount; i++) { ostd::Vec2 tc { 0.0f, 0.0f }; if (hasTexCoords) @@ -1079,13 +1109,13 @@ namespace ogfx { tc.x, tc.y }, }; } - for (int i = 0; i < indexCount; i++) + for (i32 i = 0; i < indexCount; i++) m_indices[m_indexCount++] = base + inds[i]; } - void BasicRenderer2D::print_ttf_error(const ostd::String& funcName) + void BasicRenderer2D::print_ttf_error(const String& funcName) { - m_out.fg(ostd::ConsoleColors::Red).p(funcName).p("(...) failed: ").p(ostd::String(SDL_GetError())).reset().nl(); + m_out.fg(ostd::ConsoleColors::Red).p(funcName).p("(...) failed: ").p(String(SDL_GetError())).reset().nl(); } // ===================================================== PRIVATE HELPERS ===================================================== } diff --git a/src/ogfx/render/BasicRenderer.hpp b/src/ogfx/render/BasicRenderer.hpp index dfd5b0a..9ce521d 100644 --- a/src/ogfx/render/BasicRenderer.hpp +++ b/src/ogfx/render/BasicRenderer.hpp @@ -34,16 +34,16 @@ namespace ogfx { public: struct tErrors { - inline static constexpr int32_t NoError = 0; - inline static constexpr int32_t FailedToLoad = 1; - inline static constexpr int32_t FailedToOpenFontFile = 2; - inline static constexpr int32_t Uninitialized = 3; - inline static constexpr int32_t InvalidState = 5; - inline static constexpr int32_t TTFRenderTextBlendedFail = 6; - inline static constexpr int32_t TTFCreateTextureFromSurfaceFail = 7; - inline static constexpr int32_t NullFont = 8; - inline static constexpr int32_t NoFont = 9; - inline static constexpr int32_t FailedToOpenFontByteStrean = 10; + inline static constexpr i32 NoError = 0; + inline static constexpr i32 FailedToLoad = 1; + inline static constexpr i32 FailedToOpenFontFile = 2; + inline static constexpr i32 Uninitialized = 3; + inline static constexpr i32 InvalidState = 5; + inline static constexpr i32 TTFRenderTextBlendedFail = 6; + inline static constexpr i32 TTFCreateTextureFromSurfaceFail = 7; + inline static constexpr i32 NullFont = 8; + inline static constexpr i32 NoFont = 9; + inline static constexpr i32 FailedToOpenFontByteStrean = 10; }; private: class SignalHandler : public ostd::BaseObject { @@ -57,25 +57,25 @@ namespace ogfx public: inline BasicRenderer2D(void) { } ~BasicRenderer2D(void); - int32_t init(WindowCore& window); + i32 init(WindowCore& window); SDL_Renderer* getSDLRenderer(void) const; void flushBatch(void); void endFrame(void); void pushClippingRect(const ostd::Rectangle& rect, bool additive = false); void popClippingRect(void); - int32_t loadDefaultFont(int32_t fontSize = 0); + i32 loadDefaultFont(i32 fontSize = 0); void closeFont(void); - int32_t openFont(const ostd::String& fontPath, int32_t fontSize = 0); - int32_t openFont(const ostd::UByte resource_data[], uint32_t data_size, int32_t fontSize = 0); - int32_t setFontSize(int32_t fontSize); - ostd::Vec2 getStringDimensions(const ostd::String& message, int32_t fontSize = 0, TTF_Font* font = nullptr); + i32 openFont(const String& fontPath, i32 fontSize = 0); + i32 openFont(const ostd::UByte resource_data[], u32 data_size, i32 fontSize = 0); + i32 setFontSize(i32 fontSize); + ostd::Vec2 getStringDimensions(const String& message, i32 fontSize = 0, TTF_Font* font = nullptr); - inline uint32_t getDrawCallCount(void) { return m_drawCallCount; } + inline u32 getDrawCallCount(void) { return m_drawCallCount; } inline bool hasOpenFont(void) { return m_fontOpen; } inline TTF_Font* getSDLFont(void) { return m_font; } inline bool isValid(void) const { return m_initialized && m_fontOpen && (m_font != nullptr || m_fontFromMemory); } - inline int32_t geterrorState(void) { return m_errorState; } - inline int32_t getFontSize(void) { return m_fontSize; } + inline i32 geterrorState(void) { return m_errorState; } + inline i32 getFontSize(void) { return m_fontSize; } inline WindowCore& getWindow(void) { return *m_window; } inline bool isInitialized(void) { return m_initialized; } inline FontGlyphAtlas& getFontGlyphAtlas(void) { return m_fontGlyphAtlas; } @@ -83,67 +83,73 @@ namespace ogfx void drawImage(const ogfx::Image& image, const ostd::Vec2& position, const ostd::Vec2& size = { 0, 0 }, const ostd::Rectangle& srcRect = { 0, 0, 0, 0 }); void drawAnimation(const Animation& anim, const ostd::Vec2& position, const ostd::Vec2& size = { 0, 0 }); - void drawString(const ostd::String& str, const ostd::Vec2& position, const ostd::Color& color, int32_t fontSize = 0, float scale = 1.0f); - void drawCenteredString(const ostd::String& str, const ostd::Vec2& center, const ostd::Color& color, int32_t fontSize = 0, float scale = 1.0f); - void drawCenteredString(const ostd::String& str, const ostd::Rectangle& bounds, const ostd::Color& color, int32_t fontSize = 0, float scale = 1.0f); + void drawString(const String& str, const ostd::Vec2& position, const ostd::Color& color, i32 fontSize = 0, f32 scale = 1.0f); + void drawCenteredString(const String& str, const ostd::Vec2& center, const ostd::Color& color, i32 fontSize = 0, f32 scale = 1.0f); + void drawCenteredString(const String& str, const ostd::Rectangle& bounds, const ostd::Color& color, i32 fontSize = 0, f32 scale = 1.0f); + void drawLine(const ostd::FLine& line, const ostd::Color& color, i32 thickness = 1, bool rounded = true); - void drawLine(const ostd::FLine& line, const ostd::Color& color, int32_t thickness = 1, bool rounded = true); - - void drawRect(const ostd::Rectangle& rect, const ostd::Color& color, int32_t thickness = 1); - void drawRoundRect(const ostd::Rectangle& rect, const ostd::Color& color, float radius, int32_t thickness = 1); - void drawCircle(const ostd::Vec2& center, float radius, const ostd::Color& color, int32_t thickness = 1); - void drawCircle(const ostd::Rectangle& rect, const ostd::Color& color, int32_t thickness = 1); - void drawEllipse(const ostd::Rectangle& rect, const ostd::Color& color, int32_t thickness = 1); + void drawRect(const ostd::Rectangle& rect, const ostd::Color& color, i32 thickness = 1); + void drawRect(const ostd::Vec2& center, const ostd::Vec2& size, const ostd::Color& color, i32 thickness = 1); + void drawRoundRect(const ostd::Vec2& center, const ostd::Vec2& size, const ostd::Color& color, f32 radius, i32 thickness = 1); + void drawRoundRect(const ostd::Rectangle& rect, const ostd::Color& color, f32 radius, i32 thickness = 1); + void drawCircle(const ostd::Vec2& center, f32 radius, const ostd::Color& color, i32 thickness = 1); + void drawCircle(const ostd::Rectangle& rect, const ostd::Color& color, i32 thickness = 1); + void drawEllipse(const ostd::Rectangle& rect, const ostd::Color& color, i32 thickness = 1); void fillRect(const ostd::Rectangle& rect, const ostd::Color& color); - void fillRoundRect(const ostd::Rectangle& rect, const ostd::Color& color, float radius); - void fillCircle(const ostd::Vec2& center, float radius, const ostd::Color& color); + void fillRect(const ostd::Vec2& center, const ostd::Vec2& size, const ostd::Color& color); + void fillRoundRect(const ostd::Rectangle& rect, const ostd::Color& color, f32 radius); + void fillRoundRect(const ostd::Vec2& center, const ostd::Vec2& size, const ostd::Color& color, f32 radius); + void fillCircle(const ostd::Vec2& center, f32 radius, const ostd::Color& color); void fillCircle(const ostd::Rectangle& rect, const ostd::Color& color); void fillEllipse(const ostd::Rectangle& rect, const ostd::Color& color); - void outlinedRect(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, int32_t outlineThickness = 1); - void outlinedRoundRect(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, float radius, int32_t outlineThickness = 1); - void outlinedCircle(const ostd::Vec2& center, float radius, const ostd::Color& fillColor, const ostd::Color& outlineColor, int32_t outlineThickness = 1); - void outlinedCircle(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, int32_t outlineThickness = 1); - void outlinedEllipse(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, int32_t outlineThickness = 1); + void outlinedRect(const ostd::Vec2& center, const ostd::Vec2& size, const ostd::Color& fillColor, const ostd::Color& outlineColor, i32 outlineThickness = 1); + void outlinedRect(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, i32 outlineThickness = 1); + void outlinedRoundRect(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, f32 radius, i32 outlineThickness = 1); + void outlinedRoundRect(const ostd::Vec2& center, const ostd::Vec2& size, const ostd::Color& fillColor, const ostd::Color& outlineColor, f32 radius, i32 outlineThickness = 1); + void outlinedCircle(const ostd::Vec2& center, f32 radius, const ostd::Color& fillColor, const ostd::Color& outlineColor, i32 outlineThickness = 1); + void outlinedCircle(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, i32 outlineThickness = 1); + void outlinedEllipse(const ostd::Rectangle& rect, const ostd::Color& fillColor, const ostd::Color& outlineColor, i32 outlineThickness = 1); private: void init_arrays(void); - void generate_half_circle(const ostd::Vec2& center, const ostd::Vec2& dir, float radius, int segments, const ostd::Color& color); - void generate_quarter_circle(const ostd::Vec2& center, float radius, float thickness, float startAngle, const ostd::Color& color, int segments); - void generate_circle_stroke(const ostd::Vec2& center, float radius, float thickness, const ostd::Color& color, int segments); - void generate_ellipse_stroke(const ostd::Vec2& center, float radiusX, float radiusY, float thickness, float startAngle, float endAngle, const ostd::Color& color, int segments); - void generate_filled_ellipse_stroke(const ostd::Vec2& center, float radiusX, float radiusY, float startAngle, const ostd::Color& color, int segments); - void generate_filled_ellipse(const ostd::Vec2& center, float radiusX, float radiusY, const ostd::Color& color, int segments); - void push_polygon(const ostd::Vec2* verts, const ostd::Vec2* texCoords, uint32_t vertCount, const uint32_t* inds, uint32_t indexCount, const ostd::Color& color, SDL_Texture* texture); - void print_ttf_error(const ostd::String& funcName); - inline int32_t set_error_state(int32_t err) { m_errorState = err; return m_errorState; } + void generate_half_circle(const ostd::Vec2& center, const ostd::Vec2& dir, f32 radius, i32 segments, const ostd::Color& color); + void generate_quarter_circle(const ostd::Vec2& center, f32 radius, f32 thickness, f32 startAngle, const ostd::Color& color, i32 segments); + void generate_circle_stroke(const ostd::Vec2& center, f32 radius, f32 thickness, const ostd::Color& color, i32 segments); + void generate_ellipse_stroke(const ostd::Vec2& center, f32 radiusX, f32 radiusY, f32 thickness, f32 startAngle, f32 endAngle, const ostd::Color& color, i32 segments); + void generate_filled_ellipse_stroke(const ostd::Vec2& center, f32 radiusX, f32 radiusY, f32 startAngle, const ostd::Color& color, i32 segments); + void generate_filled_ellipse(const ostd::Vec2& center, f32 radiusX, f32 radiusY, const ostd::Color& color, i32 segments); + void push_polygon(const ostd::Vec2* verts, const ostd::Vec2* texCoords, u32 vertCount, const u32* inds, u32 indexCount, const ostd::Color& color, SDL_Texture* texture); + void print_ttf_error(const String& funcName); + inline i32 set_error_state(i32 err) { m_errorState = err; return m_errorState; } public: - inline static constexpr int32_t MaxVertices { 8192 }; - inline static constexpr int32_t MaxIndices { (int32_t)(MaxVertices * 1.5f) }; + inline static constexpr i32 MaxVertices { 8192 }; + inline static constexpr i32 MaxIndices { (i32)(MaxVertices * 1.5f) }; private: WindowCore* m_window { nullptr }; ostd::ConsoleOutputHandler m_out; bool m_initialized { false }; - std::vector m_clipStack; + stdvec m_clipStack; std::array m_vertices; - std::array m_indices; - int32_t m_vertexCount { 0 }; - int32_t m_indexCount { 0 }; + std::array m_indices; + i32 m_vertexCount { 0 }; + i32 m_indexCount { 0 }; SDL_Texture* m_texture { nullptr }; - uint32_t m_drawCallCount { 0 }; + u32 m_drawCallCount { 0 }; bool m_fontOpen { false }; TTF_Font* m_font { nullptr }; - int32_t m_errorState { tErrors::NoError }; - int32_t m_fontSize { DefaultFontSize }; + i32 m_errorState { tErrors::NoError }; + i32 m_fontSize { DefaultFontSize }; bool m_fontFromMemory { false }; FontGlyphAtlas m_fontGlyphAtlas; + SignalHandler m_sigHandler { *this }; - inline static constexpr int32_t DefaultFontSize { 16 }; + inline static constexpr i32 DefaultFontSize { 16 }; }; } diff --git a/src/ogfx/render/FontGlyphAtlas.cpp b/src/ogfx/render/FontGlyphAtlas.cpp index 529486d..6f9b0ee 100644 --- a/src/ogfx/render/FontGlyphAtlas.cpp +++ b/src/ogfx/render/FontGlyphAtlas.cpp @@ -31,14 +31,14 @@ namespace ogfx { m_renderer = &renderer; m_uvs.reserve(4096); - for (int32_t i = 0; i < FontGlyphAtlas::MaxAtlasCount; i++) + for (i32 i = 0; i < FontGlyphAtlas::MaxAtlasCount; i++) m_atlases[i] = nullptr; m_currentAtlasCount = 0; create_new_atlas(); return *this; } - const std::vector FontGlyphAtlas::processString(const ostd::String& str, TTF_Font* font, uint32_t fontSize) + const stdvec FontGlyphAtlas::processString(const String& str, TTF_Font* font, u32 fontSize) { if (m_currentAtlasCount <= 0) return {}; @@ -47,24 +47,24 @@ namespace ogfx for (auto& c : str) { const GlyphInfo* dummy; - if (!rasterize_glyph(ostd::String("").addChar(c), font, fontSize, &dummy)) + if (!rasterize_glyph(String("").addChar(c), font, fontSize, &dummy)) return {}; } // Pass 2: collect stable pointers (no more insertions, no rehash risk) - std::vector glyphs; + stdvec glyphs; glyphs.reserve(str.len()); for (auto& c : str) { - auto cps = ostd::String("").addChar(c).getUTF8Codepoints(); + auto cps = String("").addChar(c).getUTF8Codepoints(); if (cps.size() != 1) return {}; - GlyphKey key { cps[0], uint64_t(font), fontSize }; + GlyphKey key { cps[0], u64(font), fontSize }; glyphs.push_back(&m_uvs[key]); } return glyphs; } - bool FontGlyphAtlas::rasterize_glyph(const ostd::String& glyphStr, TTF_Font* font, uint32_t fontSize, const GlyphInfo** outGlyph) + bool FontGlyphAtlas::rasterize_glyph(const String& glyphStr, TTF_Font* font, u32 fontSize, const GlyphInfo** outGlyph) { if (!font || m_currentAtlasCount <= 0) return false; @@ -73,9 +73,9 @@ namespace ogfx if (cps.size() != 1) return false; - uint32_t codepoint = cps[0]; + u32 codepoint = cps[0]; - GlyphKey key { codepoint, uint64_t(font), fontSize }; + GlyphKey key { codepoint, u64(font), fontSize }; auto it = m_uvs.find(key); if (it != m_uvs.end()) { @@ -87,10 +87,10 @@ namespace ogfx if (!surf) return false; - int gw = surf->w; - int gh = surf->h; + i32 gw = surf->w; + i32 gh = surf->h; - int minx, maxx, miny, maxy, advance; + i32 minx, maxx, miny, maxy, advance; TTF_GetGlyphMetrics(font, codepoint, &minx, &maxx, &miny, &maxy, &advance); GlyphInfo glyph; @@ -99,14 +99,14 @@ namespace ogfx SDL_Texture* atlas = m_atlases[m_currentAtlasCount - 1]; - if (m_penX + gw > int(AtlasTextureDimension)) + if (m_penX + gw > i32(AtlasTextureDimension)) { m_penX = 0; m_penY += m_rowHeight; m_rowHeight = 0; } - if (m_penY + gh > int(AtlasTextureDimension)) + if (m_penY + gh > i32(AtlasTextureDimension)) { SDL_DestroySurface(surf); @@ -126,17 +126,17 @@ namespace ogfx SDL_DestroySurface(surf); - float u0 = float(m_penX) / float(AtlasTextureDimension); - float v0 = float(m_penY) / float(AtlasTextureDimension); - float u1 = float(m_penX + gw) / float(AtlasTextureDimension); - float v1 = float(m_penY + gh) / float(AtlasTextureDimension); + f32 u0 = f32(m_penX) / f32(AtlasTextureDimension); + f32 v0 = f32(m_penY) / f32(AtlasTextureDimension); + f32 u1 = f32(m_penX + gw) / f32(AtlasTextureDimension); + f32 v1 = f32(m_penY + gh) / f32(AtlasTextureDimension); glyph.atlas = atlas; glyph.uvs[0] = { u0, v0 }; glyph.uvs[1] = { u1, v0 }; glyph.uvs[2] = { u1, v1 }; glyph.uvs[3] = { u0, v1 }; - glyph.size = { static_cast(gw), static_cast(gh) }; + glyph.size = { cast(gw), cast(gh) }; m_uvs[key] = glyph; *outGlyph = &(m_uvs[key]); @@ -148,7 +148,7 @@ namespace ogfx bool FontGlyphAtlas::create_new_atlas(void) { - if (m_currentAtlasCount >= int(MaxAtlasCount)) + if (m_currentAtlasCount >= i32(MaxAtlasCount)) return false; if (!m_renderer) @@ -168,7 +168,7 @@ namespace ogfx { // Clear the texture to transparent void* pixels = nullptr; - int pitch = 0; + i32 pitch = 0; if (SDL_LockTexture(tex, nullptr, &pixels, &pitch) == 0) { memset(pixels, 0x00, pitch * AtlasTextureDimension); diff --git a/src/ogfx/render/FontGlyphAtlas.hpp b/src/ogfx/render/FontGlyphAtlas.hpp index a090e8d..a113dc1 100644 --- a/src/ogfx/render/FontGlyphAtlas.hpp +++ b/src/ogfx/render/FontGlyphAtlas.hpp @@ -34,14 +34,14 @@ namespace ogfx ostd::Vec2 uvs[4]; SDL_Texture* atlas { nullptr }; ostd::Vec2 size; - uint32_t codepoint { 0 }; - int32_t advance { 0 }; + u32 codepoint { 0 }; + i32 advance { 0 }; }; struct GlyphKey { - uint32_t codepoint; - uint64_t fontID; - uint32_t pixelSize; + u32 codepoint; + u64 fontID; + u32 pixelSize; bool operator==(const GlyphKey& other) const noexcept { @@ -54,9 +54,9 @@ namespace ogfx { size_t operator()(const GlyphKey& k) const noexcept { - size_t h = std::hash()(k.codepoint); - h ^= std::hash()(k.fontID) + 0x9e3779b9 + (h << 6) + (h >> 2); - h ^= std::hash()(k.pixelSize) + 0x9e3779b9 + (h << 6) + (h >> 2); + size_t h = std::hash()(k.codepoint); + h ^= std::hash()(k.fontID) + 0x9e3779b9 + (h << 6) + (h >> 2); + h ^= std::hash()(k.pixelSize) + 0x9e3779b9 + (h << 6) + (h >> 2); return h; } }; @@ -64,23 +64,23 @@ namespace ogfx inline FontGlyphAtlas(void) { } inline FontGlyphAtlas(BasicRenderer2D& renderer) { init(renderer); } FontGlyphAtlas init(BasicRenderer2D& renderer); - const std::vector processString(const ostd::String& str, TTF_Font* font, uint32_t fontSize); + const stdvec processString(const String& str, TTF_Font* font, u32 fontSize); private: - bool rasterize_glyph(const ostd::String& glyphStr, TTF_Font* font, uint32_t fontSize, const GlyphInfo** outGlyph); + bool rasterize_glyph(const String& glyphStr, TTF_Font* font, u32 fontSize, const GlyphInfo** outGlyph); bool create_new_atlas(void); public: - inline static constexpr uint32_t AtlasTextureDimension { 8192 }; - inline static constexpr uint32_t MaxAtlasCount { 16 }; + inline static constexpr u32 AtlasTextureDimension { 8192 }; + inline static constexpr u32 MaxAtlasCount { 16 }; public: std::unordered_map m_uvs; SDL_Texture* m_atlases[FontGlyphAtlas::MaxAtlasCount]; - int32_t m_currentAtlasCount { 0 }; + i32 m_currentAtlasCount { 0 }; BasicRenderer2D* m_renderer { nullptr }; - int32_t m_penX { 0 }; - int32_t m_penY { 0 }; - int32_t m_rowHeight { 0 }; + i32 m_penX { 0 }; + i32 m_penY { 0 }; + i32 m_rowHeight { 0 }; }; } diff --git a/src/ogfx/render/PixelRenderer.cpp b/src/ogfx/render/PixelRenderer.cpp index 43d518c..2f63700 100644 --- a/src/ogfx/render/PixelRenderer.cpp +++ b/src/ogfx/render/PixelRenderer.cpp @@ -31,18 +31,18 @@ namespace ogfx characterMap[c] = getCharacterIndex(c); } - bool PixelRenderer::TextRenderer::drawString(ostd::String str, uint32_t column, uint32_t row, uint32_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint32_t* fontPixels, ostd::Color color, ostd::Color background) + bool PixelRenderer::TextRenderer::drawString(const String& str, u32 column, u32 row, u32* screenPixels, i32 screenWidth, i32 screenHeight, u32* fontPixels, const ostd::Color& color, const ostd::Color& background) { - ostd::String se(str); + String se(str); if (se == "") return false; if (row >= CONSOLE_CHARS_V) return false; if (column >= CONSOLE_CHARS_H) return false; if (column + str.len() > CONSOLE_CHARS_H) return false; - int32_t x = column * FONT_CHAR_W; - int32_t y = row * FONT_CHAR_H; + i32 x = column * FONT_CHAR_W; + i32 y = row * FONT_CHAR_H; for (auto& c : str) { - drawCharacter((uint8_t*)screenPixels, screenWidth, screenHeight, (uint8_t*)fontPixels, x, y, c, color, background); + drawCharacter((u8*)screenPixels, screenWidth, screenHeight, (u8*)fontPixels, x, y, c, color, background); x += FONT_CHAR_W; } s_cursor_pos_x = x; @@ -51,11 +51,11 @@ namespace ogfx return true; } - int32_t PixelRenderer::TextRenderer::getCharacterIndex(char c) + i32 PixelRenderer::TextRenderer::getCharacterIndex(char c) { using namespace ostd; - int32_t charIndex = (int)c - 32; + i32 charIndex = (i32)c - 32; IPoint charCoords = CONVERT_1D_2D(charIndex, FONT_H_CHARS); charCoords.x *= FONT_CHAR_W * 4; charCoords.y *= FONT_CHAR_H; @@ -64,37 +64,37 @@ namespace ogfx return charIndex; } - ostd::Color PixelRenderer::TextRenderer::applyTint(ostd::Color baseColor, ostd::Color tintColor) + ostd::Color PixelRenderer::TextRenderer::applyTint(const ostd::Color& baseColor, const ostd::Color& tintColor) { auto nBase = baseColor.getNormalizedColor(); auto nTint = tintColor.getNormalizedColor(); - float r = nBase.r * nTint.r; - float g = nBase.r * nTint.g; - float b = nBase.r * nTint.b; + f32 r = nBase.r * nTint.r; + f32 g = nBase.r * nTint.g; + f32 b = nBase.r * nTint.b; ostd::Color::FloatCol nTinted(r, g, b, 1.0f); return ostd::Color(nTinted); } - void PixelRenderer::TextRenderer::drawCharacter(uint8_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint8_t* fontPixels, int32_t x, int32_t y, char c, ostd::Color color, ostd::Color background) + void PixelRenderer::TextRenderer::drawCharacter(u8* screenPixels, i32 screenWidth, i32 screenHeight, u8* fontPixels, i32 x, i32 y, char c, const ostd::Color& color, const ostd::Color& background) { using namespace ostd; - int32_t charIndex = characterMap[c]; + i32 charIndex = characterMap[c]; IPoint charCoords = CONVERT_1D_2D(charIndex, (FONT_CHAR_W * FONT_H_CHARS * 4)); - int32_t screenx = x * 4, screeny = y; + i32 screenx = x * 4, screeny = y; ostd::Color tintedColor; bool applyBackground = false; - for (int32_t y = charCoords.y; y < charCoords.y + (FONT_CHAR_H); y += 1) + for (i32 y = charCoords.y; y < charCoords.y + (FONT_CHAR_H); y += 1) { - for (int32_t x = charCoords.x; x < charCoords.x + (FONT_CHAR_W * 4); x += 4) + for (i32 x = charCoords.x; x < charCoords.x + (FONT_CHAR_W * 4); x += 4) { - int32_t index = CONVERT_2D_1D(x, y, (FONT_CHAR_W * FONT_H_CHARS * 4)); - int32_t screenIndex = CONVERT_2D_1D(screenx, screeny, (screenWidth * 4)); + i32 index = CONVERT_2D_1D(x, y, (FONT_CHAR_W * FONT_H_CHARS * 4)); + i32 screenIndex = CONVERT_2D_1D(screenx, screeny, (screenWidth * 4)); screenx += 4; if (fontPixels[index] == 0x00 && fontPixels[index + 1] == 0x00 && fontPixels[index + 2] == 0x00) { @@ -138,7 +138,7 @@ namespace ogfx if (!parent.isValid() || !parent.isInitialized()) return; //TODO: Error m_parent = &parent; - m_pixels = ostd::Memory::createArray(parent.getWindowWidth() * parent.getWindowHeight()); + m_pixels = ostd::Memory::createArray(parent.getWindowWidth() * parent.getWindowHeight()); m_texture = SDL_CreateTexture(parent.getSDLRenderer(), SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, parent.getWindowWidth(), parent.getWindowHeight()); m_windowWidth = parent.getWindowWidth(); m_windowHeight = parent.getWindowHeight(); @@ -153,7 +153,7 @@ namespace ogfx if (isInvalid()) return; if (signal.ID == ostd::BuiltinSignals::WindowResized) { - m_pixels = ostd::Memory::resizeArray(m_pixels, m_parent->getWindowWidth() * m_parent->getWindowHeight()); + m_pixels = ostd::Memory::resizeArray(m_pixels, m_parent->getWindowWidth() * m_parent->getWindowHeight()); SDL_DestroyTexture(m_texture); m_texture = SDL_CreateTexture(m_parent->getSDLRenderer(), SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, m_parent->getWindowWidth(), m_parent->getWindowHeight()); m_windowWidth = m_parent->getWindowWidth(); @@ -172,18 +172,18 @@ namespace ogfx void PixelRenderer::displayBuffer(void) { if (isInvalid()) return; - SDL_FRect rect { 0, 0, static_cast(m_windowWidth), static_cast(m_windowHeight) }; + SDL_FRect rect { 0, 0, cast(m_windowWidth), cast(m_windowHeight) }; SDL_RenderTexture(m_parent->getSDLRenderer(), m_texture, NULL, &rect); } void PixelRenderer::clear(const ostd::Color& color) { if (isInvalid()) return; - for (int32_t y = 0; y < m_windowHeight; y++) + for (i32 y = 0; y < m_windowHeight; y++) { - for (uint32_t x = 0; x < m_windowWidth; x++) + for (u32 x = 0; x < m_windowWidth; x++) { - int32_t index = CONVERT_2D_1D(x, y, m_windowWidth); + i32 index = CONVERT_2D_1D(x, y, m_windowWidth); m_pixels[index] = color.asInteger(ostd::Color::eColorFormat::ARGB); } } diff --git a/src/ogfx/render/PixelRenderer.hpp b/src/ogfx/render/PixelRenderer.hpp index 700c21b..41080f6 100644 --- a/src/ogfx/render/PixelRenderer.hpp +++ b/src/ogfx/render/PixelRenderer.hpp @@ -24,7 +24,7 @@ #include #include #include -#include + namespace ogfx { @@ -34,42 +34,42 @@ namespace ogfx public: class TextRenderer { private: - inline static std::unordered_map characterMap; + inline static stdumap characterMap; public: static void initialize(void); - static bool drawString(ostd::String str, uint32_t column, uint32_t row, uint32_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint32_t* fontPixels, ostd::Color color = { 255, 255, 255, 255 }, ostd::Color background = { 255, 255, 255, 0 }); + static bool drawString(const String& str, u32 column, u32 row, u32* screenPixels, i32 screenWidth, i32 screenHeight, u32* fontPixels, const ostd::Color& color = { 255, 255, 255, 255 }, const ostd::Color& background = { 255, 255, 255, 0 }); private: - static int32_t getCharacterIndex(char c); - static ostd::Color applyTint(ostd::Color baseColor, ostd::Color tintColor); - static void drawCharacter(uint8_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint8_t* fontPixels, int32_t x, int32_t y, char c, ostd::Color color = { 255, 255, 255, 255 }, ostd::Color background = { 255, 255, 255, 0 }); + static i32 getCharacterIndex(char c); + static ostd::Color applyTint(const ostd::Color& baseColor, const ostd::Color& tintColor); + static void drawCharacter(u8* screenPixels, i32 screenWidth, i32 screenHeight, u8* fontPixels, i32 x, i32 y, char c, const ostd::Color& color = { 255, 255, 255, 255 }, const ostd::Color& background = { 255, 255, 255, 0 }); public: - inline static constexpr int32_t FONT_CHAR_W = 11; - inline static constexpr int32_t FONT_CHAR_H = 26; - inline static constexpr int32_t FONT_V_CHARS = 6; - inline static constexpr int32_t FONT_H_CHARS = 16; - inline static constexpr int32_t CONSOLE_CHARS_H = 90; - inline static constexpr int32_t CONSOLE_CHARS_V = 21; + inline static constexpr i32 FONT_CHAR_W = 11; + inline static constexpr i32 FONT_CHAR_H = 26; + inline static constexpr i32 FONT_V_CHARS = 6; + inline static constexpr i32 FONT_H_CHARS = 16; + inline static constexpr i32 CONSOLE_CHARS_H = 90; + inline static constexpr i32 CONSOLE_CHARS_V = 21; - inline static int8_t s_cursor_pos_x = 0; + inline static i8 s_cursor_pos_x = 0; }; public: class Font { public: inline Font(void) { } - inline Font(const ostd::String& fontPath) + inline Font(const String& fontPath) { init(fontPath); } - inline void init(const ostd::String& fontPath) + inline void init(const String& fontPath) { ostd::ConsoleOutputHandler out; m_fontSurface = SDL_LoadBMP(fontPath.c_str()); if (m_fontSurface == NULL) out.bg(ostd::ConsoleColors::Red).p("Error loading pixel font.").reset().nl(); - m_fontPixels = (uint32_t*)m_fontSurface->pixels; + m_fontPixels = (u32*)m_fontSurface->pixels; } inline ~Font(void) { @@ -78,7 +78,7 @@ namespace ogfx public: SDL_Surface* m_fontSurface { nullptr }; - uint32_t* m_fontPixels { nullptr }; + u32* m_fontPixels { nullptr }; }; public: inline PixelRenderer(void) { invalidate(); } @@ -87,15 +87,15 @@ namespace ogfx void handleSignal(ostd::Signal& signal) override; void updateBuffer(void); void displayBuffer(void); - inline uint32_t* getScreenPixels(void) { return m_pixels; } + inline u32* getScreenPixels(void) { return m_pixels; } void clear(const ostd::Color& color); private: - uint32_t* m_pixels { nullptr }; + u32* m_pixels { nullptr }; SDL_Texture* m_texture { nullptr }; WindowCore* m_parent { nullptr }; - int32_t m_windowWidth { 0 }; - int32_t m_windowHeight { 0 }; + i32 m_windowWidth { 0 }; + i32 m_windowHeight { 0 }; }; } diff --git a/src/ogfx/resources/Image.cpp b/src/ogfx/resources/Image.cpp index f05f635..5f1cb0a 100644 --- a/src/ogfx/resources/Image.cpp +++ b/src/ogfx/resources/Image.cpp @@ -34,7 +34,7 @@ namespace ogfx m_height = 0; } - Image& Image::loadFromFile(const ostd::String& filePath, BasicRenderer2D& gfx) + Image& Image::loadFromFile(const String& filePath, BasicRenderer2D& gfx) { if (!gfx.isInitialized()) return *this; //TODO: Error diff --git a/src/ogfx/resources/Image.hpp b/src/ogfx/resources/Image.hpp index 7156e46..3ab631b 100644 --- a/src/ogfx/resources/Image.hpp +++ b/src/ogfx/resources/Image.hpp @@ -31,18 +31,18 @@ namespace ogfx { public: inline Image(void) { invalidate(); } - inline Image(const ostd::String& filePath, BasicRenderer2D& gfx) { loadFromFile(filePath, gfx); } + inline Image(const String& filePath, BasicRenderer2D& gfx) { loadFromFile(filePath, gfx); } inline ~Image(void) { destroy(); } void destroy(void); - Image& loadFromFile(const ostd::String& filePath, BasicRenderer2D& gfx); + Image& loadFromFile(const String& filePath, BasicRenderer2D& gfx); inline ostd::Vec2 getSize(void) const { return { m_width, m_height }; } inline bool isLoaded(void) const { return m_loaded; } inline SDL_Texture* getSDLTexture(void) const { return m_sdl_texture; } private: SDL_Texture* m_sdl_texture { nullptr }; - float m_width { 0 }; - float m_height { 0 }; + f32 m_width { 0 }; + f32 m_height { 0 }; bool m_loaded { false }; }; } diff --git a/src/ogfx/resources/UbuntuMonoRegularTTF.cpp b/src/ogfx/resources/UbuntuMonoRegularTTF.cpp index 54770c0..8eb1801 100644 --- a/src/ogfx/resources/UbuntuMonoRegularTTF.cpp +++ b/src/ogfx/resources/UbuntuMonoRegularTTF.cpp @@ -35,7 +35,7 @@ namespace ogfx { - const uint32_t ubuntu_mono_regular_ttf_size = 189892; + const u32 ubuntu_mono_regular_ttf_size = 189892; const ostd::UByte ubuntu_mono_regular_ttf_data[189892] = { 0, 1, 0, 0, 0, 16, 1, 0, 0, 4, 0, 0, 71, 83, 85, 66, 172, 54, 149, 231, 0, 0, 34, 204, 0, 0, 16, 50, 79, 83, 47, 50, 136, 193, 253, 210, 0, 0, 1, 144, diff --git a/src/ogfx/resources/UbuntuMonoRegularTTF.hpp b/src/ogfx/resources/UbuntuMonoRegularTTF.hpp index d0ea5e2..14cf7b6 100644 --- a/src/ogfx/resources/UbuntuMonoRegularTTF.hpp +++ b/src/ogfx/resources/UbuntuMonoRegularTTF.hpp @@ -24,6 +24,6 @@ namespace ogfx { - extern const uint32_t ubuntu_mono_regular_ttf_size; + extern const u32 ubuntu_mono_regular_ttf_size; extern const ostd::UByte ubuntu_mono_regular_ttf_data[]; } diff --git a/src/ogfx/utils/Animation.cpp b/src/ogfx/utils/Animation.cpp index 94064d2..3cb9cb5 100644 --- a/src/ogfx/utils/Animation.cpp +++ b/src/ogfx/utils/Animation.cpp @@ -28,7 +28,7 @@ namespace ogfx create(0, 0, 0, 0, 0); } - Animation::Animation(int frames, int columns, int rows, int frame_width, int frame_height) + Animation::Animation(i32 frames, i32 columns, i32 rows, i32 frame_width, i32 frame_height) { create(frames, columns, rows, frame_width, frame_height); } @@ -49,7 +49,7 @@ namespace ogfx m_random = false; } - void Animation::create(int frames, int columns, int rows, int frame_width, int frame_height) + void Animation::create(i32 frames, i32 columns, i32 rows, i32 frame_width, i32 frame_height) { m_frames = frames; m_columns = columns; @@ -107,11 +107,11 @@ namespace ogfx } else if (m_still) m_current_frame = 1; //TODO: Hardcoded value - int x = ((m_current_frame % m_columns) + m_column_offset) * m_frame_width; - int y = m_row_offset * m_frame_height; + i32 x = ((m_current_frame % m_columns) + m_column_offset) * m_frame_width; + i32 y = m_row_offset * m_frame_height; if (m_rows > 1) y = ((m_current_frame / m_columns) + m_row_offset) * m_frame_height; - m_frame_rect = { static_cast(x), static_cast(y), static_cast(m_frame_width), static_cast(m_frame_height) }; + m_frame_rect = { cast(x), cast(y), cast(m_frame_width), cast(m_frame_height) }; } } diff --git a/src/ogfx/utils/Animation.hpp b/src/ogfx/utils/Animation.hpp index fa7413d..8654742 100644 --- a/src/ogfx/utils/Animation.hpp +++ b/src/ogfx/utils/Animation.hpp @@ -29,18 +29,18 @@ namespace ogfx class Animation { public: struct AnimationData { - int32_t length; - int32_t speed; - int32_t still_frame; + i32 length; + i32 speed; + i32 still_frame; - int32_t row_offset; - int32_t column_offset; + i32 row_offset; + i32 column_offset; - int32_t rows; - int32_t columns; + i32 rows; + i32 columns; - int32_t frame_width; - int32_t frame_height; + i32 frame_width; + i32 frame_height; bool still; bool backwards; @@ -64,28 +64,28 @@ namespace ogfx }; public: Animation(void); - Animation(int32_t frames, int32_t columns, int32_t rows, int32_t frame_width, int32_t frame_height); + Animation(i32 frames, i32 columns, i32 rows, i32 frame_width, i32 frame_height); Animation(AnimationData& ad); - void create(int32_t frames, int32_t columns, int32_t rows, int32_t frame_width, int32_t frame_height); + void create(i32 frames, i32 columns, i32 rows, i32 frame_width, i32 frame_height); void create(AnimationData& ad); void update(void); void resetAnimation(void); - inline void setFrameNumber(int32_t n) { m_frames = n; } - inline void setColumnNumber(int32_t n) { m_columns = n; } + inline void setFrameNumber(i32 n) { m_frames = n; } + inline void setColumnNumber(i32 n) { m_columns = n; } inline void setBackwards(bool b) { m_backwards = b; } - inline void setSpeed(int32_t d) { m_frame_time = d; } - inline void setColumnOffset(int32_t o) { m_column_offset = o; } - inline void setRowOffset(int32_t o) { m_row_offset = o; } + inline void setSpeed(i32 d) { m_frame_time = d; } + inline void setColumnOffset(i32 o) { m_column_offset = o; } + inline void setRowOffset(i32 o) { m_row_offset = o; } inline void setStill(bool s) { m_still = s; } inline void setSpriteSheet(Image& img) { m_spriteSheet = &img; } - inline int32_t getFrameNumber(void) const { return m_frames; } - inline int32_t getColumnNumber(void) const { return m_columns; } + inline i32 getFrameNumber(void) const { return m_frames; } + inline i32 getColumnNumber(void) const { return m_columns; } inline bool getBackwards(void) const { return m_backwards; } - inline int32_t getDelay(void) const { return m_frame_time; } - inline int32_t getColumnOffset(void) const { return m_column_offset; } - inline int32_t getRowOffset(void) const { return m_row_offset; } + inline i32 getDelay(void) const { return m_frame_time; } + inline i32 getColumnOffset(void) const { return m_column_offset; } + inline i32 getRowOffset(void) const { return m_row_offset; } inline bool isStill(void) const { return m_still; } inline ostd::Rectangle getFrameRect(void) const { return m_frame_rect; } inline const Image& getSpriteSheet(void) const { return (m_spriteSheet != nullptr ? *m_spriteSheet : InvalidImage); } @@ -96,18 +96,18 @@ namespace ogfx Image* m_spriteSheet { nullptr }; inline static Image InvalidImage; - int32_t m_frames; - int32_t m_rows; - int32_t m_columns; - int32_t m_frame_width; - int32_t m_frame_height; + i32 m_frames; + i32 m_rows; + i32 m_columns; + i32 m_frame_width; + i32 m_frame_height; - int32_t m_column_offset; - int32_t m_row_offset; + i32 m_column_offset; + i32 m_row_offset; - int32_t m_frame_time; - int32_t m_current_time; - int32_t m_current_frame; + i32 m_frame_time; + i32 m_current_time; + i32 m_current_frame; bool m_backwards; bool m_back; diff --git a/src/ogfx/utils/Keycodes.hpp b/src/ogfx/utils/Keycodes.hpp index 5b590cd..9754023 100644 --- a/src/ogfx/utils/Keycodes.hpp +++ b/src/ogfx/utils/Keycodes.hpp @@ -26,261 +26,261 @@ namespace ogfx { struct KeyCode { - inline static constexpr uint32_t Unknown { SDLK_UNKNOWN }; - inline static constexpr uint32_t Return { SDLK_RETURN }; - inline static constexpr uint32_t Escape { SDLK_ESCAPE }; - inline static constexpr uint32_t Backspace { SDLK_BACKSPACE }; - inline static constexpr uint32_t Tab { SDLK_TAB }; - inline static constexpr uint32_t Space { SDLK_SPACE }; - inline static constexpr uint32_t Exclaim { SDLK_EXCLAIM }; - inline static constexpr uint32_t Dblapostrophe { SDLK_DBLAPOSTROPHE }; - inline static constexpr uint32_t Hash { SDLK_HASH }; - inline static constexpr uint32_t Dollar { SDLK_DOLLAR }; - inline static constexpr uint32_t Percent { SDLK_PERCENT }; - inline static constexpr uint32_t Ampersand { SDLK_AMPERSAND }; - inline static constexpr uint32_t Apostrophe { SDLK_APOSTROPHE }; - inline static constexpr uint32_t Leftparen { SDLK_LEFTPAREN }; - inline static constexpr uint32_t Rightparen { SDLK_RIGHTPAREN }; - inline static constexpr uint32_t Asterisk { SDLK_ASTERISK }; - inline static constexpr uint32_t Plus { SDLK_PLUS }; - inline static constexpr uint32_t Comma { SDLK_COMMA }; - inline static constexpr uint32_t Minus { SDLK_MINUS }; - inline static constexpr uint32_t Period { SDLK_PERIOD }; - inline static constexpr uint32_t Slash { SDLK_SLASH }; - inline static constexpr uint32_t Num0 { SDLK_0 }; - inline static constexpr uint32_t Num1 { SDLK_1 }; - inline static constexpr uint32_t Num2 { SDLK_2 }; - inline static constexpr uint32_t Num3 { SDLK_3 }; - inline static constexpr uint32_t Num4 { SDLK_4 }; - inline static constexpr uint32_t Num5 { SDLK_5 }; - inline static constexpr uint32_t Num6 { SDLK_6 }; - inline static constexpr uint32_t Num7 { SDLK_7 }; - inline static constexpr uint32_t Num8 { SDLK_8 }; - inline static constexpr uint32_t Num9 { SDLK_9 }; - inline static constexpr uint32_t Colon { SDLK_COLON }; - inline static constexpr uint32_t Semicolon { SDLK_SEMICOLON }; - inline static constexpr uint32_t Less { SDLK_LESS }; - inline static constexpr uint32_t Equals { SDLK_EQUALS }; - inline static constexpr uint32_t Greater { SDLK_GREATER }; - inline static constexpr uint32_t Question { SDLK_QUESTION }; - inline static constexpr uint32_t At { SDLK_AT }; - inline static constexpr uint32_t LeftBracket { SDLK_LEFTBRACKET }; - inline static constexpr uint32_t Backslash { SDLK_BACKSLASH }; - inline static constexpr uint32_t RightBracket { SDLK_RIGHTBRACKET }; - inline static constexpr uint32_t Caret { SDLK_CARET }; - inline static constexpr uint32_t Underscore { SDLK_UNDERSCORE }; - inline static constexpr uint32_t Grave { SDLK_GRAVE }; - inline static constexpr uint32_t A { SDLK_A }; - inline static constexpr uint32_t B { SDLK_B }; - inline static constexpr uint32_t C { SDLK_C }; - inline static constexpr uint32_t D { SDLK_D }; - inline static constexpr uint32_t E { SDLK_E }; - inline static constexpr uint32_t F { SDLK_F }; - inline static constexpr uint32_t G { SDLK_G }; - inline static constexpr uint32_t H { SDLK_H }; - inline static constexpr uint32_t I { SDLK_I }; - inline static constexpr uint32_t J { SDLK_J }; - inline static constexpr uint32_t K { SDLK_K }; - inline static constexpr uint32_t L { SDLK_L }; - inline static constexpr uint32_t M { SDLK_M }; - inline static constexpr uint32_t N { SDLK_N }; - inline static constexpr uint32_t O { SDLK_O }; - inline static constexpr uint32_t P { SDLK_P }; - inline static constexpr uint32_t Q { SDLK_Q }; - inline static constexpr uint32_t R { SDLK_R }; - inline static constexpr uint32_t S { SDLK_S }; - inline static constexpr uint32_t T { SDLK_T }; - inline static constexpr uint32_t U { SDLK_U }; - inline static constexpr uint32_t V { SDLK_V }; - inline static constexpr uint32_t W { SDLK_W }; - inline static constexpr uint32_t X { SDLK_X }; - inline static constexpr uint32_t Y { SDLK_Y }; - inline static constexpr uint32_t Z { SDLK_Z }; - inline static constexpr uint32_t Leftbrace { SDLK_LEFTBRACE }; - inline static constexpr uint32_t Pipe { SDLK_PIPE }; - inline static constexpr uint32_t Rightbrace { SDLK_RIGHTBRACE }; - inline static constexpr uint32_t Tilde { SDLK_TILDE }; - inline static constexpr uint32_t Delete { SDLK_DELETE }; - inline static constexpr uint32_t Plusminus { SDLK_PLUSMINUS }; - inline static constexpr uint32_t Capslock { SDLK_CAPSLOCK }; - inline static constexpr uint32_t F1 { SDLK_F1 }; - inline static constexpr uint32_t F2 { SDLK_F2 }; - inline static constexpr uint32_t F3 { SDLK_F3 }; - inline static constexpr uint32_t F4 { SDLK_F4 }; - inline static constexpr uint32_t F5 { SDLK_F5 }; - inline static constexpr uint32_t F6 { SDLK_F6 }; - inline static constexpr uint32_t F7 { SDLK_F7 }; - inline static constexpr uint32_t F8 { SDLK_F8 }; - inline static constexpr uint32_t F9 { SDLK_F9 }; - inline static constexpr uint32_t F10 { SDLK_F10 }; - inline static constexpr uint32_t F11 { SDLK_F11 }; - inline static constexpr uint32_t F12 { SDLK_F12 }; - inline static constexpr uint32_t Printscreen { SDLK_PRINTSCREEN }; - inline static constexpr uint32_t Scrolllock { SDLK_SCROLLLOCK }; - inline static constexpr uint32_t Pause { SDLK_PAUSE }; - inline static constexpr uint32_t Insert { SDLK_INSERT }; - inline static constexpr uint32_t Home { SDLK_HOME }; - inline static constexpr uint32_t Pageup { SDLK_PAGEUP }; - inline static constexpr uint32_t End { SDLK_END }; - inline static constexpr uint32_t Pagedown { SDLK_PAGEDOWN }; - inline static constexpr uint32_t Right { SDLK_RIGHT }; - inline static constexpr uint32_t Left { SDLK_LEFT }; - inline static constexpr uint32_t Down { SDLK_DOWN }; - inline static constexpr uint32_t Up { SDLK_UP }; - inline static constexpr uint32_t Numlockclear { SDLK_NUMLOCKCLEAR }; - inline static constexpr uint32_t KpDivide { SDLK_KP_DIVIDE }; - inline static constexpr uint32_t KpMultiply { SDLK_KP_MULTIPLY }; - inline static constexpr uint32_t KpMinus { SDLK_KP_MINUS }; - inline static constexpr uint32_t KpPlus { SDLK_KP_PLUS }; - inline static constexpr uint32_t KpEnter { SDLK_KP_ENTER }; - inline static constexpr uint32_t Kp1 { SDLK_KP_1 }; - inline static constexpr uint32_t Kp2 { SDLK_KP_2 }; - inline static constexpr uint32_t Kp3 { SDLK_KP_3 }; - inline static constexpr uint32_t Kp4 { SDLK_KP_4 }; - inline static constexpr uint32_t Kp5 { SDLK_KP_5 }; - inline static constexpr uint32_t Kp6 { SDLK_KP_6 }; - inline static constexpr uint32_t Kp7 { SDLK_KP_7 }; - inline static constexpr uint32_t Kp8 { SDLK_KP_8 }; - inline static constexpr uint32_t Kp9 { SDLK_KP_9 }; - inline static constexpr uint32_t Kp0 { SDLK_KP_0 }; - inline static constexpr uint32_t KpPeriod { SDLK_KP_PERIOD }; - inline static constexpr uint32_t Application { SDLK_APPLICATION }; - inline static constexpr uint32_t Power { SDLK_POWER }; - inline static constexpr uint32_t KpEquals { SDLK_KP_EQUALS }; - inline static constexpr uint32_t F13 { SDLK_F13 }; - inline static constexpr uint32_t F14 { SDLK_F14 }; - inline static constexpr uint32_t F15 { SDLK_F15 }; - inline static constexpr uint32_t F16 { SDLK_F16 }; - inline static constexpr uint32_t F17 { SDLK_F17 }; - inline static constexpr uint32_t F18 { SDLK_F18 }; - inline static constexpr uint32_t F19 { SDLK_F19 }; - inline static constexpr uint32_t F20 { SDLK_F20 }; - inline static constexpr uint32_t F21 { SDLK_F21 }; - inline static constexpr uint32_t F22 { SDLK_F22 }; - inline static constexpr uint32_t F23 { SDLK_F23 }; - inline static constexpr uint32_t F24 { SDLK_F24 }; - inline static constexpr uint32_t Execute { SDLK_EXECUTE }; - inline static constexpr uint32_t Help { SDLK_HELP }; - inline static constexpr uint32_t Menu { SDLK_MENU }; - inline static constexpr uint32_t Select { SDLK_SELECT }; - inline static constexpr uint32_t Stop { SDLK_STOP }; - inline static constexpr uint32_t Again { SDLK_AGAIN }; - inline static constexpr uint32_t Undo { SDLK_UNDO }; - inline static constexpr uint32_t Cut { SDLK_CUT }; - inline static constexpr uint32_t Copy { SDLK_COPY }; - inline static constexpr uint32_t Paste { SDLK_PASTE }; - inline static constexpr uint32_t Find { SDLK_FIND }; - inline static constexpr uint32_t Mute { SDLK_MUTE }; - inline static constexpr uint32_t Volumeup { SDLK_VOLUMEUP }; - inline static constexpr uint32_t Volumedown { SDLK_VOLUMEDOWN }; - inline static constexpr uint32_t KpComma { SDLK_KP_COMMA }; - inline static constexpr uint32_t KpEqualsas400 { SDLK_KP_EQUALSAS400 }; - inline static constexpr uint32_t Alterase { SDLK_ALTERASE }; - inline static constexpr uint32_t Sysreq { SDLK_SYSREQ }; - inline static constexpr uint32_t Cancel { SDLK_CANCEL }; - inline static constexpr uint32_t Clear { SDLK_CLEAR }; - inline static constexpr uint32_t Prior { SDLK_PRIOR }; - inline static constexpr uint32_t Return2 { SDLK_RETURN2 }; - inline static constexpr uint32_t Separator { SDLK_SEPARATOR }; - inline static constexpr uint32_t Out { SDLK_OUT }; - inline static constexpr uint32_t Oper { SDLK_OPER }; - inline static constexpr uint32_t Clearagain { SDLK_CLEARAGAIN }; - inline static constexpr uint32_t Crsel { SDLK_CRSEL }; - inline static constexpr uint32_t Exsel { SDLK_EXSEL }; - inline static constexpr uint32_t Kp00 { SDLK_KP_00 }; - inline static constexpr uint32_t Kp000 { SDLK_KP_000 }; - inline static constexpr uint32_t Thousandsseparator { SDLK_THOUSANDSSEPARATOR }; - inline static constexpr uint32_t Decimalseparator { SDLK_DECIMALSEPARATOR }; - inline static constexpr uint32_t Currencyunit { SDLK_CURRENCYUNIT }; - inline static constexpr uint32_t Currencysubunit { SDLK_CURRENCYSUBUNIT }; - inline static constexpr uint32_t KpLeftparen { SDLK_KP_LEFTPAREN }; - inline static constexpr uint32_t KpRightparen { SDLK_KP_RIGHTPAREN }; - inline static constexpr uint32_t KpLeftbrace { SDLK_KP_LEFTBRACE }; - inline static constexpr uint32_t KpRightbrace { SDLK_KP_RIGHTBRACE }; - inline static constexpr uint32_t KpTab { SDLK_KP_TAB }; - inline static constexpr uint32_t KpBackspace { SDLK_KP_BACKSPACE }; - inline static constexpr uint32_t KpA { SDLK_KP_A }; - inline static constexpr uint32_t KpB { SDLK_KP_B }; - inline static constexpr uint32_t KpC { SDLK_KP_C }; - inline static constexpr uint32_t KpD { SDLK_KP_D }; - inline static constexpr uint32_t KpE { SDLK_KP_E }; - inline static constexpr uint32_t KpF { SDLK_KP_F }; - inline static constexpr uint32_t KpXor { SDLK_KP_XOR }; - inline static constexpr uint32_t KpPower { SDLK_KP_POWER }; - inline static constexpr uint32_t KpPercent { SDLK_KP_PERCENT }; - inline static constexpr uint32_t KpLess { SDLK_KP_LESS }; - inline static constexpr uint32_t KpGreater { SDLK_KP_GREATER }; - inline static constexpr uint32_t KpAmpersand { SDLK_KP_AMPERSAND }; - inline static constexpr uint32_t KpDblampersand { SDLK_KP_DBLAMPERSAND }; - inline static constexpr uint32_t KpVerticalbar { SDLK_KP_VERTICALBAR }; - inline static constexpr uint32_t KpDblverticalbar { SDLK_KP_DBLVERTICALBAR }; - inline static constexpr uint32_t KpColon { SDLK_KP_COLON }; - inline static constexpr uint32_t KpHash { SDLK_KP_HASH }; - inline static constexpr uint32_t KpSpace { SDLK_KP_SPACE }; - inline static constexpr uint32_t KpAt { SDLK_KP_AT }; - inline static constexpr uint32_t KpExclam { SDLK_KP_EXCLAM }; - inline static constexpr uint32_t KpMemstore { SDLK_KP_MEMSTORE }; - inline static constexpr uint32_t KpMemrecall { SDLK_KP_MEMRECALL }; - inline static constexpr uint32_t KpMemclear { SDLK_KP_MEMCLEAR }; - inline static constexpr uint32_t KpMemadd { SDLK_KP_MEMADD }; - inline static constexpr uint32_t KpMemsubtract { SDLK_KP_MEMSUBTRACT }; - inline static constexpr uint32_t KpMemmultiply { SDLK_KP_MEMMULTIPLY }; - inline static constexpr uint32_t KpMemdivide { SDLK_KP_MEMDIVIDE }; - inline static constexpr uint32_t KpPlusminus { SDLK_KP_PLUSMINUS }; - inline static constexpr uint32_t KpClear { SDLK_KP_CLEAR }; - inline static constexpr uint32_t KpClearentry { SDLK_KP_CLEARENTRY }; - inline static constexpr uint32_t KpBinary { SDLK_KP_BINARY }; - inline static constexpr uint32_t KpOctal { SDLK_KP_OCTAL }; - inline static constexpr uint32_t KpDecimal { SDLK_KP_DECIMAL }; - inline static constexpr uint32_t KpHexadecimal { SDLK_KP_HEXADECIMAL }; - inline static constexpr uint32_t Lctrl { SDLK_LCTRL }; - inline static constexpr uint32_t Lshift { SDLK_LSHIFT }; - inline static constexpr uint32_t Lalt { SDLK_LALT }; - inline static constexpr uint32_t Lgui { SDLK_LGUI }; - inline static constexpr uint32_t Rctrl { SDLK_RCTRL }; - inline static constexpr uint32_t Rshift { SDLK_RSHIFT }; - inline static constexpr uint32_t Ralt { SDLK_RALT }; - inline static constexpr uint32_t Rgui { SDLK_RGUI }; - inline static constexpr uint32_t Mode { SDLK_MODE }; - inline static constexpr uint32_t Sleep { SDLK_SLEEP }; - inline static constexpr uint32_t Wake { SDLK_WAKE }; - inline static constexpr uint32_t ChannelIncrement { SDLK_CHANNEL_INCREMENT }; - inline static constexpr uint32_t ChannelDecrement { SDLK_CHANNEL_DECREMENT }; - inline static constexpr uint32_t MediaPlay { SDLK_MEDIA_PLAY }; - inline static constexpr uint32_t MediaPause { SDLK_MEDIA_PAUSE }; - inline static constexpr uint32_t MediaRecord { SDLK_MEDIA_RECORD }; - inline static constexpr uint32_t MediaFastForward { SDLK_MEDIA_FAST_FORWARD }; - inline static constexpr uint32_t MediaRewind { SDLK_MEDIA_REWIND }; - inline static constexpr uint32_t MediaNextTrack { SDLK_MEDIA_NEXT_TRACK }; - inline static constexpr uint32_t MediaPreviousTrack { SDLK_MEDIA_PREVIOUS_TRACK }; - inline static constexpr uint32_t MediaStop { SDLK_MEDIA_STOP }; - inline static constexpr uint32_t MediaEject { SDLK_MEDIA_EJECT }; - inline static constexpr uint32_t MediaPlayPause { SDLK_MEDIA_PLAY_PAUSE }; - inline static constexpr uint32_t MediaSelect { SDLK_MEDIA_SELECT }; - inline static constexpr uint32_t AcNew { SDLK_AC_NEW }; - inline static constexpr uint32_t AcOpen { SDLK_AC_OPEN }; - inline static constexpr uint32_t AcClose { SDLK_AC_CLOSE }; - inline static constexpr uint32_t AcExit { SDLK_AC_EXIT }; - inline static constexpr uint32_t AcSave { SDLK_AC_SAVE }; - inline static constexpr uint32_t AcPrint { SDLK_AC_PRINT }; - inline static constexpr uint32_t AcProperties { SDLK_AC_PROPERTIES }; - inline static constexpr uint32_t AcSearch { SDLK_AC_SEARCH }; - inline static constexpr uint32_t AcHome { SDLK_AC_HOME }; - inline static constexpr uint32_t AcBack { SDLK_AC_BACK }; - inline static constexpr uint32_t AcForward { SDLK_AC_FORWARD }; - inline static constexpr uint32_t AcStop { SDLK_AC_STOP }; - inline static constexpr uint32_t AcRefresh { SDLK_AC_REFRESH }; - inline static constexpr uint32_t AcBookmarks { SDLK_AC_BOOKMARKS }; - inline static constexpr uint32_t Softleft { SDLK_SOFTLEFT }; - inline static constexpr uint32_t Softright { SDLK_SOFTRIGHT }; - inline static constexpr uint32_t Call { SDLK_CALL }; - inline static constexpr uint32_t Endcall { SDLK_ENDCALL }; - inline static constexpr uint32_t LeftTab { SDLK_LEFT_TAB }; - inline static constexpr uint32_t Level5Shift { SDLK_LEVEL5_SHIFT }; - inline static constexpr uint32_t MultiKeyCompose { SDLK_MULTI_KEY_COMPOSE }; - inline static constexpr uint32_t Lmeta { SDLK_LMETA }; - inline static constexpr uint32_t Rmeta { SDLK_RMETA }; - inline static constexpr uint32_t Lhyper { SDLK_LHYPER }; - inline static constexpr uint32_t Rhyper { SDLK_RHYPER }; + inline static constexpr u32 Unknown { SDLK_UNKNOWN }; + inline static constexpr u32 Return { SDLK_RETURN }; + inline static constexpr u32 Escape { SDLK_ESCAPE }; + inline static constexpr u32 Backspace { SDLK_BACKSPACE }; + inline static constexpr u32 Tab { SDLK_TAB }; + inline static constexpr u32 Space { SDLK_SPACE }; + inline static constexpr u32 Exclaim { SDLK_EXCLAIM }; + inline static constexpr u32 Dblapostrophe { SDLK_DBLAPOSTROPHE }; + inline static constexpr u32 Hash { SDLK_HASH }; + inline static constexpr u32 Dollar { SDLK_DOLLAR }; + inline static constexpr u32 Percent { SDLK_PERCENT }; + inline static constexpr u32 Ampersand { SDLK_AMPERSAND }; + inline static constexpr u32 Apostrophe { SDLK_APOSTROPHE }; + inline static constexpr u32 Leftparen { SDLK_LEFTPAREN }; + inline static constexpr u32 Rightparen { SDLK_RIGHTPAREN }; + inline static constexpr u32 Asterisk { SDLK_ASTERISK }; + inline static constexpr u32 Plus { SDLK_PLUS }; + inline static constexpr u32 Comma { SDLK_COMMA }; + inline static constexpr u32 Minus { SDLK_MINUS }; + inline static constexpr u32 Period { SDLK_PERIOD }; + inline static constexpr u32 Slash { SDLK_SLASH }; + inline static constexpr u32 Num0 { SDLK_0 }; + inline static constexpr u32 Num1 { SDLK_1 }; + inline static constexpr u32 Num2 { SDLK_2 }; + inline static constexpr u32 Num3 { SDLK_3 }; + inline static constexpr u32 Num4 { SDLK_4 }; + inline static constexpr u32 Num5 { SDLK_5 }; + inline static constexpr u32 Num6 { SDLK_6 }; + inline static constexpr u32 Num7 { SDLK_7 }; + inline static constexpr u32 Num8 { SDLK_8 }; + inline static constexpr u32 Num9 { SDLK_9 }; + inline static constexpr u32 Colon { SDLK_COLON }; + inline static constexpr u32 Semicolon { SDLK_SEMICOLON }; + inline static constexpr u32 Less { SDLK_LESS }; + inline static constexpr u32 Equals { SDLK_EQUALS }; + inline static constexpr u32 Greater { SDLK_GREATER }; + inline static constexpr u32 Question { SDLK_QUESTION }; + inline static constexpr u32 At { SDLK_AT }; + inline static constexpr u32 LeftBracket { SDLK_LEFTBRACKET }; + inline static constexpr u32 Backslash { SDLK_BACKSLASH }; + inline static constexpr u32 RightBracket { SDLK_RIGHTBRACKET }; + inline static constexpr u32 Caret { SDLK_CARET }; + inline static constexpr u32 Underscore { SDLK_UNDERSCORE }; + inline static constexpr u32 Grave { SDLK_GRAVE }; + inline static constexpr u32 A { SDLK_A }; + inline static constexpr u32 B { SDLK_B }; + inline static constexpr u32 C { SDLK_C }; + inline static constexpr u32 D { SDLK_D }; + inline static constexpr u32 E { SDLK_E }; + inline static constexpr u32 F { SDLK_F }; + inline static constexpr u32 G { SDLK_G }; + inline static constexpr u32 H { SDLK_H }; + inline static constexpr u32 I { SDLK_I }; + inline static constexpr u32 J { SDLK_J }; + inline static constexpr u32 K { SDLK_K }; + inline static constexpr u32 L { SDLK_L }; + inline static constexpr u32 M { SDLK_M }; + inline static constexpr u32 N { SDLK_N }; + inline static constexpr u32 O { SDLK_O }; + inline static constexpr u32 P { SDLK_P }; + inline static constexpr u32 Q { SDLK_Q }; + inline static constexpr u32 R { SDLK_R }; + inline static constexpr u32 S { SDLK_S }; + inline static constexpr u32 T { SDLK_T }; + inline static constexpr u32 U { SDLK_U }; + inline static constexpr u32 V { SDLK_V }; + inline static constexpr u32 W { SDLK_W }; + inline static constexpr u32 X { SDLK_X }; + inline static constexpr u32 Y { SDLK_Y }; + inline static constexpr u32 Z { SDLK_Z }; + inline static constexpr u32 Leftbrace { SDLK_LEFTBRACE }; + inline static constexpr u32 Pipe { SDLK_PIPE }; + inline static constexpr u32 Rightbrace { SDLK_RIGHTBRACE }; + inline static constexpr u32 Tilde { SDLK_TILDE }; + inline static constexpr u32 Delete { SDLK_DELETE }; + inline static constexpr u32 Plusminus { SDLK_PLUSMINUS }; + inline static constexpr u32 Capslock { SDLK_CAPSLOCK }; + inline static constexpr u32 F1 { SDLK_F1 }; + inline static constexpr u32 F2 { SDLK_F2 }; + inline static constexpr u32 F3 { SDLK_F3 }; + inline static constexpr u32 F4 { SDLK_F4 }; + inline static constexpr u32 F5 { SDLK_F5 }; + inline static constexpr u32 F6 { SDLK_F6 }; + inline static constexpr u32 F7 { SDLK_F7 }; + inline static constexpr u32 F8 { SDLK_F8 }; + inline static constexpr u32 F9 { SDLK_F9 }; + inline static constexpr u32 F10 { SDLK_F10 }; + inline static constexpr u32 F11 { SDLK_F11 }; + inline static constexpr u32 F12 { SDLK_F12 }; + inline static constexpr u32 Printscreen { SDLK_PRINTSCREEN }; + inline static constexpr u32 Scrolllock { SDLK_SCROLLLOCK }; + inline static constexpr u32 Pause { SDLK_PAUSE }; + inline static constexpr u32 Insert { SDLK_INSERT }; + inline static constexpr u32 Home { SDLK_HOME }; + inline static constexpr u32 Pageup { SDLK_PAGEUP }; + inline static constexpr u32 End { SDLK_END }; + inline static constexpr u32 Pagedown { SDLK_PAGEDOWN }; + inline static constexpr u32 Right { SDLK_RIGHT }; + inline static constexpr u32 Left { SDLK_LEFT }; + inline static constexpr u32 Down { SDLK_DOWN }; + inline static constexpr u32 Up { SDLK_UP }; + inline static constexpr u32 Numlockclear { SDLK_NUMLOCKCLEAR }; + inline static constexpr u32 KpDivide { SDLK_KP_DIVIDE }; + inline static constexpr u32 KpMultiply { SDLK_KP_MULTIPLY }; + inline static constexpr u32 KpMinus { SDLK_KP_MINUS }; + inline static constexpr u32 KpPlus { SDLK_KP_PLUS }; + inline static constexpr u32 KpEnter { SDLK_KP_ENTER }; + inline static constexpr u32 Kp1 { SDLK_KP_1 }; + inline static constexpr u32 Kp2 { SDLK_KP_2 }; + inline static constexpr u32 Kp3 { SDLK_KP_3 }; + inline static constexpr u32 Kp4 { SDLK_KP_4 }; + inline static constexpr u32 Kp5 { SDLK_KP_5 }; + inline static constexpr u32 Kp6 { SDLK_KP_6 }; + inline static constexpr u32 Kp7 { SDLK_KP_7 }; + inline static constexpr u32 Kp8 { SDLK_KP_8 }; + inline static constexpr u32 Kp9 { SDLK_KP_9 }; + inline static constexpr u32 Kp0 { SDLK_KP_0 }; + inline static constexpr u32 KpPeriod { SDLK_KP_PERIOD }; + inline static constexpr u32 Application { SDLK_APPLICATION }; + inline static constexpr u32 Power { SDLK_POWER }; + inline static constexpr u32 KpEquals { SDLK_KP_EQUALS }; + inline static constexpr u32 F13 { SDLK_F13 }; + inline static constexpr u32 F14 { SDLK_F14 }; + inline static constexpr u32 F15 { SDLK_F15 }; + inline static constexpr u32 F16 { SDLK_F16 }; + inline static constexpr u32 F17 { SDLK_F17 }; + inline static constexpr u32 F18 { SDLK_F18 }; + inline static constexpr u32 F19 { SDLK_F19 }; + inline static constexpr u32 F20 { SDLK_F20 }; + inline static constexpr u32 F21 { SDLK_F21 }; + inline static constexpr u32 F22 { SDLK_F22 }; + inline static constexpr u32 F23 { SDLK_F23 }; + inline static constexpr u32 F24 { SDLK_F24 }; + inline static constexpr u32 Execute { SDLK_EXECUTE }; + inline static constexpr u32 Help { SDLK_HELP }; + inline static constexpr u32 Menu { SDLK_MENU }; + inline static constexpr u32 Select { SDLK_SELECT }; + inline static constexpr u32 Stop { SDLK_STOP }; + inline static constexpr u32 Again { SDLK_AGAIN }; + inline static constexpr u32 Undo { SDLK_UNDO }; + inline static constexpr u32 Cut { SDLK_CUT }; + inline static constexpr u32 Copy { SDLK_COPY }; + inline static constexpr u32 Paste { SDLK_PASTE }; + inline static constexpr u32 Find { SDLK_FIND }; + inline static constexpr u32 Mute { SDLK_MUTE }; + inline static constexpr u32 Volumeup { SDLK_VOLUMEUP }; + inline static constexpr u32 Volumedown { SDLK_VOLUMEDOWN }; + inline static constexpr u32 KpComma { SDLK_KP_COMMA }; + inline static constexpr u32 KpEqualsas400 { SDLK_KP_EQUALSAS400 }; + inline static constexpr u32 Alterase { SDLK_ALTERASE }; + inline static constexpr u32 Sysreq { SDLK_SYSREQ }; + inline static constexpr u32 Cancel { SDLK_CANCEL }; + inline static constexpr u32 Clear { SDLK_CLEAR }; + inline static constexpr u32 Prior { SDLK_PRIOR }; + inline static constexpr u32 Return2 { SDLK_RETURN2 }; + inline static constexpr u32 Separator { SDLK_SEPARATOR }; + inline static constexpr u32 Out { SDLK_OUT }; + inline static constexpr u32 Oper { SDLK_OPER }; + inline static constexpr u32 Clearagain { SDLK_CLEARAGAIN }; + inline static constexpr u32 Crsel { SDLK_CRSEL }; + inline static constexpr u32 Exsel { SDLK_EXSEL }; + inline static constexpr u32 Kp00 { SDLK_KP_00 }; + inline static constexpr u32 Kp000 { SDLK_KP_000 }; + inline static constexpr u32 Thousandsseparator { SDLK_THOUSANDSSEPARATOR }; + inline static constexpr u32 Decimalseparator { SDLK_DECIMALSEPARATOR }; + inline static constexpr u32 Currencyunit { SDLK_CURRENCYUNIT }; + inline static constexpr u32 Currencysubunit { SDLK_CURRENCYSUBUNIT }; + inline static constexpr u32 KpLeftparen { SDLK_KP_LEFTPAREN }; + inline static constexpr u32 KpRightparen { SDLK_KP_RIGHTPAREN }; + inline static constexpr u32 KpLeftbrace { SDLK_KP_LEFTBRACE }; + inline static constexpr u32 KpRightbrace { SDLK_KP_RIGHTBRACE }; + inline static constexpr u32 KpTab { SDLK_KP_TAB }; + inline static constexpr u32 KpBackspace { SDLK_KP_BACKSPACE }; + inline static constexpr u32 KpA { SDLK_KP_A }; + inline static constexpr u32 KpB { SDLK_KP_B }; + inline static constexpr u32 KpC { SDLK_KP_C }; + inline static constexpr u32 KpD { SDLK_KP_D }; + inline static constexpr u32 KpE { SDLK_KP_E }; + inline static constexpr u32 KpF { SDLK_KP_F }; + inline static constexpr u32 KpXor { SDLK_KP_XOR }; + inline static constexpr u32 KpPower { SDLK_KP_POWER }; + inline static constexpr u32 KpPercent { SDLK_KP_PERCENT }; + inline static constexpr u32 KpLess { SDLK_KP_LESS }; + inline static constexpr u32 KpGreater { SDLK_KP_GREATER }; + inline static constexpr u32 KpAmpersand { SDLK_KP_AMPERSAND }; + inline static constexpr u32 KpDblampersand { SDLK_KP_DBLAMPERSAND }; + inline static constexpr u32 KpVerticalbar { SDLK_KP_VERTICALBAR }; + inline static constexpr u32 KpDblverticalbar { SDLK_KP_DBLVERTICALBAR }; + inline static constexpr u32 KpColon { SDLK_KP_COLON }; + inline static constexpr u32 KpHash { SDLK_KP_HASH }; + inline static constexpr u32 KpSpace { SDLK_KP_SPACE }; + inline static constexpr u32 KpAt { SDLK_KP_AT }; + inline static constexpr u32 KpExclam { SDLK_KP_EXCLAM }; + inline static constexpr u32 KpMemstore { SDLK_KP_MEMSTORE }; + inline static constexpr u32 KpMemrecall { SDLK_KP_MEMRECALL }; + inline static constexpr u32 KpMemclear { SDLK_KP_MEMCLEAR }; + inline static constexpr u32 KpMemadd { SDLK_KP_MEMADD }; + inline static constexpr u32 KpMemsubtract { SDLK_KP_MEMSUBTRACT }; + inline static constexpr u32 KpMemmultiply { SDLK_KP_MEMMULTIPLY }; + inline static constexpr u32 KpMemdivide { SDLK_KP_MEMDIVIDE }; + inline static constexpr u32 KpPlusminus { SDLK_KP_PLUSMINUS }; + inline static constexpr u32 KpClear { SDLK_KP_CLEAR }; + inline static constexpr u32 KpClearentry { SDLK_KP_CLEARENTRY }; + inline static constexpr u32 KpBinary { SDLK_KP_BINARY }; + inline static constexpr u32 KpOctal { SDLK_KP_OCTAL }; + inline static constexpr u32 KpDecimal { SDLK_KP_DECIMAL }; + inline static constexpr u32 KpHexadecimal { SDLK_KP_HEXADECIMAL }; + inline static constexpr u32 Lctrl { SDLK_LCTRL }; + inline static constexpr u32 Lshift { SDLK_LSHIFT }; + inline static constexpr u32 Lalt { SDLK_LALT }; + inline static constexpr u32 Lgui { SDLK_LGUI }; + inline static constexpr u32 Rctrl { SDLK_RCTRL }; + inline static constexpr u32 Rshift { SDLK_RSHIFT }; + inline static constexpr u32 Ralt { SDLK_RALT }; + inline static constexpr u32 Rgui { SDLK_RGUI }; + inline static constexpr u32 Mode { SDLK_MODE }; + inline static constexpr u32 Sleep { SDLK_SLEEP }; + inline static constexpr u32 Wake { SDLK_WAKE }; + inline static constexpr u32 ChannelIncrement { SDLK_CHANNEL_INCREMENT }; + inline static constexpr u32 ChannelDecrement { SDLK_CHANNEL_DECREMENT }; + inline static constexpr u32 MediaPlay { SDLK_MEDIA_PLAY }; + inline static constexpr u32 MediaPause { SDLK_MEDIA_PAUSE }; + inline static constexpr u32 MediaRecord { SDLK_MEDIA_RECORD }; + inline static constexpr u32 MediaFastForward { SDLK_MEDIA_FAST_FORWARD }; + inline static constexpr u32 MediaRewind { SDLK_MEDIA_REWIND }; + inline static constexpr u32 MediaNextTrack { SDLK_MEDIA_NEXT_TRACK }; + inline static constexpr u32 MediaPreviousTrack { SDLK_MEDIA_PREVIOUS_TRACK }; + inline static constexpr u32 MediaStop { SDLK_MEDIA_STOP }; + inline static constexpr u32 MediaEject { SDLK_MEDIA_EJECT }; + inline static constexpr u32 MediaPlayPause { SDLK_MEDIA_PLAY_PAUSE }; + inline static constexpr u32 MediaSelect { SDLK_MEDIA_SELECT }; + inline static constexpr u32 AcNew { SDLK_AC_NEW }; + inline static constexpr u32 AcOpen { SDLK_AC_OPEN }; + inline static constexpr u32 AcClose { SDLK_AC_CLOSE }; + inline static constexpr u32 AcExit { SDLK_AC_EXIT }; + inline static constexpr u32 AcSave { SDLK_AC_SAVE }; + inline static constexpr u32 AcPrint { SDLK_AC_PRINT }; + inline static constexpr u32 AcProperties { SDLK_AC_PROPERTIES }; + inline static constexpr u32 AcSearch { SDLK_AC_SEARCH }; + inline static constexpr u32 AcHome { SDLK_AC_HOME }; + inline static constexpr u32 AcBack { SDLK_AC_BACK }; + inline static constexpr u32 AcForward { SDLK_AC_FORWARD }; + inline static constexpr u32 AcStop { SDLK_AC_STOP }; + inline static constexpr u32 AcRefresh { SDLK_AC_REFRESH }; + inline static constexpr u32 AcBookmarks { SDLK_AC_BOOKMARKS }; + inline static constexpr u32 Softleft { SDLK_SOFTLEFT }; + inline static constexpr u32 Softright { SDLK_SOFTRIGHT }; + inline static constexpr u32 Call { SDLK_CALL }; + inline static constexpr u32 Endcall { SDLK_ENDCALL }; + inline static constexpr u32 LeftTab { SDLK_LEFT_TAB }; + inline static constexpr u32 Level5Shift { SDLK_LEVEL5_SHIFT }; + inline static constexpr u32 MultiKeyCompose { SDLK_MULTI_KEY_COMPOSE }; + inline static constexpr u32 Lmeta { SDLK_LMETA }; + inline static constexpr u32 Rmeta { SDLK_RMETA }; + inline static constexpr u32 Lhyper { SDLK_LHYPER }; + inline static constexpr u32 Rhyper { SDLK_RHYPER }; }; } diff --git a/src/ogfx/utils/SDLInclude.hpp b/src/ogfx/utils/SDLInclude.hpp index 4a959b8..533c045 100644 --- a/src/ogfx/utils/SDLInclude.hpp +++ b/src/ogfx/utils/SDLInclude.hpp @@ -74,11 +74,11 @@ namespace ogfx } private: - inline static int s_refCount { 0 }; + inline static i32 s_refCount { 0 }; public: - inline static constexpr int32_t ErrorSDLInitFailed { 1 }; - inline static constexpr int32_t ErrorSDLTTFInitFailed { 2 }; + inline static constexpr i32 ErrorSDLInitFailed { 1 }; + inline static constexpr i32 ErrorSDLTTFInitFailed { 2 }; }; } diff --git a/src/ostd/data/BaseObject.cpp b/src/ostd/data/BaseObject.cpp index 66be66e..3db6805 100755 --- a/src/ostd/data/BaseObject.cpp +++ b/src/ostd/data/BaseObject.cpp @@ -41,7 +41,7 @@ namespace ostd return getTypeName().add("->uid=").add(getID()).add("/oid=").add(getCompareOID()).add("/valid=").add(STR_BOOL(isValid())); } - void BaseObject::connectSignal(uint32_t signal_id) + void BaseObject::connectSignal(u32 signal_id) { SignalHandler::connect(*this, signal_id); } diff --git a/src/ostd/data/BaseObject.hpp b/src/ostd/data/BaseObject.hpp index b32cc16..231fa4a 100755 --- a/src/ostd/data/BaseObject.hpp +++ b/src/ostd/data/BaseObject.hpp @@ -37,8 +37,8 @@ namespace ostd virtual BaseObject& operator=(const BaseObject& copy); inline void setSignalCallback(SignalCallback callback) { callback_signal = callback; } - virtual inline uint64_t getID(void) const { return m_uid; } - virtual inline void setID(uint64_t id) { m_uid = id; } + virtual inline u64 getID(void) const { return m_uid; } + virtual inline void setID(u64 id) { m_uid = id; } virtual inline bool isValid(void) const { return !isInvalid(); } virtual inline bool isInvalid(void) const { return !m_valid || m_oid == 0; } @@ -46,7 +46,7 @@ namespace ostd virtual inline void validate(void) { m_valid = true; } virtual inline void setValid(bool valid) { m_valid = valid; } - inline uint64_t getCompareOID(void) const { return m_oid; } + inline u64 getCompareOID(void) const { return m_oid; } inline bool compareByOID(const BaseObject& other) const { return m_oid == other.m_oid; } inline static BaseObject& InvalidRef(void) { return BaseObject::s_invalid_obj; } @@ -62,7 +62,7 @@ namespace ostd virtual void print(bool newLine = true, OutputHandlerBase* __destination = nullptr) const; virtual inline void handleSignal(Signal& signal) { } - void connectSignal(uint32_t signal_id); + void connectSignal(u32 signal_id); void __handle_signal(Signal& signal); @@ -72,14 +72,14 @@ namespace ostd inline BaseObject(bool __valid) { m_uid = -1; m_valid = __valid; m_oid = 0; } private: - uint64_t m_uid; - uint64_t m_oid; + u64 m_uid; + u64 m_oid; bool m_valid; String m_typeName; bool m_signalsEnabled { true }; SignalCallback callback_signal { nullptr }; - inline static uint64_t s_next_oid { 1024 }; + inline static u64 s_next_oid { 1024 }; static BaseObject s_invalid_obj; }; } diff --git a/src/ostd/data/Bitfields.hpp b/src/ostd/data/Bitfields.hpp index d7eb3b9..4027174 100755 --- a/src/ostd/data/Bitfields.hpp +++ b/src/ostd/data/Bitfields.hpp @@ -1,39 +1,40 @@ /* - OmniaFramework - A collection of useful functionality - Copyright (C) 2025 OmniaX-Dev + OmniaFramework - A collection of useful functionality + Copyright (C) 2025 OmniaX-Dev - This file is part of OmniaFramework. + This file is part of OmniaFramework. - OmniaFramework is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + OmniaFramework is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - OmniaFramework is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + OmniaFramework is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with OmniaFramework. If not, see . + You should have received a copy of the GNU General Public License + along with OmniaFramework. If not, see . */ #pragma once #include #include +#include -#define get_bit(__bit_field, __bit_n ) __bit_field.bits.b##__bit_n -#define set_bit(__bit_field, __bit_n ) __bit_field.bits.b##__bit_n = true -#define clr_bit(__bit_field, __bit_n ) __bit_field.bits.b##__bit_n = false -#define tgl_bit(__bit_field, __bit_n ) __bit_field.bits.b##__bit_n = !__bit_field.bits.b##__bit_n -#define val_bit(__bit_field, __bit_n, __val ) __bit_field.bits.b##__bit_n = __val +#define get_bit(__bit_field, __bit_n ) __bit_field.bits.b##__bit_n +#define set_bit(__bit_field, __bit_n ) __bit_field.bits.b##__bit_n = true +#define clr_bit(__bit_field, __bit_n ) __bit_field.bits.b##__bit_n = false +#define tgl_bit(__bit_field, __bit_n ) __bit_field.bits.b##__bit_n = !__bit_field.bits.b##__bit_n +#define val_bit(__bit_field, __bit_n, __val ) __bit_field.bits.b##__bit_n = __val namespace ostd { union BitField_8 { - uint8_t value = 0; + u8 value = 0; struct { bool b0 : 1; bool b1 : 1; @@ -47,7 +48,7 @@ namespace ostd }; union BitField_16 { - uint16_t value = 0; + u16 value = 0; struct { bool b0 : 1; bool b1 : 1; @@ -69,7 +70,7 @@ namespace ostd }; union BitField_32 { - uint32_t value = 0; + u32 value = 0; struct { bool b0 : 1; bool b1 : 1; @@ -107,7 +108,7 @@ namespace ostd }; union BitField_64 { - uint64_t value = 0; + u64 value = 0; struct { bool b0 : 1; bool b1 : 1; @@ -180,7 +181,7 @@ namespace ostd { public: //8-Bit field - static inline bool get(const BitField_8& bf, const uint8_t& bit) + static inline bool get(const BitField_8& bf, const u8& bit) { switch (bit) { @@ -195,7 +196,7 @@ namespace ostd default: return false; } } - static inline void set(BitField_8& bf, const uint8_t& bit) + static inline void set(BitField_8& bf, const u8& bit) { switch (bit) { @@ -210,7 +211,7 @@ namespace ostd default: break; } } - static inline void clr(BitField_8& bf, const uint8_t& bit) + static inline void clr(BitField_8& bf, const u8& bit) { switch (bit) { @@ -225,7 +226,7 @@ namespace ostd default: break; } } - static inline void tgl(BitField_8& bf, const uint8_t& bit) + static inline void tgl(BitField_8& bf, const u8& bit) { switch (bit) { @@ -240,7 +241,7 @@ namespace ostd default: break; } } - static inline void val(BitField_8& bf, const uint8_t& bit, bool value) + static inline void val(BitField_8& bf, const u8& bit, bool value) { switch (bit) { @@ -257,7 +258,7 @@ namespace ostd } //16-Bit field - static inline bool get(const BitField_16& bf, const uint8_t& bit) + static inline bool get(const BitField_16& bf, const u8& bit) { switch (bit) { @@ -280,7 +281,7 @@ namespace ostd default: return false; } } - static inline void set(BitField_16& bf, const uint8_t& bit) + static inline void set(BitField_16& bf, const u8& bit) { switch (bit) { @@ -303,7 +304,7 @@ namespace ostd default: break; } } - static inline void clr(BitField_16& bf, const uint8_t& bit) + static inline void clr(BitField_16& bf, const u8& bit) { switch (bit) { @@ -326,7 +327,7 @@ namespace ostd default: break; } } - static inline void tgl(BitField_16& bf, const uint8_t& bit) + static inline void tgl(BitField_16& bf, const u8& bit) { switch (bit) { @@ -349,7 +350,7 @@ namespace ostd default: break; } } - static inline void val(BitField_16& bf, const uint8_t& bit, bool value) + static inline void val(BitField_16& bf, const u8& bit, bool value) { switch (bit) { @@ -374,7 +375,7 @@ namespace ostd } //32-Bit field - static inline bool get(const BitField_32& bf, const uint8_t& bit) + static inline bool get(const BitField_32& bf, const u8& bit) { switch (bit) { @@ -413,7 +414,7 @@ namespace ostd default: return false; } } - static inline void set(BitField_32& bf, const uint8_t& bit) + static inline void set(BitField_32& bf, const u8& bit) { switch (bit) { @@ -452,7 +453,7 @@ namespace ostd default: break; } } - static inline void clr(BitField_32& bf, const uint8_t& bit) + static inline void clr(BitField_32& bf, const u8& bit) { switch (bit) { @@ -491,7 +492,7 @@ namespace ostd default: break; } } - static inline void tgl(BitField_32& bf, const uint8_t& bit) + static inline void tgl(BitField_32& bf, const u8& bit) { switch (bit) { @@ -530,7 +531,7 @@ namespace ostd default: break; } } - static inline void val(BitField_32& bf, const uint8_t& bit, bool value) + static inline void val(BitField_32& bf, const u8& bit, bool value) { switch (bit) { @@ -571,7 +572,7 @@ namespace ostd } //64-Bit field - static inline bool get(const BitField_64& bf, const uint8_t& bit) + static inline bool get(const BitField_64& bf, const u8& bit) { switch (bit) { @@ -642,7 +643,7 @@ namespace ostd default: return false; } } - static inline void set(BitField_64& bf, const uint8_t& bit) + static inline void set(BitField_64& bf, const u8& bit) { switch (bit) { @@ -713,7 +714,7 @@ namespace ostd default: break; } } - static inline void clr(BitField_64& bf, const uint8_t& bit) + static inline void clr(BitField_64& bf, const u8& bit) { switch (bit) { @@ -784,7 +785,7 @@ namespace ostd default: break; } } - static inline void tgl(BitField_64& bf, const uint8_t& bit) + static inline void tgl(BitField_64& bf, const u8& bit) { switch (bit) { @@ -855,7 +856,7 @@ namespace ostd default: break; } } - static inline void val(BitField_64& bf, const uint8_t& bit, bool value) + static inline void val(BitField_64& bf, const u8& bit, bool value) { switch (bit) { diff --git a/src/ostd/data/Color.cpp b/src/ostd/data/Color.cpp index a34a7fa..7c9ba51 100755 --- a/src/ostd/data/Color.cpp +++ b/src/ostd/data/Color.cpp @@ -12,14 +12,14 @@ namespace ostd BaseObject::setValid(true); } - Color::Color(uint8_t rgb_single_value, uint8_t alpha) : r(*this), g(*this), b(*this), a(*this) + Color::Color(u8 rgb_single_value, u8 alpha) : r(*this), g(*this), b(*this), a(*this) { set(rgb_single_value, alpha); setTypeName("ox::Color"); BaseObject::setValid(true); } - Color::Color(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t alpha) : r(*this), g(*this), b(*this), a(*this) + Color::Color(u8 _r, u8 _g, u8 _b, u8 alpha) : r(*this), g(*this), b(*this), a(*this) { set(_r, _g, _b, alpha); setTypeName("ox::Color"); @@ -42,10 +42,10 @@ namespace ostd Color::Color(const Color& copy) : BaseObject(copy), r(*this), g(*this), b(*this), a(*this) { - r = static_cast(copy.r); - g = static_cast(copy.g); - b = static_cast(copy.b); - a = static_cast(copy.a); + r = cast(copy.r); + g = cast(copy.g); + b = cast(copy.b); + a = cast(copy.a); } bool Color::operator==(const Color& col2) @@ -61,10 +61,10 @@ namespace ostd Color& Color::operator=(const Color& copy) { BaseObject::operator=(copy); - r = static_cast(copy.r); - g = static_cast(copy.g); - b = static_cast(copy.b); - a = static_cast(copy.a); + r = cast(copy.r); + g = cast(copy.g); + b = cast(copy.b); + a = cast(copy.a); return *this; } @@ -77,7 +77,7 @@ namespace ostd return *this; } - Color& Color::set(uint8_t rgb_single_value, uint8_t alpha) + Color& Color::set(u8 rgb_single_value, u8 alpha) { r = rgb_single_value; g = rgb_single_value; @@ -86,7 +86,7 @@ namespace ostd return *this; } - Color& Color::set(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t alpha) + Color& Color::set(u8 _r, u8 _g, u8 _b, u8 alpha) { r = _r; g = _g; @@ -111,12 +111,12 @@ namespace ostd } if (se.startsWith("0x")) { - int64_t ic = se.toInt(); + i64 ic = se.toInt(); union uC32 { - uint8_t data[4]; - uint32_t value; + u8 data[4]; + u32 value; } c32_u; - c32_u.value = static_cast(ic); + c32_u.value = cast(ic); a = c32_u.data[0]; b = c32_u.data[1]; g = c32_u.data[2]; @@ -147,14 +147,14 @@ namespace ostd Color& Color::set(const FloatCol& normalized_color) { - r = static_cast(std::round(normalized_color.r * 255)); - g = static_cast(std::round(normalized_color.g * 255)); - b = static_cast(std::round(normalized_color.b * 255)); - a = static_cast(std::round(normalized_color.a * 255)); + r = cast(std::round(normalized_color.r * 255)); + g = cast(std::round(normalized_color.g * 255)); + b = cast(std::round(normalized_color.b * 255)); + a = cast(std::round(normalized_color.a * 255)); return *this; } - String Color::hexString(bool include_alpha, String prefix) const + String Color::hexString(bool include_alpha, const String& prefix) const { String hex = ""; hex += String::getHexStr(r, false, 1); @@ -181,11 +181,11 @@ namespace ostd return rgb; } - uint32_t Color::asInteger(eColorFormat format) const + u32 Color::asInteger(eColorFormat format) const { union uC32 { - uint8_t data[4]; - uint32_t value; + u8 data[4]; + u32 value; } c32_u; if (format == eColorFormat::RGBA) { @@ -235,11 +235,11 @@ namespace ostd } } - void Color::RGBtoHSV(float r, float g, float b, float& h, float& s, float& v) + void Color::RGBtoHSV(f32 r, f32 g, f32 b, f32& h, f32& s, f32& v) { - float max = std::max({r, g, b}); - float min = std::min({r, g, b}); - float d = max - min; + f32 max = std::max({r, g, b}); + f32 min = std::min({r, g, b}); + f32 d = max - min; v = max; @@ -259,13 +259,13 @@ namespace ostd h /= 6.0f; } - void Color::HSVtoRGB(float h, float s, float v, float& r, float& g, float& b) + void Color::HSVtoRGB(f32 h, f32 s, f32 v, f32& r, f32& g, f32& b) { - int i = static_cast(h * 6); - float f = h * 6 - i; - float p = v * (1 - s); - float q = v * (1 - f * s); - float t = v * (1 - (1 - f) * s); + i32 i = cast(h * 6); + f32 f = h * 6 - i; + f32 p = v * (1 - s); + f32 q = v * (1 - f * s); + f32 t = v * (1 - (1 - f) * s); switch (i % 6) { diff --git a/src/ostd/data/Color.hpp b/src/ostd/data/Color.hpp index 8ba44f8..2553893 100755 --- a/src/ostd/data/Color.hpp +++ b/src/ostd/data/Color.hpp @@ -1,26 +1,25 @@ /* - OmniaFramework - A collection of useful functionality - Copyright (C) 2025 OmniaX-Dev + OmniaFramework - A collection of useful functionality + Copyright (C) 2025 OmniaX-Dev - This file is part of OmniaFramework. + This file is part of OmniaFramework. - OmniaFramework is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + OmniaFramework is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - OmniaFramework is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + OmniaFramework is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with OmniaFramework. If not, see . + You should have received a copy of the GNU General Public License + along with OmniaFramework. If not, see . */ #pragma once -#include #include #include #include @@ -31,26 +30,26 @@ namespace ostd { public: struct FloatCol { - float r; - float g; - float b; - float a; + f32 r; + f32 g; + f32 b; + f32 a; FloatCol(void) : r(0.0f), g(0.0f), b(0.0f), a(1.0f) { } - FloatCol(float _r, float _g, float _b, float _a) : r(_r), g(_g), b(_b), a(_a) { } + FloatCol(f32 _r, f32 _g, f32 _b, f32 _a) : r(_r), g(_g), b(_b), a(_a) { } }; public: struct Channel { - uint8_t value; + u8 value; Color& parent; inline Channel(Color& _parent) : parent(_parent) { value = 0; } - inline operator uint8_t() const { return value; } - inline Channel& operator=(uint8_t v) + inline operator u8() const { return value; } + inline Channel& operator=(u8 v) { - value = v; - parent.m_dirty = true; - return *this; + value = v; + parent.m_dirty = true; + return *this; } }; @@ -58,8 +57,8 @@ namespace ostd public: Color(void); - Color(uint8_t rgb_single_value, uint8_t alpha = 255); - Color(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t alpha = 255); + Color(u8 rgb_single_value, u8 alpha = 255); + Color(u8 _r, u8 _g, u8 _b, u8 alpha = 255); Color(const String& color_string); Color(const FloatCol& normalized_color); Color(const Color& copy); @@ -69,14 +68,14 @@ namespace ostd Color& operator=(const Color& copy); Color& set(void); - Color& set(uint8_t rgb_single_value, uint8_t alpha = 255); - Color& set(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t alpha = 255); + Color& set(u8 rgb_single_value, u8 alpha = 255); + Color& set(u8 _r, u8 _g, u8 _b, u8 alpha = 255); Color& set(const String& color_string); Color& set(const FloatCol& normalized_color); - String hexString(bool include_alpha = false, String prefix = "0x") const; + String hexString(bool include_alpha = false, const String& prefix = "0x") const; String rgbString(bool include_parenthesis = true, bool include_alpha = false) const; - uint32_t asInteger(eColorFormat format = eColorFormat::RGBA) const; + u32 asInteger(eColorFormat format = eColorFormat::RGBA) const; FloatCol getNormalizedColor(void) const; String toString(void) const override; @@ -84,8 +83,8 @@ namespace ostd inline void invalidate(void) override { } inline void setValid(bool valid) override { } - static void RGBtoHSV(float r, float g, float b, float& h, float& s, float& v); - static void HSVtoRGB(float h, float s, float v, float& r, float& g, float& b); + static void RGBtoHSV(f32 r, f32 g, f32 b, f32& h, f32& s, f32& v); + static void HSVtoRGB(f32 h, f32 s, f32 v, f32& r, f32& g, f32& b); public: Channel r; @@ -95,7 +94,7 @@ namespace ostd private: mutable bool m_dirty { true }; - mutable FloatCol m_cachedFloat { 0, 0, 0, 0 }; + mutable FloatCol m_cachedFloat { 0, 0, 0, 0 }; public: }; diff --git a/src/ostd/data/Types.hpp b/src/ostd/data/Types.hpp index 589878c..d73d4a6 100755 --- a/src/ostd/data/Types.hpp +++ b/src/ostd/data/Types.hpp @@ -1,21 +1,21 @@ /* - OmniaFramework - A collection of useful functionality - Copyright (C) 2025 OmniaX-Dev + OmniaFramework - A collection of useful functionality + Copyright (C) 2025 OmniaX-Dev - This file is part of OmniaFramework. + This file is part of OmniaFramework. - OmniaFramework is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + OmniaFramework is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - OmniaFramework is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + OmniaFramework is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with OmniaFramework. If not, see . + You should have received a copy of the GNU General Public License + along with OmniaFramework. If not, see . */ #pragma once @@ -23,45 +23,67 @@ #include #include #include +#include #include +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef i8 b8; +typedef float f32; +typedef double f64; +typedef unsigned char uchar; + +template +using stdvec = std::vector; +template +using stdumap = std::unordered_map; + +#define cast static_cast + namespace ostd { typedef std::string cpp_string; - typedef int64_t QWord; - typedef int32_t DWord; - typedef int16_t Word; - typedef int8_t Byte; + typedef i64 QWord; + typedef i32 DWord; + typedef i16 Word; + typedef i8 Byte; + + typedef u64 UQWord; + typedef u32 UDWord; + typedef u16 UWord; + typedef u8 UByte; - typedef uint64_t UQWord; - typedef uint32_t UDWord; - typedef uint16_t UWord; - typedef uint8_t UByte; typedef uint32_t StreamIndex; typedef union { - float val; - Byte data[4]; - int32_t raw; + f32 val; + i8 data[4]; + i32 raw; } __float_parser; typedef union { - double val; - Byte data[8]; - int64_t raw; + f64 val; + i8 data[8]; + i64 raw; } __double_parser; struct tTypeSize { - static inline const uint8_t BYTE = 1; - static inline const uint8_t WORD = 2; - static inline const uint8_t DWORD = 4; - static inline const uint8_t QWORD = 8; - static inline const uint8_t ADDR = 4; - static inline const uint8_t FLOAT = 4; - static inline const uint8_t DOUBLE = 8; + static inline const u8 BYTE = 1; + static inline const u8 WORD = 2; + static inline const u8 DWORD = 4; + static inline const u8 QWORD = 8; + static inline const u8 ADDR = 4; + static inline const u8 FLOAT = 4; + static inline const u8 DOUBLE = 8; }; - typedef std::vector ByteStream; + typedef stdvec ByteStream; } diff --git a/src/ostd/io/Console.cpp b/src/ostd/io/Console.cpp index 10e460c..35f5bc0 100644 --- a/src/ostd/io/Console.cpp +++ b/src/ostd/io/Console.cpp @@ -31,7 +31,7 @@ void BasicConsole::clearConsole(void) SetConsoleCursorPosition( hStdOut, homeCoords ); } -void BasicConsole::getConsoleSize(int32_t& outColumns, int32_t& outRows) +void BasicConsole::getConsoleSize(i32& outColumns, i32& outRows) { CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); @@ -39,7 +39,7 @@ void BasicConsole::getConsoleSize(int32_t& outColumns, int32_t& outRows) outRows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; } -void BasicConsole::setConsoleCursorPosition(int32_t x, int32_t y) +void BasicConsole::setConsoleCursorPosition(i32 x, i32 y) { COORD coord; coord.X = x; coord.Y = y; @@ -63,7 +63,7 @@ void BasicConsole::clearConsole(void) { if (!cur_term) { - int result; + i32 result; setupterm(NULL, STDOUT_FILENO, &result); if (result <= 0) return; } @@ -71,7 +71,7 @@ void BasicConsole::clearConsole(void) putp(tigetstr( "clear" )); } -void BasicConsole::getConsoleSize(int32_t& outColumns, int32_t& outRows) +void BasicConsole::getConsoleSize(i32& outColumns, i32& outRows) { struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); @@ -79,7 +79,7 @@ void BasicConsole::getConsoleSize(int32_t& outColumns, int32_t& outRows) outColumns = w.ws_col; } -void BasicConsole::setConsoleCursorPosition(int32_t x, int32_t y) +void BasicConsole::setConsoleCursorPosition(i32 x, i32 y) { printf("\033[%d;%dH",y+1,x+1); } @@ -100,7 +100,7 @@ IPoint BasicConsole::getConsoleCursorPosition(void) std::fflush(stdout); // Read response: ESC [ row ; col R - int row = 0, col = 0; + i32 row = 0, col = 0; if (std::scanf("\033[%d;%dR", &row, &col) != 2) { // Failed to parse row = col = -1; @@ -126,7 +126,7 @@ void BasicConsole::clearConsole(void) std::fflush(stdout); } -void BasicConsole::getConsoleSize(int32_t& outColumns, int32_t& outRows) +void BasicConsole::getConsoleSize(i32& outColumns, i32& outRows) { struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); @@ -134,7 +134,7 @@ void BasicConsole::getConsoleSize(int32_t& outColumns, int32_t& outRows) outColumns = w.ws_col; } -void BasicConsole::setConsoleCursorPosition(int32_t x, int32_t y) +void BasicConsole::setConsoleCursorPosition(i32 x, i32 y) { // ANSI escape sequence: move cursor to (y+1, x+1) std::printf("\033[%d;%dH", y + 1, x + 1); @@ -157,7 +157,7 @@ IPoint BasicConsole::getConsoleCursorPosition(void) std::fflush(stdout); // Read response: ESC [ row ; col R - int row = 0, col = 0; + i32 row = 0, col = 0; if (std::scanf("\033[%d;%dR", &row, &col) != 2) { // Failed to parse row = col = -1; @@ -173,16 +173,16 @@ IPoint BasicConsole::getConsoleCursorPosition(void) #endif -int32_t BasicConsole::getConsoleWidth(void) +i32 BasicConsole::getConsoleWidth(void) { - int32_t rows = 0, cols = 0; + i32 rows = 0, cols = 0; getConsoleSize(cols, rows); return cols; } -int32_t BasicConsole::getConsoleHeight(void) +i32 BasicConsole::getConsoleHeight(void) { - int32_t rows = 0, cols = 0; + i32 rows = 0, cols = 0; getConsoleSize(rows, cols); return rows; } @@ -263,55 +263,55 @@ OutputHandlerBase& InteractiveConsole::p(const String& se) return *this; } -OutputHandlerBase& InteractiveConsole::p(uint8_t i) +OutputHandlerBase& InteractiveConsole::p(u8 i) { - std::cout << (uint8_t)i; + std::cout << (u8)i; return *this; } -OutputHandlerBase& InteractiveConsole::p(int8_t i) +OutputHandlerBase& InteractiveConsole::p(i8 i) { - std::cout << (int8_t)i; + std::cout << (i8)i; return *this; } -OutputHandlerBase& InteractiveConsole::p(uint16_t i) +OutputHandlerBase& InteractiveConsole::p(u16 i) { - std::cout << (uint16_t)i; + std::cout << (u16)i; return *this; } -OutputHandlerBase& InteractiveConsole::p(int16_t i) +OutputHandlerBase& InteractiveConsole::p(i16 i) { - std::cout << (int16_t)i; + std::cout << (i16)i; return *this; } -OutputHandlerBase& InteractiveConsole::p(uint32_t i) +OutputHandlerBase& InteractiveConsole::p(u32 i) { - std::cout << (uint32_t)i; + std::cout << (u32)i; return *this; } -OutputHandlerBase& InteractiveConsole::p(int32_t i) +OutputHandlerBase& InteractiveConsole::p(i32 i) { - std::cout << (int32_t)i; + std::cout << (i32)i; return *this; } -OutputHandlerBase& InteractiveConsole::p(uint64_t i) +OutputHandlerBase& InteractiveConsole::p(u64 i) { - std::cout << (uint64_t)i; + std::cout << (u64)i; return *this; } -OutputHandlerBase& InteractiveConsole::p(int64_t i) +OutputHandlerBase& InteractiveConsole::p(i64 i) { - std::cout << (int64_t)i; + std::cout << (i64)i; return *this; } -OutputHandlerBase& InteractiveConsole::p(float f, uint8_t precision) +OutputHandlerBase& InteractiveConsole::p(f32 f, u8 precision) { if (precision == 0) { @@ -326,7 +326,7 @@ OutputHandlerBase& InteractiveConsole::p(float f, uint8_t precision) return *this; } -OutputHandlerBase& InteractiveConsole::p(double f, uint8_t precision) +OutputHandlerBase& InteractiveConsole::p(f64 f, u8 precision) { if (precision == 0) { @@ -365,14 +365,14 @@ OutputHandlerBase& InteractiveConsole::clear(void) return *this; } -void InteractiveConsole::getConsoleSize(int32_t& outColumns, int32_t& outRows) +void InteractiveConsole::getConsoleSize(i32& outColumns, i32& outRows) { BasicConsole::getConsoleSize(outColumns, outRows); } IPoint InteractiveConsole::getConsoleSize(void) { - int32_t x = 0, y = 0; + i32 x = 0, y = 0; BasicConsole::getConsoleSize(x, y); return { x, y }; } @@ -397,7 +397,7 @@ void InteractiveConsole::__construct_buffer(void) return; } m_oldConsoleSize = console_size; - int32_t linear_size = m_oldConsoleSize.x * m_oldConsoleSize.y; + i32 linear_size = m_oldConsoleSize.x * m_oldConsoleSize.y; m_buffer.resize(linear_size); m_secondBuffer.resize(linear_size); m_validBuffer = false; @@ -414,7 +414,7 @@ void InteractiveConsole::__swap_buffers(void) void InteractiveConsole::__validate_and_clear_buffers(void) { if (m_validBuffer) return; - for (int32_t i = 0; i < m_buffer.size(); i++) + for (i32 i = 0; i < m_buffer.size(); i++) m_buffer[i] = m_secondBuffer[i] = m_emptyChar; m_validBuffer = true; } diff --git a/src/ostd/io/Console.hpp b/src/ostd/io/Console.hpp index 676802f..a65e344 100644 --- a/src/ostd/io/Console.hpp +++ b/src/ostd/io/Console.hpp @@ -30,7 +30,6 @@ #else #include #endif -#include namespace ostd { @@ -38,11 +37,11 @@ namespace ostd { public: static void clearConsole(void); - static void getConsoleSize(int32_t& outColumns, int32_t& outRows); - static void setConsoleCursorPosition(int32_t x, int32_t y); + static void getConsoleSize(i32& outColumns, i32& outRows); + static void setConsoleCursorPosition(i32 x, i32 y); static IPoint getConsoleCursorPosition(void); - static int32_t getConsoleWidth(void); - static int32_t getConsoleHeight(void); + static i32 getConsoleWidth(void); + static i32 getConsoleHeight(void); }; class InteractiveConsole : public OutputHandlerBase @@ -69,16 +68,16 @@ namespace ostd OutputHandlerBase& pObject(const BaseObject& bo) override; OutputHandlerBase& p(const String& se) override; - OutputHandlerBase& p(uint8_t i) override; - OutputHandlerBase& p(int8_t i) override; - OutputHandlerBase& p(uint16_t i) override; - OutputHandlerBase& p(int16_t i) override; - OutputHandlerBase& p(uint32_t i) override; - OutputHandlerBase& p(int32_t i) override; - OutputHandlerBase& p(uint64_t i) override; - OutputHandlerBase& p(int64_t i) override; - OutputHandlerBase& p(float f, uint8_t precision = 0) override; - OutputHandlerBase& p(double f, uint8_t precision = 0) override; + OutputHandlerBase& p(u8 i) override; + OutputHandlerBase& p(i8 i) override; + OutputHandlerBase& p(u16 i) override; + OutputHandlerBase& p(i16 i) override; + OutputHandlerBase& p(u32 i) override; + OutputHandlerBase& p(i32 i) override; + OutputHandlerBase& p(u64 i) override; + OutputHandlerBase& p(i64 i) override; + OutputHandlerBase& p(f32 f, u8 precision = 0) override; + OutputHandlerBase& p(f64 f, u8 precision = 0) override; OutputHandlerBase& nl(void) override; OutputHandlerBase& flush(void) override; @@ -86,17 +85,17 @@ namespace ostd OutputHandlerBase& clear(void) override; inline OutputHandlerBase& xy(IPoint position) override { m_cursorPosition = position; __set_cursor(); return *this; } - inline OutputHandlerBase& xy(int32_t x, int32_t y) override { m_cursorPosition = { x, y }; __set_cursor(); return *this; } - inline OutputHandlerBase& x(int32_t x) override { m_cursorPosition.x = x; __set_cursor(); return *this; } - inline OutputHandlerBase& y(int32_t y) override { m_cursorPosition.y = y; __set_cursor(); return *this; } + inline OutputHandlerBase& xy(i32 x, i32 y) override { m_cursorPosition = { x, y }; __set_cursor(); return *this; } + inline OutputHandlerBase& x(i32 x) override { m_cursorPosition.x = x; __set_cursor(); return *this; } + inline OutputHandlerBase& y(i32 y) override { m_cursorPosition.y = y; __set_cursor(); return *this; } - void getConsoleSize(int32_t& outColumns, int32_t& outRows) override; + void getConsoleSize(i32& outColumns, i32& outRows) override; IPoint getConsoleSize(void) override; inline IPoint getCursorPosition(void) override { return m_cursorPosition; } - inline void getCursorPosition(int32_t& outX, int32_t& outY) override { outX = m_cursorPosition.x; outY = m_cursorPosition.y; } - inline int32_t getCursorX(void) override { return m_cursorPosition.x; } - inline int32_t getCursorY(void) override { return m_cursorPosition.y; } + inline void getCursorPosition(i32& outX, i32& outY) override { outX = m_cursorPosition.x; outY = m_cursorPosition.y; } + inline i32 getCursorX(void) override { return m_cursorPosition.x; } + inline i32 getCursorY(void) override { return m_cursorPosition.y; } //InteractiveConsole inline void enableDirectMode(void) { m_mode = eMode::Direct; } @@ -117,8 +116,8 @@ namespace ostd IPoint m_cursorPosition { 0, 0 }; IPoint m_oldConsoleSize { 0, 0 }; eMode m_mode { eMode::Direct }; - std::vector m_buffer; - std::vector m_secondBuffer; + stdvec m_buffer; + stdvec m_secondBuffer; bool m_validBuffer { false }; tRichChar m_emptyChar { @@ -202,17 +201,17 @@ namespace ostd String flushKeyBuffer(void); #ifndef WINDOWS_OS - int kbhit(void); - int getch(void); + i32 kbhit(void); + i32 getch(void); #endif private: #ifndef WINDOWS_OS struct termios initial_settings, new_settings; - int peek_character; + i32 peek_character; #endif - std::vector m_key_buff; + stdvec m_key_buff; String m_cmd; bool m_output_enabled; bool m_cmd_buffer_enabled; diff --git a/src/ostd/io/Errors.cpp b/src/ostd/io/Errors.cpp index 8e73e85..65b321b 100755 --- a/src/ostd/io/Errors.cpp +++ b/src/ostd/io/Errors.cpp @@ -4,7 +4,7 @@ namespace ostd { - RuntimeError& RuntimeError::create(uint8_t group, uint64_t code, uint8_t level, const String &msg) + RuntimeError& RuntimeError::create(u8 group, u64 code, u8 level, const String &msg) { m_errGroup = group; m_errCode = code; @@ -15,7 +15,7 @@ namespace ostd return *this; } - void RuntimeError::fire(const String& extraMessage, OutputHandlerBase* outputHandler, BaseObject& userData, int32_t _line_num, const String& _file_name) + void RuntimeError::fire(const String& extraMessage, OutputHandlerBase* outputHandler, BaseObject& userData, i32 _line_num, const String& _file_name) { if (isInvalid() || m_errGroup == 0x0 || m_errLevel == tErrorLevel::NoError || m_errCode == 0x0) return; String errorMessage = m_message + "\n"; diff --git a/src/ostd/io/Errors.hpp b/src/ostd/io/Errors.hpp index 90a6e06..633960b 100755 --- a/src/ostd/io/Errors.hpp +++ b/src/ostd/io/Errors.hpp @@ -29,25 +29,25 @@ namespace ostd { struct tErrorLevel { - inline static constexpr uint8_t NoError = 0x00; - inline static constexpr uint8_t Warning = 0x01; - inline static constexpr uint8_t Error = 0x02; - inline static constexpr uint8_t Fatal = 0x03; + inline static constexpr u8 NoError = 0x00; + inline static constexpr u8 Warning = 0x01; + inline static constexpr u8 Error = 0x02; + inline static constexpr u8 Fatal = 0x03; }; class RuntimeError : public BaseObject { public: inline RuntimeError(void) { invalidate(); } - inline RuntimeError(uint8_t group, uint64_t code, uint8_t level, const String& msg) { create(group, code, level, msg); } - RuntimeError& create(uint8_t group, uint64_t code, uint8_t level, const String& msg); + inline RuntimeError(u8 group, u64 code, u8 level, const String& msg) { create(group, code, level, msg); } + RuntimeError& create(u8 group, u64 code, u8 level, const String& msg); - void fire(const String& extraMessage = "", OutputHandlerBase* outputHandler = nullptr, BaseObject& userData = BaseObject::InvalidRef(), int32_t _line_num = 0, const String& _file_name = ""); + void fire(const String& extraMessage = "", OutputHandlerBase* outputHandler = nullptr, BaseObject& userData = BaseObject::InvalidRef(), i32 _line_num = 0, const String& _file_name = ""); private: - uint8_t m_errGroup { 0x00 }; - uint8_t m_errLevel { tErrorLevel::NoError }; - uint64_t m_errCode { 0x0000000000000000 }; + u8 m_errGroup { 0x00 }; + u8 m_errLevel { tErrorLevel::NoError }; + u64 m_errCode { 0x0000000000000000 }; String m_message { "" }; }; diff --git a/src/ostd/io/File.cpp b/src/ostd/io/File.cpp index b006c24..332ad7c 100755 --- a/src/ostd/io/File.cpp +++ b/src/ostd/io/File.cpp @@ -38,7 +38,7 @@ namespace ostd return *this; } - std::vector TextFileBuffer::getLines(const String& separator, bool trim_tokens, bool allow_white_space_only_tokens) + stdvec TextFileBuffer::getLines(const String& separator, bool trim_tokens, bool allow_white_space_only_tokens) { if (!exists()) return { }; auto st = String(m_buffer); diff --git a/src/ostd/io/File.hpp b/src/ostd/io/File.hpp index ca6c347..a4896b7 100755 --- a/src/ostd/io/File.hpp +++ b/src/ostd/io/File.hpp @@ -21,7 +21,7 @@ #pragma once #include -#include + #include #include @@ -42,7 +42,7 @@ namespace ostd inline const String& name(void) const { return m_name; } inline const String& rawContent(void) { return m_buffer; } - std::vector getLines(const String& separator = "\n", bool trim_tokens = true, bool allow_white_space_only_tokens = false); + stdvec getLines(const String& separator = "\n", bool trim_tokens = true, bool allow_white_space_only_tokens = false); inline bool exists(void) { return isValid(); } diff --git a/src/ostd/io/FileSystem.cpp b/src/ostd/io/FileSystem.cpp index 5018dd3..25155ac 100644 --- a/src/ostd/io/FileSystem.cpp +++ b/src/ostd/io/FileSystem.cpp @@ -5,9 +5,9 @@ namespace ostd { - std::vector FileSystem::listFilesInDirectory(const String& directoryPath) + stdvec FileSystem::listFilesInDirectory(const String& directoryPath) { - std::vector list; + stdvec list; for (const auto& file : std::filesystem::directory_iterator(directoryPath.cpp_str())) { if (!std::filesystem::is_directory(file.path())) @@ -16,9 +16,9 @@ namespace ostd return list; } - std::vector FileSystem::listDirectoriesInDirectory(const String& directoryPath) + stdvec FileSystem::listDirectoriesInDirectory(const String& directoryPath) { - std::vector list; + stdvec list; for (const auto& file : std::filesystem::directory_iterator(directoryPath.cpp_str())) { if (std::filesystem::is_directory(file.path())) @@ -27,17 +27,17 @@ namespace ostd return list; } - std::vector FileSystem::listDirectory(const String& directoryPath) + stdvec FileSystem::listDirectory(const String& directoryPath) { - std::vector list; + stdvec list; for (const auto& file : std::filesystem::directory_iterator(directoryPath.cpp_str())) list.push_back(file.path()); return list; } - std::vector FileSystem::listFilesInDirectoryRecursive(const String& directoryPath) + stdvec FileSystem::listFilesInDirectoryRecursive(const String& directoryPath) { - std::vector list; + stdvec list; for (const auto& file : std::filesystem::recursive_directory_iterator(directoryPath.cpp_str())) { if (!std::filesystem::is_directory(file.path())) @@ -46,9 +46,9 @@ namespace ostd return list; } - std::vector FileSystem::listDirectoriesInDirectoryRecursive(const String& directoryPath) + stdvec FileSystem::listDirectoriesInDirectoryRecursive(const String& directoryPath) { - std::vector list; + stdvec list; for (const auto& file : std::filesystem::recursive_directory_iterator(directoryPath.cpp_str())) { if (std::filesystem::is_directory(file.path())) @@ -57,9 +57,9 @@ namespace ostd return list; } - std::vector FileSystem::listDirectoryRecursive(const String& directoryPath) + stdvec FileSystem::listDirectoryRecursive(const String& directoryPath) { - std::vector list; + stdvec list; for (const auto& file : std::filesystem::recursive_directory_iterator(directoryPath.cpp_str())) list.push_back(file.path()); return list; @@ -245,7 +245,7 @@ namespace ostd } } - bool FileSystem::isValidFileCreationPath(const ostd::String& filePath) + bool FileSystem::isValidFileCreationPath(const String& filePath) { namespace fs = std::filesystem; try @@ -268,7 +268,7 @@ namespace ostd } } - bool FileSystem::isValidDirectoryCreationPath(const ostd::String& directoryPath) + bool FileSystem::isValidDirectoryCreationPath(const String& directoryPath) { namespace fs = std::filesystem; try { @@ -290,7 +290,7 @@ namespace ostd } } - FileSystem::ePathStatus FileSystem::getPathStatus(const ostd::String& path) + FileSystem::ePathStatus FileSystem::getPathStatus(const String& path) { if (directoryExists(path)) return ePathStatus::ExistingDirectory; @@ -302,7 +302,7 @@ namespace ostd } - bool FileSystem::readTextFile(String fileName, std::vector& outLines) + bool FileSystem::readTextFile(const String& fileName, stdvec& outLines) { String line; std::ifstream file(fileName.cpp_str()); @@ -313,9 +313,9 @@ namespace ostd return true; } - bool FileSystem::readTextFileRaw(String fileName, String& outString) + bool FileSystem::readTextFileRaw(const String& fileName, String& outString) { - std::vector lines; + stdvec lines; if (!readTextFile(fileName, lines)) return false; outString.clr(); @@ -324,7 +324,7 @@ namespace ostd return true; } - bool FileSystem::writeTextFile(const ostd::String& filePath, const std::vector& lines, bool truncate) + bool FileSystem::writeTextFile(const String& filePath, const stdvec& lines, bool truncate) { namespace fs = std::filesystem; ePathStatus status = getPathStatus(filePath); @@ -356,18 +356,18 @@ namespace ostd } - bool FileSystem::writeTextFileRaw(const ostd::String& filePath, const ostd::String& lines, bool truncate) + bool FileSystem::writeTextFileRaw(const String& filePath, const String& lines, bool truncate) { auto _lines = lines.tokenize("\n", false, true).getRawData(); return writeTextFile(filePath, _lines, truncate); } - bool FileSystem::loadFileFromHppResource(String output_file_path, const char* resource_buffer, unsigned int size) + bool FileSystem::loadFileFromHppResource(const String& output_file_path, const char* resource_buffer, u32 size) { - unsigned char ext_len = resource_buffer[0]; + uchar ext_len = resource_buffer[0]; String ext = ""; - for (unsigned char i = 0; i < ext_len; i++) + for (uchar i = 0; i < ext_len; i++) ext += (char)(resource_buffer[i + 1]); if (String(output_file_path).trim().toLower().endsWith(ext)) ext = ""; diff --git a/src/ostd/io/FileSystem.hpp b/src/ostd/io/FileSystem.hpp index df7dd0b..53c3c8d 100644 --- a/src/ostd/io/FileSystem.hpp +++ b/src/ostd/io/FileSystem.hpp @@ -20,7 +20,7 @@ #pragma once -#include + #include #include @@ -31,12 +31,12 @@ namespace ostd public: enum class ePathStatus { Invalid = 0, ExistingDirectory, ExistingFile, ValidNewPath }; public: - static std::vector listFilesInDirectory(const String& directoryPath); - static std::vector listDirectoriesInDirectory(const String& directoryPath); - static std::vector listDirectory(const String& directoryPath); - static std::vector listFilesInDirectoryRecursive(const String& directoryPath); - static std::vector listDirectoriesInDirectoryRecursive(const String& directoryPath); - static std::vector listDirectoryRecursive(const String& directoryPath); + static stdvec listFilesInDirectory(const String& directoryPath); + static stdvec listDirectoriesInDirectory(const String& directoryPath); + static stdvec listDirectory(const String& directoryPath); + static stdvec listFilesInDirectoryRecursive(const String& directoryPath); + static stdvec listDirectoriesInDirectoryRecursive(const String& directoryPath); + static stdvec listDirectoryRecursive(const String& directoryPath); static std::filesystem::path getHomeDirPath(void); static std::filesystem::path getWorkingDirPath(void); @@ -49,15 +49,15 @@ namespace ostd static bool directoryExists(const String& directoryPath); static bool fileExists(const String& filePath); static bool pathExists(const String& path); - static bool isValidFileCreationPath(const ostd::String& filePath); - static bool isValidDirectoryCreationPath(const ostd::String& directoryPath); - static ePathStatus getPathStatus(const ostd::String& path); + static bool isValidFileCreationPath(const String& filePath); + static bool isValidDirectoryCreationPath(const String& directoryPath); + static ePathStatus getPathStatus(const String& path); - static bool readTextFile(String fileName, std::vector& outLines); - static bool readTextFileRaw(String fileName, String& outString); - static bool writeTextFile(const ostd::String& filePath, const std::vector& lines, bool truncate = true); - static bool writeTextFileRaw(const ostd::String& filePath, const ostd::String& lines, bool truncate = true); + static bool readTextFile(const String& fileName, stdvec& outLines); + static bool readTextFileRaw(const String& fileName, String& outString); + static bool writeTextFile(const String& filePath, const stdvec& lines, bool truncate = true); + static bool writeTextFileRaw(const String& filePath, const String& lines, bool truncate = true); - static bool loadFileFromHppResource(String output_file_path, const char* resource_buffer, unsigned int size); + static bool loadFileFromHppResource(const String& output_file_path, const char* resource_buffer, u32 size); }; } diff --git a/src/ostd/io/IOHandlers.hpp b/src/ostd/io/IOHandlers.hpp index baf9a4b..4eeba36 100644 --- a/src/ostd/io/IOHandlers.hpp +++ b/src/ostd/io/IOHandlers.hpp @@ -150,16 +150,16 @@ namespace ostd inline virtual OutputHandlerBase& pObject(const BaseObject& bo) { return *this; } inline virtual OutputHandlerBase& p(const String& se) { return *this; } - inline virtual OutputHandlerBase& p(uint8_t i) { return *this; } - inline virtual OutputHandlerBase& p(int8_t i) { return *this; } - inline virtual OutputHandlerBase& p(uint16_t i) { return *this; } - inline virtual OutputHandlerBase& p(int16_t i) { return *this; } - inline virtual OutputHandlerBase& p(uint32_t i) { return *this; } - inline virtual OutputHandlerBase& p(int32_t i) { return *this; } - inline virtual OutputHandlerBase& p(uint64_t i) { return *this; } - inline virtual OutputHandlerBase& p(int64_t i) { return *this; } - inline virtual OutputHandlerBase& p(float f, uint8_t precision = 0) { return *this; } - inline virtual OutputHandlerBase& p(double f, uint8_t precision = 0) { return *this; } + inline virtual OutputHandlerBase& p(u8 i) { return *this; } + inline virtual OutputHandlerBase& p(i8 i) { return *this; } + inline virtual OutputHandlerBase& p(u16 i) { return *this; } + inline virtual OutputHandlerBase& p(i16 i) { return *this; } + inline virtual OutputHandlerBase& p(u32 i) { return *this; } + inline virtual OutputHandlerBase& p(i32 i) { return *this; } + inline virtual OutputHandlerBase& p(u64 i) { return *this; } + inline virtual OutputHandlerBase& p(i64 i) { return *this; } + inline virtual OutputHandlerBase& p(f32 f, u8 precision = 0) { return *this; } + inline virtual OutputHandlerBase& p(f64 f, u8 precision = 0) { return *this; } inline virtual OutputHandlerBase& nl(void) { return *this; } inline virtual OutputHandlerBase& tab(void) { return *this; } @@ -168,16 +168,16 @@ namespace ostd inline virtual OutputHandlerBase& clear(void) { return *this; } inline virtual OutputHandlerBase& xy(IPoint position) { return *this; } - inline virtual OutputHandlerBase& xy(int32_t x, int32_t y) { return *this; } - inline virtual OutputHandlerBase& x(int32_t x) { return *this; } - inline virtual OutputHandlerBase& y(int32_t y) { return *this; } + inline virtual OutputHandlerBase& xy(i32 x, i32 y) { return *this; } + inline virtual OutputHandlerBase& x(i32 x) { return *this; } + inline virtual OutputHandlerBase& y(i32 y) { return *this; } inline virtual IPoint getCursorPosition(void) { return { 0, 0 }; } - inline virtual void getCursorPosition(int32_t& outX, int32_t& outY) { } - inline virtual int32_t getCursorX(void) { return 0; } - inline virtual int32_t getCursorY(void) { return 0; } + inline virtual void getCursorPosition(i32& outX, i32& outY) { } + inline virtual i32 getCursorX(void) { return 0; } + inline virtual i32 getCursorY(void) { return 0; } - inline virtual void getConsoleSize(int32_t& outColumns, int32_t& outRows) { } + inline virtual void getConsoleSize(i32& outColumns, i32& outRows) { } inline virtual IPoint getConsoleSize(void) { return { 0, 0 }; } }; @@ -198,16 +198,16 @@ namespace ostd OutputHandlerBase& pObject(const BaseObject& bo) override; OutputHandlerBase& p(const String& se) override; - OutputHandlerBase& p(uint8_t i) override; - OutputHandlerBase& p(int8_t i) override; - OutputHandlerBase& p(uint16_t i) override; - OutputHandlerBase& p(int16_t i) override; - OutputHandlerBase& p(uint32_t i) override; - OutputHandlerBase& p(int32_t i) override; - OutputHandlerBase& p(uint64_t i) override; - OutputHandlerBase& p(int64_t i) override; - OutputHandlerBase& p(float f, uint8_t precision = 0) override; - OutputHandlerBase& p(double f, uint8_t precision = 0) override; + OutputHandlerBase& p(u8 i) override; + OutputHandlerBase& p(i8 i) override; + OutputHandlerBase& p(u16 i) override; + OutputHandlerBase& p(i16 i) override; + OutputHandlerBase& p(u32 i) override; + OutputHandlerBase& p(i32 i) override; + OutputHandlerBase& p(u64 i) override; + OutputHandlerBase& p(i64 i) override; + OutputHandlerBase& p(f32 f, u8 precision = 0) override; + OutputHandlerBase& p(f64 f, u8 precision = 0) override; OutputHandlerBase& nl(void) override; OutputHandlerBase& flush(void) override; @@ -215,16 +215,16 @@ namespace ostd OutputHandlerBase& clear(void) override; OutputHandlerBase& xy(IPoint position) override; - OutputHandlerBase& xy(int32_t x, int32_t y) override; - OutputHandlerBase& x(int32_t x) override; - OutputHandlerBase& y(int32_t y) override; + OutputHandlerBase& xy(i32 x, i32 y) override; + OutputHandlerBase& x(i32 x) override; + OutputHandlerBase& y(i32 y) override; IPoint getCursorPosition(void) override; - void getCursorPosition(int32_t& outX, int32_t& outY) override; - int32_t getCursorX(void) override; - int32_t getCursorY(void) override; + void getCursorPosition(i32& outX, i32& outY) override; + i32 getCursorX(void) override; + i32 getCursorY(void) override; - void getConsoleSize(int32_t& outColumns, int32_t& outRows) override; + void getConsoleSize(i32& outColumns, i32& outRows) override; IPoint getConsoleSize(void) override; }; } diff --git a/src/ostd/io/Json.cpp b/src/ostd/io/Json.cpp index 122cc83..09ecd34 100644 --- a/src/ostd/io/Json.cpp +++ b/src/ostd/io/Json.cpp @@ -19,31 +19,31 @@ namespace ostd catch (const json::exception&) { return false; } } }; - // ----- int ---------------------------------------------------------- - template<> struct Getter + // ----- i32 ---------------------------------------------------------- + template<> struct Getter { - static int exec_impl(const std::string& p, const json& root) + static i32 exec_impl(const std::string& p, const json& root) { - try { return root.at(p).get(); } + try { return root.at(p).get(); } catch (const json::exception&) { return 0; } } }; - // ----- double ------------------------------------------------------- - template<> struct Getter + // ----- f64 ------------------------------------------------------- + template<> struct Getter { - static double exec_impl(const std::string& p, const json& root) + static f64 exec_impl(const std::string& p, const json& root) { - try { return root.at(p).get(); } + try { return root.at(p).get(); } catch (const json::exception&) { return 0.0; } } }; - // ----- ostd::String ------------------------------------------------- - template<> struct Getter + // ----- String ------------------------------------------------- + template<> struct Getter { - static ostd::String exec_impl(const std::string& p, const json& root) + static String exec_impl(const std::string& p, const json& root) { - try { return ostd::String(root.at(p).get().c_str()); } - catch (const json::exception&) { return ostd::String(""); } + try { return String(root.at(p).get().c_str()); } + catch (const json::exception&) { return String(""); } } }; // ----- ostd::Color ------------------------------------------------- @@ -66,11 +66,11 @@ namespace ostd // Case 2: Array of integers if (node.is_array() && !node.empty()) { - std::vector vals; + stdvec vals; for (const auto& v : node) { if (!v.is_number_integer()) return ostd::Color(); - int iv = v.get(); + i32 iv = v.get(); if (iv < 0 || iv > 255) return ostd::Color(); vals.push_back(iv); } @@ -100,13 +100,13 @@ namespace ostd const json& node = root.at(p); if (node.is_array() && node.size() == 4) { - std::vector vals; + stdvec vals; vals.reserve(4); for (const auto& v : node) { if (!v.is_number_float() && !v.is_number_integer()) return ostd::Rectangle(); - vals.push_back(v.get()); + vals.push_back(v.get()); } return ostd::Rectangle(vals[0], vals[1], vals[2], vals[3]); } @@ -118,12 +118,12 @@ namespace ostd } } }; - // ----- std::vector ---------------------------------------- - template<> struct Getter> + // ----- stdvec ---------------------------------------- + template<> struct Getter> { - static std::vector exec_impl(const std::string& p, const json& root) + static stdvec exec_impl(const std::string& p, const json& root) { - std::vector result; + stdvec result; try { const json& arr = root.at(p); @@ -131,18 +131,18 @@ namespace ostd for (const auto& v : arr) { if (v.is_number_integer()) - result.push_back(v.get()); + result.push_back(v.get()); } } catch (...) {} return result; } }; - // ----- std::vector ----------------------------------------- - template<> struct Getter> + // ----- stdvec ----------------------------------------- + template<> struct Getter> { - static std::vector exec_impl(const std::string& p, const json& root) + static stdvec exec_impl(const std::string& p, const json& root) { - std::vector result; + stdvec result; try { const json& arr = root.at(p); @@ -150,18 +150,18 @@ namespace ostd for (const auto& v : arr) { if (v.is_number()) - result.push_back(v.get()); + result.push_back(v.get()); } } catch (...) {} return result; } }; - // ----- std::vector ----------------------------------- - template<> struct Getter> + // ----- stdvec ----------------------------------- + template<> struct Getter> { - static std::vector exec_impl(const std::string& p, const json& root) + static stdvec exec_impl(const std::string& p, const json& root) { - std::vector result; + stdvec result; try { const json& arr = root.at(p); @@ -175,12 +175,12 @@ namespace ostd return result; } }; - // ----- std::vector ----------------------------------- - template<> struct Getter> + // ----- stdvec ----------------------------------- + template<> struct Getter> { - static std::vector exec_impl(const std::string& p, const json& root) + static stdvec exec_impl(const std::string& p, const json& root) { - std::vector result; + stdvec result; try { const json& node = root.at(p); @@ -203,7 +203,7 @@ namespace ostd } } }; - // ----- std::vector ----------------------------------- + // ----- stdvec ----------------------------------- template<> struct Getter { static ostd::Vec2 exec_impl(const std::string& p, const json& root) @@ -213,7 +213,7 @@ namespace ostd const json& arr = root.at(p); if (!arr.is_array() || arr.size() != 2) return ostd::Vec2(); - return ostd::Vec2(arr[0].get(), arr[1].get()); + return ostd::Vec2(arr[0].get(), arr[1].get()); } catch (...) { @@ -221,12 +221,12 @@ namespace ostd } } }; - // ----- std::vector ----------------------------------- - template<> struct Getter> + // ----- stdvec ----------------------------------- + template<> struct Getter> { - static std::vector exec_impl(const std::string& p, const json& root) + static stdvec exec_impl(const std::string& p, const json& root) { - std::vector result; + stdvec result; try { const json& node = root.at(p); @@ -269,10 +269,10 @@ namespace ostd } }; - // ----- int ---------------------------------------------------------- - template<> struct Setter + // ----- i32 ---------------------------------------------------------- + template<> struct Setter { - static bool exec_impl(const std::string& p, json& root, int value) + static bool exec_impl(const std::string& p, json& root, i32 value) { try { @@ -283,10 +283,10 @@ namespace ostd } }; - // ----- double ------------------------------------------------------- - template<> struct Setter + // ----- f64 ------------------------------------------------------- + template<> struct Setter { - static bool exec_impl(const std::string& p, json& root, double value) + static bool exec_impl(const std::string& p, json& root, f64 value) { try { @@ -297,10 +297,10 @@ namespace ostd } }; - // ----- ostd::String ------------------------------------------------- - template<> struct Setter + // ----- String ------------------------------------------------- + template<> struct Setter { - static bool exec_impl(const std::string& p, json& root, const ostd::String& value) + static bool exec_impl(const std::string& p, json& root, const String& value) { try { @@ -318,16 +318,16 @@ namespace ostd try { json arr = json::array(); - arr.push_back(static_cast(value.r)); - arr.push_back(static_cast(value.g)); - arr.push_back(static_cast(value.b)); - if (value.a != 255) arr.push_back(static_cast(value.a)); + arr.push_back(cast(value.r)); + arr.push_back(cast(value.g)); + arr.push_back(cast(value.b)); + if (value.a != 255) arr.push_back(cast(value.a)); root[p] = arr; return true; } catch (...) { return false; } } }; - // ----- std::vector ----------------------------------- + // ----- stdvec ----------------------------------- template<> struct Setter { static bool exec_impl(const std::string& p, json& root, const ostd::Vec2& value) @@ -367,38 +367,38 @@ namespace ostd } } }; - // ----- std::vector ---------------------------------------- - template<> struct Setter> + // ----- stdvec ---------------------------------------- + template<> struct Setter> { - static bool exec_impl(const std::string& p, json& root, const std::vector& value) + static bool exec_impl(const std::string& p, json& root, const stdvec& value) { try { json arr = json::array(); - for (int32_t v : value) arr.push_back(v); + for (i32 v : value) arr.push_back(v); root[p] = arr; return true; } catch (...) { return false; } } }; - // ----- std::vector ----------------------------------------- - template<> struct Setter> + // ----- stdvec ----------------------------------------- + template<> struct Setter> { - static bool exec_impl(const std::string& p, json& root, const std::vector& value) + static bool exec_impl(const std::string& p, json& root, const stdvec& value) { try { json arr = json::array(); - for (double v : value) arr.push_back(v); + for (f64 v : value) arr.push_back(v); root[p] = arr; return true; } catch (...) { return false; } } }; - // ----- std::vector ----------------------------------- - template<> struct Setter> + // ----- stdvec ----------------------------------- + template<> struct Setter> { - static bool exec_impl(const std::string& p, json& root, const std::vector& value) + static bool exec_impl(const std::string& p, json& root, const stdvec& value) { try { @@ -409,10 +409,10 @@ namespace ostd } catch (...) { return false; } } }; - // ----- std::vector ----------------------------------- - template<> struct Setter> + // ----- stdvec ----------------------------------- + template<> struct Setter> { - static bool exec_impl(const std::string& p, json& root, const std::vector& value) + static bool exec_impl(const std::string& p, json& root, const stdvec& value) { try { @@ -428,10 +428,10 @@ namespace ostd } } }; - // ----- std::vector ----------------------------------- - template<> struct Setter> + // ----- stdvec ----------------------------------- + template<> struct Setter> { - static bool exec_impl(const std::string& p, json& root, const std::vector& value) + static bool exec_impl(const std::string& p, json& root, const stdvec& value) { try { @@ -457,7 +457,7 @@ namespace ostd } - static inline bool __navigate_json_path(const ostd::String& path, json*& outSource, ostd::String& outName) + static inline bool __navigate_json_path(const String& path, json*& outSource, String& outName) { auto tokens = path.tokenize("."); if (tokens.count() <= 1) @@ -468,7 +468,7 @@ namespace ostd return true; } - ostd::String key = ""; + String key = ""; while (tokens.hasNext()) { key = tokens.next(); @@ -490,10 +490,10 @@ namespace ostd } template - T JsonFile::get(const ostd::String& name) + T JsonFile::get(const String& name) { json* source = &m_json; - ostd::String settingName = ""; + String settingName = ""; if (__navigate_json_path(name, source, settingName)) return detail::Getter::exec_impl(settingName, *source); else @@ -501,7 +501,7 @@ namespace ostd return detail::Getter::exec_impl(settingName, *source); } template - bool JsonFile::set(const ostd::String& name, T value) + bool JsonFile::set(const String& name, T value) { if (!m_loaded) return false; if (!m_writeable) return false; @@ -510,7 +510,7 @@ namespace ostd if (tokens.count() == 0) return false; json* current = &m_json; - ostd::String key; + String key; while (tokens.hasNext()) { @@ -530,34 +530,34 @@ namespace ostd return false; } - bool JsonFile::get_bool(const ostd::String& name) { return get(name); } - int JsonFile::get_int(const ostd::String& name) { return get(name); } - double JsonFile::get_double(const ostd::String& name) { return get(name); } - ostd::String JsonFile::get_string(const ostd::String& name) { return get(name); } - ostd::Color JsonFile::get_color(const ostd::String& name) { return get(name); } - ostd::Vec2 JsonFile::get_vec2(const ostd::String& name) { return get(name); } - ostd::Rectangle JsonFile::get_rect(const ostd::String& name) { return get(name); } - std::vector JsonFile::get_int_array(const ostd::String& name) { return get>(name); } - std::vector JsonFile::get_double_array(const ostd::String& name) { return get>(name); } - std::vector JsonFile::get_string_array(const ostd::String& name) { return get>(name); } - std::vector JsonFile::get_color_array(const ostd::String& name) { return get>(name); } - std::vector JsonFile::get_rect_array(const ostd::String& name) { return get>(name); } + bool JsonFile::get_bool(const String& name) { return get(name); } + i32 JsonFile::get_int(const String& name) { return get(name); } + f64 JsonFile::get_double(const String& name) { return get(name); } + String JsonFile::get_string(const String& name) { return get(name); } + ostd::Color JsonFile::get_color(const String& name) { return get(name); } + ostd::Vec2 JsonFile::get_vec2(const String& name) { return get(name); } + ostd::Rectangle JsonFile::get_rect(const String& name) { return get(name); } + stdvec JsonFile::get_int_array(const String& name) { return get>(name); } + stdvec JsonFile::get_double_array(const String& name) { return get>(name); } + stdvec JsonFile::get_string_array(const String& name) { return get>(name); } + stdvec JsonFile::get_color_array(const String& name) { return get>(name); } + stdvec JsonFile::get_rect_array(const String& name) { return get>(name); } - bool JsonFile::set_bool(const ostd::String& name, bool value) { return set(name, value); } - bool JsonFile::set_int(const ostd::String& name, int32_t value) { return set(name, value); } - bool JsonFile::set_double(const ostd::String& name, double value) { return set(name, value); } - bool JsonFile::set_string(const ostd::String& name, const ostd::String& value) { return set(name, value); } - bool JsonFile::set_color(const ostd::String& name, const ostd::Color& value) { return set(name, value); } - bool JsonFile::set_vec2(const ostd::String& name, const ostd::Vec2& value) { return set(name, value); } - bool JsonFile::set_rect(const ostd::String& name, const ostd::Rectangle& value) { return set(name, value); } - bool JsonFile::set_int_array(const ostd::String& name, const std::vector& value) { return set>(name, value); } - bool JsonFile::set_double_array(const ostd::String& name, const std::vector& value) { return set>(name, value); } - bool JsonFile::set_string_array(const ostd::String& name, const std::vector& value) { return set>(name, value); } - bool JsonFile::set_color_array(const ostd::String& name, const std::vector& value) { return set>(name, value); } - bool JsonFile::set_rect_array(const ostd::String& name, const std::vector& value) { return set>(name, value); } + bool JsonFile::set_bool(const String& name, bool value) { return set(name, value); } + bool JsonFile::set_int(const String& name, i32 value) { return set(name, value); } + bool JsonFile::set_double(const String& name, f64 value) { return set(name, value); } + bool JsonFile::set_string(const String& name, const String& value) { return set(name, value); } + bool JsonFile::set_color(const String& name, const ostd::Color& value) { return set(name, value); } + bool JsonFile::set_vec2(const String& name, const ostd::Vec2& value) { return set(name, value); } + bool JsonFile::set_rect(const String& name, const ostd::Rectangle& value) { return set(name, value); } + bool JsonFile::set_int_array(const String& name, const stdvec& value) { return set>(name, value); } + bool JsonFile::set_double_array(const String& name, const stdvec& value) { return set>(name, value); } + bool JsonFile::set_string_array(const String& name, const stdvec& value) { return set>(name, value); } + bool JsonFile::set_color_array(const String& name, const stdvec& value) { return set>(name, value); } + bool JsonFile::set_rect_array(const String& name, const stdvec& value) { return set>(name, value); } - bool JsonFile::init(const ostd::String& filePath, bool writeable, const json* obj) + bool JsonFile::init(const String& filePath, bool writeable, const json* obj) { m_filePath = filePath; m_rawJson = ""; diff --git a/src/ostd/io/Json.hpp b/src/ostd/io/Json.hpp index 1bf2fea..59dae30 100644 --- a/src/ostd/io/Json.hpp +++ b/src/ostd/io/Json.hpp @@ -33,52 +33,52 @@ namespace ostd { public: inline JsonFile(void) { m_loaded = false; } - inline JsonFile(const ostd::String& filePath) { init(filePath); } - bool init(const ostd::String& filePath, bool writeable = true, const json* obj = nullptr); + inline JsonFile(const String& filePath) { init(filePath); } + bool init(const String& filePath, bool writeable = true, const json* obj = nullptr); inline bool isLoaded(void) const { return m_loaded; } - template T get(const ostd::String& name); - template bool set(const ostd::String& name, T value); + template T get(const String& name); + template bool set(const String& name, T value); // --- GETTERS --- - bool get_bool(const ostd::String& name); - int32_t get_int(const ostd::String& name); - double get_double(const ostd::String& name); - ostd::String get_string(const ostd::String& name); - ostd::Color get_color(const ostd::String& name); - ostd::Vec2 get_vec2(const ostd::String& name); - ostd::Rectangle get_rect(const ostd::String& name); - std::vector get_int_array(const ostd::String& name); - std::vector get_double_array(const ostd::String& name); - std::vector get_string_array(const ostd::String& name); - std::vector get_color_array(const ostd::String& name); - std::vector get_rect_array(const ostd::String& name); + bool get_bool(const String& name); + i32 get_int(const String& name); + f64 get_double(const String& name); + String get_string(const String& name); + ostd::Color get_color(const String& name); + ostd::Vec2 get_vec2(const String& name); + ostd::Rectangle get_rect(const String& name); + stdvec get_int_array(const String& name); + stdvec get_double_array(const String& name); + stdvec get_string_array(const String& name); + stdvec get_color_array(const String& name); + stdvec get_rect_array(const String& name); // --- SETTERS --- - bool set_bool(const ostd::String& name, bool value); - bool set_int(const ostd::String& name, int32_t value); - bool set_double(const ostd::String& name, double value); - bool set_string(const ostd::String& name, const ostd::String& value); - bool set_color(const ostd::String& name, const ostd::Color& value); - bool set_vec2(const ostd::String& name, const ostd::Vec2& value); - bool set_rect(const ostd::String& name, const ostd::Rectangle& value); - bool set_int_array(const ostd::String& name, const std::vector& value); - bool set_double_array(const ostd::String& name, const std::vector& value); - bool set_string_array(const ostd::String& name, const std::vector& value); - bool set_color_array(const ostd::String& name, const std::vector& value); - bool set_rect_array(const ostd::String& name, const std::vector& value); + bool set_bool(const String& name, bool value); + bool set_int(const String& name, i32 value); + bool set_double(const String& name, f64 value); + bool set_string(const String& name, const String& value); + bool set_color(const String& name, const ostd::Color& value); + bool set_vec2(const String& name, const ostd::Vec2& value); + bool set_rect(const String& name, const ostd::Rectangle& value); + bool set_int_array(const String& name, const stdvec& value); + bool set_double_array(const String& name, const stdvec& value); + bool set_string_array(const String& name, const stdvec& value); + bool set_color_array(const String& name, const stdvec& value); + bool set_rect_array(const String& name, const stdvec& value); // --- WRAPPERS --- - inline float get_float(const ostd::String& name) { return static_cast(get_double(name)); } + inline f32 get_float(const String& name) { return cast(get_double(name)); } private: void __validate_settings(void); bool __write_to_file(const json* obj = nullptr); private: - ostd::String m_rawJson { "" }; - ostd::String m_filePath { "" }; + String m_rawJson { "" }; + String m_filePath { "" }; json m_json; bool m_loaded { false }; bool m_writeable { true }; diff --git a/src/ostd/io/Keyboard.cpp b/src/ostd/io/Keyboard.cpp index 5940820..fa871ff 100644 --- a/src/ostd/io/Keyboard.cpp +++ b/src/ostd/io/Keyboard.cpp @@ -32,10 +32,10 @@ namespace ostd } #ifndef WINDOWS_OS - int KeyboardController::kbhit(void) + i32 KeyboardController::kbhit(void) { - unsigned char ch; - int nread; + uchar ch; + i32 nread; if (peek_character != -1) return 1; new_settings.c_cc[VMIN] = 0; tcsetattr(0, TCSANOW, &new_settings); @@ -51,7 +51,7 @@ namespace ostd return 0; } - int KeyboardController::getch(void) + i32 KeyboardController::getch(void) { char ch; @@ -110,7 +110,7 @@ namespace ostd eKeys KeyboardController::getPressedKey(void) { - int k1 = 0, k2 = 0, k3 = 0; + i32 k1 = 0, k2 = 0, k3 = 0; eKeys key; if(kbhit()) { diff --git a/src/ostd/io/Logger.cpp b/src/ostd/io/Logger.cpp index eaa9cf5..925a3a2 100755 --- a/src/ostd/io/Logger.cpp +++ b/src/ostd/io/Logger.cpp @@ -7,7 +7,7 @@ namespace ostd { OutputHandlerBase* Logger::m_out = new ConsoleOutputHandler; - void Logger::__log_output(uint8_t log_level, String message, ...) + void Logger::__log_output(u8 log_level, String message, ...) { String level_str[6] = { "[ FATAL ]: ", "[ ERROR ]: ", "[ WARNING ]: ", "[ INFO ]: ", "[ DEBUG ]: ", "[ TRACE ]: " }; diff --git a/src/ostd/io/Logger.hpp b/src/ostd/io/Logger.hpp index 239b5e9..c085213 100755 --- a/src/ostd/io/Logger.hpp +++ b/src/ostd/io/Logger.hpp @@ -26,19 +26,19 @@ namespace ostd { struct tLogLevel { - inline static const uint8_t Fatal = 0; - inline static const uint8_t Error = 1; - inline static const uint8_t Warning = 2; - inline static const uint8_t Info = 3; - inline static const uint8_t Debug = 4; - inline static const uint8_t Trace = 5; + inline static const u8 Fatal = 0; + inline static const u8 Error = 1; + inline static const u8 Warning = 2; + inline static const u8 Info = 3; + inline static const u8 Debug = 4; + inline static const u8 Trace = 5; }; class OutputHandlerBase; class Logger { public: - static void __log_output(uint8_t log_level, String message, ...); + static void __log_output(u8 log_level, String message, ...); static void setOutputHandler(OutputHandlerBase& __destination); static void destroy(void); static inline OutputHandlerBase& getOutputHandler(void) { return *m_out; } diff --git a/src/ostd/io/Memory.cpp b/src/ostd/io/Memory.cpp index c11af87..40a81c0 100644 --- a/src/ostd/io/Memory.cpp +++ b/src/ostd/io/Memory.cpp @@ -23,7 +23,7 @@ namespace ostd { - void Memory::printByteStream(const ByteStream& data, StreamIndex start, uint8_t line_len, uint16_t n_rows, OutputHandlerBase& out, int32_t addrHighlight, uint32_t highlightRange, const String& title) + void Memory::printByteStream(const ByteStream& data, StreamIndex start, u8 line_len, u16 n_rows, OutputHandlerBase& out, i32 addrHighlight, u32 highlightRange, const String& title) { StreamIndex end = start + (n_rows * line_len); if (end > data.size()) end = data.size(); @@ -32,21 +32,21 @@ namespace ostd titleEdit = titleEdit.substr(0, 12); else if (titleEdit.len() < 12) { - int32_t diff = 12 - titleEdit.len(); - for (int32_t i = 0; i < diff; i++) + i32 diff = 12 - titleEdit.len(); + for (i32 i = 0; i < diff; i++) titleEdit.addChar(' '); } bool highlight = addrHighlight >= 0; - uint8_t i = 1; + u8 i = 1; ByteStream tmp; - uint16_t linew = 1 + 1 + 6 + 1 + 1 + 2 + ((2 + 2) * line_len) + 1 + 4; + u16 linew = 1 + 1 + 6 + 1 + 1 + 2 + ((2 + 2) * line_len) + 1 + 4; out.fg(ConsoleColors::BrightBlue).p(String::duplicateChar('=', linew)).nl(); if (line_len <= 0xFF) { out.fg(ConsoleColors::BrightBlue).p("|"); out.fg(ConsoleColors::BrightMagenta).p(titleEdit); out.fg(ConsoleColors::BrightBlue).p("| "); - for (int32_t i = 0; i < line_len; i++) + for (i32 i = 0; i < line_len; i++) out.fg(ConsoleColors::Green).p(String::getHexStr(i, false, 1)).p(" "); out.fg(ConsoleColors::BrightBlue).p("|").nl(); out.fg(ConsoleColors::BrightBlue).p(String::duplicateChar('=', linew)).nl(); @@ -57,7 +57,7 @@ namespace ostd for (StreamIndex addr = start; addr < end; addr++) { tmp.push_back(data[addr]); - if (highlight && (addr >= (uint32_t)addrHighlight && addr < (uint32_t)(addrHighlight + highlightRange))) + if (highlight && (addr >= (u32)addrHighlight && addr < (u32)(addrHighlight + highlightRange))) out.fg(ConsoleColors::Red); else if (data[addr] == 0) out.fg(ConsoleColors::BrightGray); @@ -102,7 +102,7 @@ namespace ostd { std::ifstream rf(filePath.cpp_str(), std::ios::out | std::ios::binary); if(!rf) return false; //TODO: Error - uint8_t cell = 0; + u8 cell = 0; while(rf.read((char*)&cell, sizeof(cell))) outStream.push_back(cell); if (outStream.size() == 0) return false; //TODO: Error @@ -113,14 +113,14 @@ namespace ostd { ByteStream bstream; for (auto& c : data) - bstream.push_back((int8_t)c); + bstream.push_back((i8)c); return bstream; } String Memory::byteStreamToString(const ByteStream& data) { String out_string = ""; - for (int64_t i = 0; i < data.size(); i++) + for (i64 i = 0; i < data.size(); i++) { if (data[i] == 0) break; out_string.addChar((char)data[i]); diff --git a/src/ostd/io/Memory.hpp b/src/ostd/io/Memory.hpp index 71d09a5..0393372 100644 --- a/src/ostd/io/Memory.hpp +++ b/src/ostd/io/Memory.hpp @@ -32,7 +32,7 @@ namespace ostd class Memory { public: - static void printByteStream(const ByteStream& data, StreamIndex start, uint8_t line_len, uint16_t n_rows, OutputHandlerBase& out, int32_t addrHighlight = -1, uint32_t highlightRange = 1, const String& title = ""); + static void printByteStream(const ByteStream& data, StreamIndex start, u8 line_len, u16 n_rows, OutputHandlerBase& out, i32 addrHighlight = -1, u32 highlightRange = 1, const String& title = ""); static bool saveByteStreamToFile(const ByteStream& stream, const String& filePath); static bool loadByteStreamFromFile(const String& filePath, ByteStream& outStream); static ByteStream stringToByteStream(const String& data); diff --git a/src/ostd/io/Midi.cpp b/src/ostd/io/Midi.cpp index 036f1ce..b3b8c69 100644 --- a/src/ostd/io/Midi.cpp +++ b/src/ostd/io/Midi.cpp @@ -1,5 +1,5 @@ #include "Midi.hpp" -#include + #include #include #include @@ -8,7 +8,7 @@ namespace ostd { //TODO: Errors - std::vector MidiParser::parseFile(const ostd::String& filePath) + stdvec MidiParser::parseFile(const String& filePath) { smf::MidiFile midi; @@ -23,10 +23,10 @@ namespace ostd midi.doTimeAnalysis(); midi.linkNotePairs(); - std::vector notes; + stdvec notes; notes.reserve(256); - for (int e = 0; e < midi[0].size(); ++e) + for (i32 e = 0; e < midi[0].size(); ++e) { auto& ev = midi[0][e]; if (ev.isNoteOn()) @@ -46,7 +46,7 @@ namespace ostd } NoteEvent* notePtr = nullptr; - double noteTime = 0.0; + f64 noteTime = 0.0; for (auto& note : notes) { if (note.endTime > noteTime) @@ -74,7 +74,7 @@ namespace ostd return notes; } - MidiParser::NoteInfo MidiParser::getNoteInfo(int midiPitch) + MidiParser::NoteInfo MidiParser::getNoteInfo(i32 midiPitch) { static const std::array noteNames = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; diff --git a/src/ostd/io/Midi.hpp b/src/ostd/io/Midi.hpp index 9ab5028..648a92b 100644 --- a/src/ostd/io/Midi.hpp +++ b/src/ostd/io/Midi.hpp @@ -29,12 +29,12 @@ namespace ostd public: class NoteEvent { public: - int32_t pitch { 0 }; // MIDI note number (0-127) - double startTime { 0.0 }; // Start time in seconds - double endTime { 0.0 }; // Start time in seconds - double duration { 0.0 }; // Duration in seconds - int32_t velocity { 0 }; // Attack velocity (1-127) - int32_t channel { 0 }; // MIDI channel (0-15) + i32 pitch { 0 }; // MIDI note number (0-127) + f64 startTime { 0.0 }; // Start time in seconds + f64 endTime { 0.0 }; // Start time in seconds + f64 duration { 0.0 }; // Duration in seconds + i32 velocity { 0 }; // Attack velocity (1-127) + i32 channel { 0 }; // MIDI channel (0-15) bool hit { false }; bool rightHand { false }; @@ -48,9 +48,9 @@ namespace ostd return pitch < other.pitch; return startTime < other.startTime; } - inline ostd::String toString(void) const + inline String toString(void) const { - ostd::String str = "Pitch: "; + String str = "Pitch: "; str.add(pitch); str.add("\nstartTime: ").add(startTime); str.add("\nendTime: ").add(endTime); @@ -64,10 +64,10 @@ namespace ostd public: class NoteInfo { public: - ostd::String name { "" }; // e.g., "A", "C#", "F" - int octave { 0 }; // e.g., 4 for C4 - int noteInOctave { 0 }; // 0-11 - int keyIndex { 0 }; // 0-based index for 88-key piano (A0=0), -1 if out of range + String name { "" }; // e.g., "A", "C#", "F" + i32 octave { 0 }; // e.g., 4 for C4 + i32 noteInOctave { 0 }; // 0-11 + i32 keyIndex { 0 }; // 0-based index for 88-key piano (A0=0), -1 if out of range public: inline bool isWhiteKey(void) const @@ -77,9 +77,9 @@ namespace ostd noteInOctave == 11; } inline bool isBlackKey(void) const { return !isWhiteKey(); } - inline ostd::String toString(void) const + inline String toString(void) const { - ostd::String str = "NOTE INFO: "; + String str = "NOTE INFO: "; str.add(name).add(octave); str.add(" - noteInOctave: ").add(noteInOctave); str.add(" - keyIndex: ").add(keyIndex); @@ -87,19 +87,19 @@ namespace ostd return str; } - static inline bool isWhiteKey(int32_t noteInOctave) + static inline bool isWhiteKey(i32 noteInOctave) { return noteInOctave == 0 || noteInOctave == 2 || noteInOctave == 4 || noteInOctave == 5 || noteInOctave == 7 || noteInOctave == 9 || noteInOctave == 11; } - static inline bool isBlackKey(int32_t noteInOctave) { return !NoteInfo::isWhiteKey(noteInOctave); } + static inline bool isBlackKey(i32 noteInOctave) { return !NoteInfo::isWhiteKey(noteInOctave); } }; public: // Parses a single-track MIDI file and returns a vector of NoteEvents - static std::vector parseFile(const ostd::String& filePath); + static stdvec parseFile(const String& filePath); // Convert MIDI pitch to NoteInfo - static NoteInfo getNoteInfo(int midiPitch); + static NoteInfo getNoteInfo(i32 midiPitch); }; } diff --git a/src/ostd/io/OutputHandlers.cpp b/src/ostd/io/OutputHandlers.cpp index 9495963..13485ff 100755 --- a/src/ostd/io/OutputHandlers.cpp +++ b/src/ostd/io/OutputHandlers.cpp @@ -55,7 +55,7 @@ namespace ostd OutputHandlerBase& ConsoleOutputHandler::bg(const Color& color) { - std::cout << "\033[48;2;" << (int)color.r << ";" << (int)color.g << ";" << (int)color.b << "m"; + std::cout << "\033[48;2;" << (i32)color.r << ";" << (i32)color.g << ";" << (i32)color.b << "m"; return *this; } @@ -73,7 +73,7 @@ namespace ostd OutputHandlerBase& ConsoleOutputHandler::fg(const Color& color) { - std::cout << "\033[38;2;" << (int)color.r << ";" << (int)color.g << ";" << (int)color.b << "m"; + std::cout << "\033[38;2;" << (i32)color.r << ";" << (i32)color.g << ";" << (i32)color.b << "m"; return *this; } @@ -124,55 +124,55 @@ namespace ostd return *this; } - OutputHandlerBase& ConsoleOutputHandler::p(uint8_t i) + OutputHandlerBase& ConsoleOutputHandler::p(u8 i) { - std::cout << (uint8_t)i; + std::cout << (u8)i; return *this; } - OutputHandlerBase& ConsoleOutputHandler::p(int8_t i) + OutputHandlerBase& ConsoleOutputHandler::p(i8 i) { - std::cout << (int8_t)i; + std::cout << (i8)i; return *this; } - OutputHandlerBase& ConsoleOutputHandler::p(uint16_t i) + OutputHandlerBase& ConsoleOutputHandler::p(u16 i) { - std::cout << (uint16_t)i; + std::cout << (u16)i; return *this; } - OutputHandlerBase& ConsoleOutputHandler::p(int16_t i) + OutputHandlerBase& ConsoleOutputHandler::p(i16 i) { - std::cout << (int16_t)i; + std::cout << (i16)i; return *this; } - OutputHandlerBase& ConsoleOutputHandler::p(uint32_t i) + OutputHandlerBase& ConsoleOutputHandler::p(u32 i) { - std::cout << (uint32_t)i; + std::cout << (u32)i; return *this; } - OutputHandlerBase& ConsoleOutputHandler::p(int32_t i) + OutputHandlerBase& ConsoleOutputHandler::p(i32 i) { - std::cout << (int32_t)i; + std::cout << (i32)i; return *this; } - OutputHandlerBase& ConsoleOutputHandler::p(uint64_t i) + OutputHandlerBase& ConsoleOutputHandler::p(u64 i) { - std::cout << (uint64_t)i; + std::cout << (u64)i; return *this; } - OutputHandlerBase& ConsoleOutputHandler::p(int64_t i) + OutputHandlerBase& ConsoleOutputHandler::p(i64 i) { - std::cout << (int64_t)i; + std::cout << (i64)i; return *this; } - OutputHandlerBase& ConsoleOutputHandler::p(float f, uint8_t precision) + OutputHandlerBase& ConsoleOutputHandler::p(f32 f, u8 precision) { if (precision == 0) { @@ -187,7 +187,7 @@ namespace ostd return *this; } - OutputHandlerBase& ConsoleOutputHandler::p(double f, uint8_t precision) + OutputHandlerBase& ConsoleOutputHandler::p(f64 f, u8 precision) { if (precision == 0) { @@ -232,21 +232,21 @@ namespace ostd return *this; } - OutputHandlerBase& ConsoleOutputHandler::xy(int32_t x, int32_t y) + OutputHandlerBase& ConsoleOutputHandler::xy(i32 x, i32 y) { BasicConsole::setConsoleCursorPosition(x, y); return *this; } - OutputHandlerBase& ConsoleOutputHandler::x(int32_t x) + OutputHandlerBase& ConsoleOutputHandler::x(i32 x) { - int32_t y = getCursorPosition().y; + i32 y = getCursorPosition().y; return xy(x, y); } - OutputHandlerBase& ConsoleOutputHandler::y(int32_t y) + OutputHandlerBase& ConsoleOutputHandler::y(i32 y) { - int32_t x = getCursorPosition().x; + i32 x = getCursorPosition().x; return xy(x, y); } @@ -255,26 +255,26 @@ namespace ostd return BasicConsole::getConsoleCursorPosition(); } - void ConsoleOutputHandler::getCursorPosition(int32_t& outX, int32_t& outY) + void ConsoleOutputHandler::getCursorPosition(i32& outX, i32& outY) { auto pos = BasicConsole::getConsoleCursorPosition();; outX = pos.x; outY = pos.y; } - int32_t ConsoleOutputHandler::getCursorX(void) + i32 ConsoleOutputHandler::getCursorX(void) { auto pos = BasicConsole::getConsoleCursorPosition();; return pos.x; } - int32_t ConsoleOutputHandler::getCursorY(void) + i32 ConsoleOutputHandler::getCursorY(void) { auto pos = BasicConsole::getConsoleCursorPosition();; return pos.y; } - void ConsoleOutputHandler::getConsoleSize(int32_t& outColumns, int32_t& outRows) + void ConsoleOutputHandler::getConsoleSize(i32& outColumns, i32& outRows) { BasicConsole::getConsoleSize(outColumns, outRows); } diff --git a/src/ostd/io/Serial.cpp b/src/ostd/io/Serial.cpp index 6b2a739..bdf7b6b 100755 --- a/src/ostd/io/Serial.cpp +++ b/src/ostd/io/Serial.cpp @@ -5,10 +5,10 @@ namespace ostd { namespace serial { - bool SerialIO::init(uint64_t size, uint8_t endianness) + bool SerialIO::init(u64 size, u8 endianness) { if (size < 1) return false; - for (uint64_t i = 0; i < size; i++) + for (u64 i = 0; i < size; i++) m_data.push_back(0); m_endianness = endianness; return true; @@ -110,7 +110,7 @@ namespace ostd return true; } - bool SerialIO::r_Float(StreamIndex addr, float& outVal) + bool SerialIO::r_Float(StreamIndex addr, f32& outVal) { if (!is_validAddr(addr, tTypeSize::FLOAT)) return false; __float_parser fp; @@ -133,7 +133,7 @@ namespace ostd return true; } - bool SerialIO::r_Double(StreamIndex addr, double& outVal) + bool SerialIO::r_Double(StreamIndex addr, f64& outVal) { if (!is_validAddr(addr, tTypeSize::DOUBLE)) return false; __double_parser dp; @@ -167,7 +167,7 @@ namespace ostd bool SerialIO::r_ByteStream(StreamIndex addr, ByteStream& outStream) { if (!is_validAddr(addr, tTypeSize::ADDR)) return false; - uint32_t stream_size; + u32 stream_size; if (!r_Addr(addr, stream_size)) return false; addr += tTypeSize::ADDR; if (!is_validAddr(addr, stream_size)) return false; @@ -178,7 +178,7 @@ namespace ostd return true; } - bool SerialIO::r_ByteStream(StreamIndex addr, ByteStream& outStream, uint32_t size) + bool SerialIO::r_ByteStream(StreamIndex addr, ByteStream& outStream, u32 size) { if (!is_validAddr(addr, size)) return false; outStream.clear(); @@ -191,7 +191,7 @@ namespace ostd bool SerialIO::r_String(StreamIndex addr, String& outString) { if (!is_validAddr(addr, tTypeSize::ADDR)) return false; - uint32_t stream_size; + u32 stream_size; if (!r_Addr(addr, stream_size)) return false; addr += tTypeSize::ADDR; if (!is_validAddr(addr, stream_size)) return false; @@ -201,7 +201,7 @@ namespace ostd return true; } - bool SerialIO::r_String(StreamIndex addr, String& outString, uint32_t size) + bool SerialIO::r_String(StreamIndex addr, String& outString, u32 size) { if (!is_validAddr(addr, size)) return false; outString = ""; @@ -213,7 +213,7 @@ namespace ostd bool SerialIO::r_NullTerminatedString(StreamIndex addr, String& outString) { outString = ""; - int8_t c = 0; + i8 c = 0; if (!r_Byte(addr, c)) return false; addr += tTypeSize::BYTE; while (c != 0) @@ -326,7 +326,7 @@ namespace ostd return true; } - bool SerialIO::w_Float(StreamIndex addr, float val) + bool SerialIO::w_Float(StreamIndex addr, f32 val) { m_statuWriting = true; if (!is_validAddr(addr, tTypeSize::FLOAT)) return false; @@ -350,7 +350,7 @@ namespace ostd return true; } - bool SerialIO::w_Double(StreamIndex addr, double val) + bool SerialIO::w_Double(StreamIndex addr, f64 val) { m_statuWriting = true; if (!is_validAddr(addr, tTypeSize::DOUBLE)) return false; @@ -385,7 +385,7 @@ namespace ostd bool SerialIO::w_ByteStream(StreamIndex addr, const ByteStream& stream, bool store_size) { m_statuWriting = true; - uint32_t stream_size = stream.size(); + u32 stream_size = stream.size(); if (store_size) { if (!is_validAddr(addr, tTypeSize::ADDR + stream_size)) return false; @@ -402,7 +402,7 @@ namespace ostd { m_statuWriting = true; auto stream = Memory::stringToByteStream(str); - uint32_t stream_size = stream.size(); + u32 stream_size = stream.size(); if (store_size && !null_terminate) { if (!is_validAddr(addr, tTypeSize::ADDR + stream_size)) return false; @@ -425,7 +425,7 @@ namespace ostd { if (isAutoResizeEnabled() && m_statuWriting) { - for (uint32_t i = 0; i <= m_resizeAmount; i++) + for (u32 i = 0; i <= m_resizeAmount; i++) m_data.push_back(0); m_statuWriting = false; return true; @@ -442,8 +442,8 @@ namespace ostd void SerialIO::print(StreamIndex start, OutputHandlerBase& out) { - uint32_t line_len = 32; - uint64_t power = 1; + u32 line_len = 32; + u64 power = 1; while(power < size()) power *= 2; Memory::printByteStream(m_data, start, line_len, power / line_len, out); diff --git a/src/ostd/io/Serial.hpp b/src/ostd/io/Serial.hpp index 57aebb2..6af5c1e 100755 --- a/src/ostd/io/Serial.hpp +++ b/src/ostd/io/Serial.hpp @@ -33,26 +33,26 @@ namespace ostd class SerialIO { public: struct tEndianness { - inline static constexpr uint8_t LittleEndian = 0x00; - inline static constexpr uint8_t BigEndian = 0x01; + inline static constexpr u8 LittleEndian = 0x00; + inline static constexpr u8 BigEndian = 0x01; }; public: inline SerialIO(void) { init(); } - inline SerialIO(uint64_t size, uint8_t endianness = tEndianness::BigEndian) { init(size, endianness); } - inline SerialIO(ByteStream& data, uint8_t endianness = tEndianness::BigEndian) { m_data = data; m_endianness = endianness; } - bool init(uint64_t size = SerialIO::DefaultMaxSize, uint8_t endianness = tEndianness::BigEndian); + inline SerialIO(u64 size, u8 endianness = tEndianness::BigEndian) { init(size, endianness); } + inline SerialIO(ByteStream& data, u8 endianness = tEndianness::BigEndian) { m_data = data; m_endianness = endianness; } + bool init(u64 size = SerialIO::DefaultMaxSize, u8 endianness = tEndianness::BigEndian); bool r_QWord(StreamIndex addr, QWord& outVal); bool r_DWord(StreamIndex addr, DWord& outVal); bool r_Word(StreamIndex addr, Word& outVal); bool r_Byte(StreamIndex addr, Byte& outVal); bool r_Addr(StreamIndex addr, StreamIndex& outVal); - bool r_Float(StreamIndex addr, float& outVal); - bool r_Double(StreamIndex addr, double& outVal); + bool r_Float(StreamIndex addr, f32& outVal); + bool r_Double(StreamIndex addr, f64& outVal); bool r_ByteStream(StreamIndex addr, ByteStream& outStream); - bool r_ByteStream(StreamIndex addr, ByteStream& outStream, uint32_t size); + bool r_ByteStream(StreamIndex addr, ByteStream& outStream, u32 size); bool r_String(StreamIndex addr, String& outString); - bool r_String(StreamIndex addr, String& outString, uint32_t size); + bool r_String(StreamIndex addr, String& outString, u32 size); bool r_NullTerminatedString(StreamIndex addr, String& outString); bool w_QWord(StreamIndex addr, QWord val); @@ -60,33 +60,33 @@ namespace ostd bool w_Word(StreamIndex addr, Word val); bool w_Byte(StreamIndex addr, Byte val); bool w_Addr(StreamIndex addr, StreamIndex val); - bool w_Float(StreamIndex addr, float val); - bool w_Double(StreamIndex addr, double val); + bool w_Float(StreamIndex addr, f32 val); + bool w_Double(StreamIndex addr, f64 val); bool w_ByteStream(StreamIndex addr, const ByteStream& stream, bool store_size = true); bool w_String(StreamIndex addr, const String& str, bool store_size = false, bool null_terminate = true); bool is_validAddr(StreamIndex addr, StreamIndex offset = 1); - inline uint64_t size(void) { return m_data.size(); } + inline u64 size(void) { return m_data.size(); } inline ByteStream& getData(void) { return m_data; } void print(StreamIndex start, OutputHandlerBase& out); bool saveToFile(const String& filePath); - inline uint8_t getEndianness(void) const { return m_endianness; } + inline u8 getEndianness(void) const { return m_endianness; } inline bool isLittleEndian(void) const { return m_endianness == tEndianness::LittleEndian; } inline bool isBigEndian(void) const { return m_endianness == tEndianness::BigEndian; } inline bool isAutoResizeEnabled(void) const { return m_autoResize; } - inline void enableAutoResize(bool val = true, int32_t resizeAmount = 1024) { m_autoResize = val; if (!val) return; m_resizeAmount = resizeAmount; } + inline void enableAutoResize(bool val = true, i32 resizeAmount = 1024) { m_autoResize = val; if (!val) return; m_resizeAmount = resizeAmount; } private: ByteStream m_data; - uint8_t m_endianness { tEndianness::BigEndian }; + u8 m_endianness { tEndianness::BigEndian }; bool m_autoResize { true }; - int32_t m_resizeAmount { 1024 }; + i32 m_resizeAmount { 1024 }; bool m_statuWriting { false }; public: - inline static constexpr uint64_t DefaultMaxSize = 512; + inline static constexpr u64 DefaultMaxSize = 512; }; } } diff --git a/src/ostd/io/Stylesheet.cpp b/src/ostd/io/Stylesheet.cpp index c65c5d8..92aceae 100644 --- a/src/ostd/io/Stylesheet.cpp +++ b/src/ostd/io/Stylesheet.cpp @@ -34,32 +34,32 @@ namespace ostd return *this; } - Stylesheet& Stylesheet::loadFromFile(const ostd::String& filePath, bool clearCurrentRules, VariableList variable) + Stylesheet& Stylesheet::loadFromFile(const String& filePath, bool clearCurrentRules, VariableList variable) { - ostd::String outContent = ""; + String outContent = ""; ostd::FileSystem::readTextFileRaw(filePath, outContent); return loadFromString(outContent, filePath, clearCurrentRules, variable); } - Stylesheet& Stylesheet::loadFromString(const ostd::String& content, const ostd::String& filePath, bool clearCurrentRules, VariableList variables) + Stylesheet& Stylesheet::loadFromString(const String& content, const String& filePath, bool clearCurrentRules, VariableList variables) { if (clearCurrentRules) m_values.clear(); - std::vector lines = content.tokenize("\n", false, true).getRawData(); - std::vector originalLines = lines; + stdvec lines = content.tokenize("\n", false, true).getRawData(); + stdvec originalLines = lines; auto richLines = getRichStringLines(lines); - uint32_t lineNumber = 0; - auto l_warn = [&](const ostd::String& msg) -> void { + u32 lineNumber = 0; + auto l_warn = [&](const String& msg) -> void { OX_WARN("%s in theme line. File: <%s:%d>", msg.c_str(), filePath.c_str(), lineNumber, originalLines[lineNumber - 1].c_str()); }; - auto l_parseLine = [&](ostd::String& line) -> void { + auto l_parseLine = [&](String& line) -> void { if (!parseThemeFileLine(line, variables)) l_warn("Error"); }; - uint8_t lineNumberMaxWidth = ostd::String("").add(static_cast(lines.size())).len(); - ostd::String groupSelector = ""; + u8 lineNumberMaxWidth = String("").add(cast(lines.size())).len(); + String groupSelector = ""; bool groupLines = true; - std::vector group; + stdvec group; bool debug_print = false; for (auto& line : lines) { @@ -85,8 +85,8 @@ namespace ostd l_warn("Invalid variable"); goto custom_continue; } - ostd::String varName = line.new_substr(0, line.indexOf("=")).trim(); - ostd::String varValue = line.new_substr(line.indexOf("=") + 1).trim(); + String varName = line.new_substr(0, line.indexOf("=")).trim(); + String varValue = line.new_substr(line.indexOf("=") + 1).trim(); if (!varName.regexMatches(m_validNameRegex)) { l_warn("Invalid variable name"); @@ -110,7 +110,7 @@ namespace ostd groupLines = false; auto newLines = parseGroup(groupSelector, group); lineNumber -= newLines.size(); - for (int32_t i = 0; i < newLines.size(); i++) + for (i32 i = 0; i < newLines.size(); i++) { auto& l = newLines[i]; l_parseLine(l); @@ -136,7 +136,7 @@ namespace ostd l_warn("Invalid group selector"); goto custom_continue; } - ostd::String rawSelector = line.new_substr(1, line.indexOf(")")).trim(); + String rawSelector = line.new_substr(1, line.indexOf(")")).trim(); groupSelector = parseGroupSelector(rawSelector); if (groupSelector == "") { @@ -159,38 +159,38 @@ namespace ostd continue; custom_continue: if (debug_print) - std::cout << ostd::String("").add(lineNumber).addLeftPadding(lineNumberMaxWidth, ' ') << "| " << richLines[lineNumber - 1] << "\n"; + std::cout << String("").add(lineNumber).addLeftPadding(lineNumberMaxWidth, ' ') << "| " << richLines[lineNumber - 1] << "\n"; } return *this; } - void Stylesheet::set(const std::string& key, TypeVariant value, const ostd::String& themeID) + void Stylesheet::set(const std::string& key, TypeVariant value, const String& themeID) { - ostd::String fullKey = "@" + themeID + "." + key; + String fullKey = "@" + themeID + "." + key; // std::cout << "SET: " << fullKey << "\n"; setFull(fullKey, value); } - void Stylesheet::removeRule(const ostd::String& fullKey) + void Stylesheet::removeRule(const String& fullKey) { m_values.erase(fullKey); } - void Stylesheet::setFull(const ostd::String& fullKey, TypeVariant value) + void Stylesheet::setFull(const String& fullKey, TypeVariant value) { m_values[fullKey] = std::move(value); } - const Stylesheet::TypeVariant* Stylesheet::getVariant(const ostd::String& key, const std::vector& themeIDList, const QualifierList& qualifierList) const + const Stylesheet::TypeVariant* Stylesheet::getVariant(const String& key, const stdvec& themeIDList, const QualifierList& qualifierList) const { - std::vector emptyThemeIDList { "" }; - const std::vector& __themeIDList = (themeIDList.size() == 0 ? emptyThemeIDList : themeIDList); + stdvec emptyThemeIDList { "" }; + const stdvec& __themeIDList = (themeIDList.size() == 0 ? emptyThemeIDList : themeIDList); for (const auto&[qualifier, state] : qualifierList) { const TypeVariant* v = nullptr; - for (int32_t i = __themeIDList.size() - 1; i >= 0; i--) + for (i32 i = __themeIDList.size() - 1; i >= 0; i--) { - const ostd::String& themeID = __themeIDList[i]; + const String& themeID = __themeIDList[i]; v = (state ? getFull("@" + themeID + ":" + qualifier + "." + key) : nullptr); if (v) return v; @@ -202,9 +202,9 @@ custom_continue: if (v) return v; } - for (int32_t i = __themeIDList.size() - 1; i >= 0; i--) + for (i32 i = __themeIDList.size() - 1; i >= 0; i--) { - const ostd::String& themeID = __themeIDList[i]; + const String& themeID = __themeIDList[i]; if (auto v = getFull("@" + themeID + "." + key)) return v; } @@ -213,7 +213,7 @@ custom_continue: return nullptr; } - const Stylesheet::TypeVariant* Stylesheet::getFull(const ostd::String& fullKey) const + const Stylesheet::TypeVariant* Stylesheet::getFull(const String& fullKey) const { auto it = m_values.find(fullKey); // if (it != m_values.end()) @@ -221,16 +221,16 @@ custom_continue: return it != m_values.end() ? &it->second : nullptr; } - bool Stylesheet::parseThemeFileLine(const ostd::String& line, const VariableList& variables, bool exitCondition) + bool Stylesheet::parseThemeFileLine(const String& line, const VariableList& variables, bool exitCondition) { if (!line.contains("=")) return false; - ostd::String key = line.new_substr(0, line.indexOf("=")).trim(); - ostd::String valuePreserveCase = line.new_substr(line.indexOf("=") + 1).trim(); - ostd::String value = line.new_substr(line.indexOf("=") + 1).trim().toLower(); + String key = line.new_substr(0, line.indexOf("=")).trim(); + String valuePreserveCase = line.new_substr(line.indexOf("=") + 1).trim(); + String value = line.new_substr(line.indexOf("=") + 1).trim().toLower(); if (key == "") return false; - ostd::String themeID = ""; + String themeID = ""; if (key.startsWith("@")) { if (key.indexOf(" ") < 2) @@ -239,7 +239,7 @@ custom_continue: key.substr(key.indexOf(" ") + 1).trim(); } if (value.isInt()) - set(key, static_cast(value.toInt()), themeID); + set(key, cast(value.toInt()), themeID); else if (value.isNumeric(true)) set(key, value.toFloat(), themeID); else if (value == "true" || value == "false") @@ -260,7 +260,7 @@ custom_continue: auto tokens = value.tokenize(","); if (tokens.count() != 2) return false; - std::vector vec; + stdvec vec; for (const auto& tok : tokens) { if (!tok.isNumeric(true)) @@ -275,7 +275,7 @@ custom_continue: auto tokens = value.tokenize(","); if (tokens.count() != 4) return false; - std::vector vec; + stdvec vec; for (const auto& tok : tokens) { if (!tok.isNumeric(true)) @@ -288,7 +288,7 @@ custom_continue: { if (exitCondition) return false; - ostd::String lineCopy = line; + String lineCopy = line; for (const auto&[var, val] : variables) { if (lineCopy.contains(var)) @@ -302,13 +302,13 @@ custom_continue: return true; } - ostd::String Stylesheet::parseGroupSelector(const ostd::String& rawSelector) const + String Stylesheet::parseGroupSelector(const String& rawSelector) const { - ostd::String sel = rawSelector.new_trim(); + String sel = rawSelector.new_trim(); if (sel == "") return ""; - ostd::String id = ""; - ostd::String name = sel; - ostd::String qual = ""; + String id = ""; + String name = sel; + String qual = ""; if (sel.contains(" ")) { id = sel.new_substr(0, sel.indexOf(" ")).trim(); @@ -332,11 +332,11 @@ custom_continue: return id; } - std::vector Stylesheet::parseGroup(const ostd::String& selector, const std::vector& group) + stdvec Stylesheet::parseGroup(const String& selector, const stdvec& group) { if (selector.new_trim() == "" || group.size() == 0) return {}; - std::vector newLines; + stdvec newLines; for (const auto& property : group) newLines.push_back(selector.new_add(".").new_add(property)); return newLines; @@ -351,15 +351,15 @@ custom_continue: std::cout << "\n"; } - ostd::String Stylesheet::typeVariantToString(const TypeVariant& v) + String Stylesheet::typeVariantToString(const TypeVariant& v) { - if (auto p = std::get_if(&v)) + if (auto p = std::get_if(&v)) return String("").add(*p); - else if (auto p = std::get_if(&v)) + else if (auto p = std::get_if(&v)) return String("").add(*p); else if (auto p = std::get_if(&v)) return STR_BOOL(*p); - else if (auto p = std::get_if(&v)) + else if (auto p = std::get_if(&v)) return *p; else if (auto p = std::get_if(&v)) return *p; @@ -370,9 +370,9 @@ custom_continue: return ""; } - std::vector Stylesheet::getRichStringLines(const std::vector& lines) + stdvec Stylesheet::getRichStringLines(const stdvec& lines) { - std::vector richLines; + stdvec richLines; for (auto line : lines) { ostd::RegexRichString rgxrstr(line); diff --git a/src/ostd/io/Stylesheet.hpp b/src/ostd/io/Stylesheet.hpp index 383371f..afeeee2 100644 --- a/src/ostd/io/Stylesheet.hpp +++ b/src/ostd/io/Stylesheet.hpp @@ -20,32 +20,32 @@ #pragma once -#include "string/TextStyleParser.hpp" +#include #include #include #include -#include + namespace ostd { class Stylesheet { - public: using QualifierList = std::vector>; - public: using VariableList = std::unordered_map>; - public: using TypeVariant = std::variant; + public: using QualifierList = stdvec>; + public: using VariableList = stdumap>; + public: using TypeVariant = std::variant; public: Stylesheet(void); Stylesheet& clear(void); - Stylesheet& loadFromFile(const ostd::String& filePath, bool clearCurrentRules = true, VariableList variables = {}); - Stylesheet& loadFromString(const ostd::String& content, const ostd::String& filePath = "memory://", bool clearCurrentRules = true, VariableList variables = {}); - void set(const std::string& key, TypeVariant value, const ostd::String& themeID); - void removeRule(const ostd::String& fullKey); - void setFull(const ostd::String& fullKey, TypeVariant value); - const TypeVariant* getVariant(const ostd::String& key, const std::vector& themeIDList, const QualifierList& qualifierList) const; - const TypeVariant* getFull(const ostd::String& fullKey) const; + Stylesheet& loadFromFile(const String& filePath, bool clearCurrentRules = true, VariableList variables = {}); + Stylesheet& loadFromString(const String& content, const String& filePath = "memory://", bool clearCurrentRules = true, VariableList variables = {}); + void set(const std::string& key, TypeVariant value, const String& themeID); + void removeRule(const String& fullKey); + void setFull(const String& fullKey, TypeVariant value); + const TypeVariant* getVariant(const String& key, const stdvec& themeIDList, const QualifierList& qualifierList) const; + const TypeVariant* getFull(const String& fullKey) const; template - inline T get(const ostd::String& key, const T& fallback, const std::vector& themeIDList, const QualifierList& qualifierList) const + inline T get(const String& key, const T& fallback, const stdvec& themeIDList, const QualifierList& qualifierList) const { if (auto v = getVariant(key, themeIDList, qualifierList)) { @@ -56,16 +56,16 @@ namespace ostd } void debugPrint(void); - ostd::String typeVariantToString(const TypeVariant& v); - std::vector getRichStringLines(const std::vector& lines); + String typeVariantToString(const TypeVariant& v); + stdvec getRichStringLines(const stdvec& lines); private: - bool parseThemeFileLine(const ostd::String& line, const VariableList& variables, bool exitCondition = false); - ostd::String parseGroupSelector(const ostd::String& rawSelector) const; - std::vector parseGroup(const ostd::String& selector, const std::vector& group); + bool parseThemeFileLine(const String& line, const VariableList& variables, bool exitCondition = false); + String parseGroupSelector(const String& rawSelector) const; + stdvec parseGroup(const String& selector, const stdvec& group); private: - std::unordered_map m_values; - const ostd::String m_validNameRegex { "^[A-Za-z_][A-Za-z0-9_]*$" }; + stdumap m_values; + const String m_validNameRegex { "^[A-Za-z_][A-Za-z0-9_]*$" }; }; } diff --git a/src/ostd/math/Geometry.hpp b/src/ostd/math/Geometry.hpp index 494469e..86d042d 100755 --- a/src/ostd/math/Geometry.hpp +++ b/src/ostd/math/Geometry.hpp @@ -22,15 +22,14 @@ #include #include -#include #include #define PI 3.1415926535898f #define TWO_PI PI * 2.0f #define HALF_PI PI / 2.0f #define QUARTER_PI PI / 4.0f -#define DEG_TO_RAD(deg) (float)(deg * (PI / 180.0f)) -#define RAD_TO_DEG(rad) (float)(rad * (180.0f / PI)) +#define DEG_TO_RAD(deg) (f32)(deg * (PI / 180.0f)) +#define RAD_TO_DEG(rad) (f32)(rad * (180.0f / PI)) #define LERP(n1, n2, f) (n2 - n1) * f + n1 #define CAP(n, max) (n > max ? max : n) @@ -48,22 +47,22 @@ namespace ostd struct Vec2 : public __i_stringeable { //======================== Data ======================== - float x; - float y; + f32 x; + f32 y; //====================================================== //==================== Construction ==================== - inline Vec2(float xx = 0, float yy = 0) : x(xx), y(yy) { } + inline Vec2(f32 xx = 0, f32 yy = 0) : x(xx), y(yy) { } inline Vec2(const Vec2& v2) { set(v2); } inline Vec2& set(const Vec2& v2) { x = v2.x; y = v2.y; return *this; } - inline Vec2& set(float xx, float yy) { x = xx; y = yy; return *this; } + inline Vec2& set(f32 xx, f32 yy) { x = xx; y = yy; return *this; } //====================================================== //================== Static Functions ================== - inline static Vec2 fromAngle(float angle) { return Vec2(std::cos(angle), std::sin(angle)); } - inline static float angleBetween(const Vec2& v1, const Vec2& v2) { return std::acos(v1.dot(v2) / (v1.mag() * v2.mag())); } + inline static Vec2 fromAngle(f32 angle) { return Vec2(std::cos(angle), std::sin(angle)); } + inline static f32 angleBetween(const Vec2& v1, const Vec2& v2) { return std::acos(v1.dot(v2) / (v1.mag() * v2.mag())); } //====================================================== @@ -75,37 +74,37 @@ namespace ostd //===================== Operations ===================== - inline float mag(void) const { return std::sqrt((x * x) + (y * y)); } + inline f32 mag(void) const { return std::sqrt((x * x) + (y * y)); } inline Vec2 add(Vec2 v2) const { return { x + v2.x, y + v2.y }; } - inline Vec2 add(float x2, float y2) const { return { x + x2, y + y2 }; } + inline Vec2 add(f32 x2, f32 y2) const { return { x + x2, y + y2 }; } inline Vec2 sub(Vec2 v2) const { return { x - v2.x, y - v2.y }; } - inline Vec2 sub(float x2, float y2) const { return { x - x2, y - y2 }; } - inline Vec2 mul(float scalar) const { return { x * scalar, y * scalar }; } - inline Vec2 div(float scalar) const { return { x / scalar, y / scalar }; } + inline Vec2 sub(f32 x2, f32 y2) const { return { x - x2, y - y2 }; } + inline Vec2 mul(f32 scalar) const { return { x * scalar, y * scalar }; } + inline Vec2 div(f32 scalar) const { return { x / scalar, y / scalar }; } - inline Vec2 normalize(void) const { float m = _zp(mag()); return { x / m, y / m }; } - inline float dist(Vec2 v2) const { return std::sqrt((float)((v2.x - x) * (v2.x - x)) + ((v2.y - y) * (v2.y - y))); } - inline float heading(void) const { return std::atan2(y, x); } - inline Vec2 rotate(float angle) const { return Vec2(*this).rotate(angle); } - inline float dot(const Vec2& v2) const { return (x * v2.x) + (y * v2.y); } - inline float cross(const Vec2& v2) const { return (x * v2.y) - (v2.x * y); } + inline Vec2 normalize(void) const { f32 m = _zp(mag()); return { x / m, y / m }; } + inline f32 dist(Vec2 v2) const { return std::sqrt((f32)((v2.x - x) * (v2.x - x)) + ((v2.y - y) * (v2.y - y))); } + inline f32 heading(void) const { return std::atan2(y, x); } + inline Vec2 rotate(f32 angle) const { return Vec2(*this).rotate(angle); } + inline f32 dot(const Vec2& v2) const { return (x * v2.x) + (y * v2.y); } + inline f32 cross(const Vec2& v2) const { return (x * v2.y) - (v2.x * y); } //====================================================== //===================== Modifiers ====================== inline Vec2& addm(const Vec2& v2) { x += v2.x; y += v2.y; return *this; } - inline Vec2& addm(const float& x2, const float& y2) { x += x2; y += y2; return *this; } + inline Vec2& addm(const f32& x2, const f32& y2) { x += x2; y += y2; return *this; } inline Vec2& subm(const Vec2& v2) { x -= v2.x; y -= v2.y; return *this; } - inline Vec2& subm(const float& x2, const float& y2) { x -= x2; y -= y2; return *this; } - inline Vec2& mulm(const float& scalar) { x *= scalar; y *= scalar; return *this; } - inline Vec2& divm(const float& scalar) { x /= scalar; y /= scalar; return *this; } + inline Vec2& subm(const f32& x2, const f32& y2) { x -= x2; y -= y2; return *this; } + inline Vec2& mulm(const f32& scalar) { x *= scalar; y *= scalar; return *this; } + inline Vec2& divm(const f32& scalar) { x /= scalar; y /= scalar; return *this; } - inline Vec2& normalizem(void) { float m = _zp(mag()); x /= m; y /= m; return *this; } - inline Vec2& setMag(const float& mag) { return normalizem().mulm(mag); } - inline Vec2& setHeading(const float& angle) { float m = mag(); set(m * std::cos(angle), m * std::sin(angle)); return *this; } - inline Vec2& rotate(const float& angle) { return setHeading(heading() + angle); } - inline Vec2& limit(const float& max) { float msq = mag(); msq *= msq; if (msq > (max * max)) divm(std::sqrt(msq)).mulm(max); return *this; } + inline Vec2& normalizem(void) { f32 m = _zp(mag()); x /= m; y /= m; return *this; } + inline Vec2& setMag(const f32& mag) { return normalizem().mulm(mag); } + inline Vec2& setHeading(const f32& angle) { f32 m = mag(); set(m * std::cos(angle), m * std::sin(angle)); return *this; } + inline Vec2& rotate(const f32& angle) { return setHeading(heading() + angle); } + inline Vec2& limit(const f32& max) { f32 msq = mag(); msq *= msq; if (msq > (max * max)) divm(std::sqrt(msq)).mulm(max); return *this; } //====================================================== @@ -115,22 +114,22 @@ namespace ostd inline Vec2 operator-() const { return { -x, -y }; } inline Vec2 operator+ (const Vec2& op2 ) const { return add(op2); } inline Vec2 operator- (const Vec2& op2 ) const { return sub(op2); } - inline Vec2 operator+ (const float& op2) const { return add(op2, op2); } - inline Vec2 operator- (const float& op2) const { return sub(op2, op2); } - inline Vec2 operator* (const float& op2) const { return mul(op2); } - inline Vec2 operator/ (const float& op2) const { return div(op2); } + inline Vec2 operator+ (const f32& op2) const { return add(op2, op2); } + inline Vec2 operator- (const f32& op2) const { return sub(op2, op2); } + inline Vec2 operator* (const f32& op2) const { return mul(op2); } + inline Vec2 operator/ (const f32& op2) const { return div(op2); } inline Vec2& operator= (const Vec2& val ) { return set(val); } - inline Vec2& operator= (const float& val) { return set(val, val); } + inline Vec2& operator= (const f32& val) { return set(val, val); } inline Vec2& operator+=(const Vec2& op2 ) { return addm(op2); } inline Vec2& operator-=(const Vec2& op2 ) { return subm(op2); } - inline Vec2& operator+=(const float& op2) { return addm(op2, op2); } - inline Vec2& operator-=(const float& op2) { return subm(op2, op2); } - inline Vec2& operator*=(const float& op2) { return mulm(op2); } - inline Vec2& operator/=(const float& op2) { return divm(op2); } + inline Vec2& operator+=(const f32& op2) { return addm(op2, op2); } + inline Vec2& operator-=(const f32& op2) { return subm(op2, op2); } + inline Vec2& operator*=(const f32& op2) { return mulm(op2); } + inline Vec2& operator/=(const f32& op2) { return divm(op2); } //====================================================== private: - inline float _zp(float n1) const { return (n1 == 0 ? 1 : n1); } + inline f32 _zp(f32 n1) const { return (n1 == 0 ? 1 : n1); } }; @@ -146,12 +145,12 @@ namespace ostd inline Point(T xx, T yy) : x(xx), y(yy) {} inline Point(const Vec2& vec) { x = vec.x; y = vec.y; } inline Point& set(const Point& v2) { x = v2.x; y = v2.y; return *this; } - inline Point& set(float xx, float yy) { x = xx; y = yy; return *this; } + inline Point& set(f32 xx, f32 yy) { x = xx; y = yy; return *this; } //===================== Operators ====================== inline bool operator==(const Point& op2 ) const { return (x == op2.x && y == op2.y); } inline bool operator!=(const Point& op2 ) const { return (x != op2.x || y != op2.y); } - inline operator Vec2() const { return { static_cast(x), static_cast(y) }; } + inline operator Vec2() const { return { cast(x), cast(y) }; } inline Point operator+ (const Point& op2 ) const { return { x + op2.x, y + op2.y }; } inline Point operator- (const Point& op2 ) const { return { x - op2.x, y - op2.y }; } inline Point operator+ (const T& op2) const { return { x + op2, y + op2 }; } @@ -174,31 +173,31 @@ namespace ostd y = (T2)(copy.y); } - inline Vec2 asVec2(void) const { return { static_cast(x), static_cast(y) }; } + inline Vec2 asVec2(void) const { return { cast(x), cast(y) }; } inline String toString(void) const override { return String("{ ").add(x).add(", ").add(y).add(" }"); } }; - typedef Point FPoint; - typedef Point DPoint; - typedef Point UIPoint; - typedef Point UI64Point; - typedef Point UI16Point; - typedef Point UI8Point; - typedef Point IPoint; - typedef Point I64Point; - typedef Point I16Point; - typedef Point I8Point; + typedef Point FPoint; + typedef Point DPoint; + typedef Point UIPoint; + typedef Point UI64Point; + typedef Point UI16Point; + typedef Point UI8Point; + typedef Point IPoint; + typedef Point I64Point; + typedef Point I16Point; + typedef Point I8Point; struct Vec3 : public __i_stringeable { - inline Vec3(float xx = 0, float yy = 0, float zz = 0) + inline Vec3(f32 xx = 0, f32 yy = 0, f32 zz = 0) { x = xx; y = yy; z = zz; } - inline Vec3(const Vec2& xy, float _z = 0.0f) { x = xy.x; y = xy.y; z = _z; } + inline Vec3(const Vec2& xy, f32 _z = 0.0f) { x = xy.x; y = xy.y; z = _z; } inline Vec2 xy(void) const { return Vec2(x, y); } inline Vec2 yz(void) const { return Vec2(y, z); } inline Vec2 zx(void) const { return Vec2(z, x); } @@ -207,22 +206,22 @@ namespace ostd inline bool operator!=(const Vec3& op2 ) const { return (x != op2.x || y != op2.y || op2.z != z); } inline Vec3& operator+=(const Vec3& op2 ) { x += op2.x; y += op2.y; z += op2.z; return *this; } - float x; - float y; - float z; + f32 x; + f32 y; + f32 z; }; struct Vec4 : public __i_stringeable { - inline Vec4(float xx = 0, float yy = 0, float zz = 0, float ww = 0) + inline Vec4(f32 xx = 0, f32 yy = 0, f32 zz = 0, f32 ww = 0) { x = xx; y = yy; z = zz; w = ww; } - inline Vec4(const Vec2& xy, float _z = 0.0f, float _w = 0.0f) { x = xy.x; y = xy.y; z = _z; w = _w; } - inline Vec4(const Vec3& xyz, float _w = 0.0f) { x = xyz.x; y = xyz.y; z = xyz.z; w = _w; } + inline Vec4(const Vec2& xy, f32 _z = 0.0f, f32 _w = 0.0f) { x = xy.x; y = xy.y; z = _z; w = _w; } + inline Vec4(const Vec3& xyz, f32 _w = 0.0f) { x = xyz.x; y = xyz.y; z = xyz.z; w = _w; } inline Vec4(const Vec2& xy, const Vec2& zw) { x = xy.x; y = xy.y; z = zw.x; w = zw.y; } inline Vec2 xy(void) const { return Vec2(x, y); } inline Vec2 yz(void) const { return Vec2(y, z); } @@ -230,10 +229,10 @@ namespace ostd inline Vec2 wx(void) const { return Vec2(w, x); } inline String toString(void) const override { return String("{ ").add(x).add(", ").add(y).add(", ").add(z).add(", ").add(w).add(" }"); } - float x; - float y; - float z; - float w; + f32 x; + f32 y; + f32 z; + f32 w; }; struct Triangle : public __i_stringeable @@ -248,7 +247,7 @@ namespace ostd vB = b; vC = c; } - inline Triangle(float ax, float ay, float bx, float by, float cx, float cy) + inline Triangle(f32 ax, f32 ay, f32 bx, f32 by, f32 cx, f32 cy) { vA.x = ax; vA.y = ay; @@ -259,7 +258,7 @@ namespace ostd } inline bool contains(Vec2 p) { - float d1, d2, d3; + f32 d1, d2, d3; bool has_neg, has_pos; d1 = __sign(p, vA, vB); @@ -274,7 +273,7 @@ namespace ostd inline String toString(void) const override { return String("{ A: ").add(vA.toString()).add(", B: ").add(vB.toString()).add(", C: ").add(vC.toString()).add(" }"); } private: - inline float __sign(Vec2 p1, Vec2 p2, Vec2 p3) + inline f32 __sign(Vec2 p1, Vec2 p2, Vec2 p3) { return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y); } @@ -284,10 +283,10 @@ namespace ostd { public: inline Rectangle(void) : x(0), y(0), w(0), h(0) {} - inline Rectangle(float xx, float yy, float ww, float hh) : x(xx), y(yy), w(ww), h(hh) {} - inline Rectangle(float xw, float yh, bool position = true) { if (position) { x = xw; y = yh; } else { w = xw; h = yh; } } - inline Rectangle(float xx, float yy, Vec2 size) { x = xx; y = yy; w = size.x; h = size.y; } - inline Rectangle(Vec2 position, float ww, float hh) { x = position.x; y = position.y; w = ww; h = hh; } + inline Rectangle(f32 xx, f32 yy, f32 ww, f32 hh) : x(xx), y(yy), w(ww), h(hh) {} + inline Rectangle(f32 xw, f32 yh, bool position = true) { if (position) { x = xw; y = yh; } else { w = xw; h = yh; } } + inline Rectangle(f32 xx, f32 yy, Vec2 size) { x = xx; y = yy; w = size.x; h = size.y; } + inline Rectangle(Vec2 position, f32 ww, f32 hh) { x = position.x; y = position.y; w = ww; h = hh; } inline Rectangle(Vec2 position, Vec2 size) { x = position.x; y = position.y; w = size.x; h = size.y; } virtual ~Rectangle(void) = default; @@ -295,75 +294,75 @@ namespace ostd inline bool operator!=(const Rectangle& op2) const { return !(*this == op2); } inline Rectangle operator+(const Rectangle& op2) const { return { x + op2.x, y + op2.y, w + op2.w, h + op2.h }; } inline Rectangle operator-(const Rectangle& op2) const { return { x - op2.x, y - op2.y, w - op2.w, h - op2.h }; } - inline Rectangle operator+(float s) const { return { x + s, y + s, w + s, h + s }; } - inline Rectangle operator-(float s) const { return { x - s, y - s, w - s, h - s }; } - inline Rectangle operator*(float s) const { return { x * s, y * s, w * s, h * s }; } - inline Rectangle operator/(float s) const { return { x / s, y / s, w / s, h / s }; } + inline Rectangle operator+(f32 s) const { return { x + s, y + s, w + s, h + s }; } + inline Rectangle operator-(f32 s) const { return { x - s, y - s, w - s, h - s }; } + inline Rectangle operator*(f32 s) const { return { x * s, y * s, w * s, h * s }; } + inline Rectangle operator/(f32 s) const { return { x / s, y / s, w / s, h / s }; } inline Rectangle& operator=(const Rectangle& r) { x = r.x; y = r.y; w = r.w; h = r.h; return *this; } - inline Rectangle& operator=(float s) { x = s; y = s; w = s; h = s; return *this; } + inline Rectangle& operator=(f32 s) { x = s; y = s; w = s; h = s; return *this; } inline Rectangle& operator+=(const Rectangle& op2) { x += op2.x; y += op2.y; w += op2.w; h += op2.h; return *this; } inline Rectangle& operator-=(const Rectangle& op2) { x -= op2.x; y -= op2.y; w -= op2.w; h -= op2.h; return *this; } - inline Rectangle& operator+=(float s) { x += s; y += s; w += s; h += s; return *this; } - inline Rectangle& operator-=(float s) { x -= s; y -= s; w -= s; h -= s; return *this; } - inline Rectangle& operator*=(float s) { x *= s; y *= s; w *= s; h *= s; return *this; } - inline Rectangle& operator/=(float s) { x /= s; y /= s; w /= s; h /= s; return *this; } + inline Rectangle& operator+=(f32 s) { x += s; y += s; w += s; h += s; return *this; } + inline Rectangle& operator-=(f32 s) { x -= s; y -= s; w -= s; h -= s; return *this; } + inline Rectangle& operator*=(f32 s) { x *= s; y *= s; w *= s; h *= s; return *this; } + inline Rectangle& operator/=(f32 s) { x /= s; y /= s; w /= s; h /= s; return *this; } - inline virtual float getx(void) const { return x; } - inline virtual float gety(void) const { return y; } - inline virtual float getw(void) const { return w; } - inline virtual float geth(void) const { return h; } - inline virtual float getCenterX(void) const { return getx() + getw() / 2; } - inline virtual float getCenterY(void) const { return gety() + geth() / 2; } + inline virtual f32 getx(void) const { return x; } + inline virtual f32 gety(void) const { return y; } + inline virtual f32 getw(void) const { return w; } + inline virtual f32 geth(void) const { return h; } + inline virtual f32 getCenterX(void) const { return getx() + getw() / 2; } + inline virtual f32 getCenterY(void) const { return gety() + geth() / 2; } - inline virtual void setx(float xx) { x = xx; } - inline virtual void sety(float yy) { y = yy; } - inline virtual void setw(float ww) { w = ww; } - inline virtual void seth(float hh) { h = hh; } + inline virtual void setx(f32 xx) { x = xx; } + inline virtual void sety(f32 yy) { y = yy; } + inline virtual void setw(f32 ww) { w = ww; } + inline virtual void seth(f32 hh) { h = hh; } inline virtual Vec2 getPosition(void) const { return Vec2(getx(), gety()); } inline virtual Vec2 getSize(void) const { return Vec2(getw(), geth()); } inline virtual Vec2 getCenter(void) const { return Vec2(getx() + getw() / 2, gety() + geth() / 2); } inline virtual void setPosition(Vec2 pos) { setx(pos.x); sety(pos.y); } - inline virtual void setPosition(float xx, float yy) { setx(xx); sety(yy); } + inline virtual void setPosition(f32 xx, f32 yy) { setx(xx); sety(yy); } inline virtual void setSize(Vec2 size) { setw(size.x); seth(size.y); } - inline virtual void setSize(float ww, float hh) { setw(ww); seth(hh); } - inline virtual void setBounds(float xx, float yy, float ww, float hh) { setx(xx); sety(yy); setw(ww); seth(hh); } + inline virtual void setSize(f32 ww, f32 hh) { setw(ww); seth(hh); } + inline virtual void setBounds(f32 xx, f32 yy, f32 ww, f32 hh) { setx(xx); sety(yy); setw(ww); seth(hh); } - inline virtual float addx(float xx) { setx(getx() + xx); return getx(); } - inline virtual float addy(float yy) { sety(gety() + yy); return gety(); } - inline virtual Vec2 addPos(float xx, float yy) { return Vec2(addx(xx), addy(yy)); } + inline virtual f32 addx(f32 xx) { setx(getx() + xx); return getx(); } + inline virtual f32 addy(f32 yy) { sety(gety() + yy); return gety(); } + inline virtual Vec2 addPos(f32 xx, f32 yy) { return Vec2(addx(xx), addy(yy)); } inline virtual Vec2 addPos(Vec2 pos) { return addPos(pos.x, pos.y); } - inline virtual float addw(float ww) { setw(getw() + ww); return getw(); } - inline virtual float addh(float hh) { seth(geth() + hh); return geth(); } - inline virtual Vec2 addSize(float ww, float hh) { return Vec2(addw(ww), addh(hh)); } + inline virtual f32 addw(f32 ww) { setw(getw() + ww); return getw(); } + inline virtual f32 addh(f32 hh) { seth(geth() + hh); return geth(); } + inline virtual Vec2 addSize(f32 ww, f32 hh) { return Vec2(addw(ww), addh(hh)); } inline virtual Vec2 addSize(Vec2 size) { return addPos(size.x, size.y); } - inline virtual float subx(float xx) { setx(getx() - xx); return getx(); } - inline virtual float suby(float yy) { sety(gety() - yy); return gety(); } - inline virtual Vec2 subPos(float xx, float yy) { return Vec2(subx(xx), suby(yy)); } + inline virtual f32 subx(f32 xx) { setx(getx() - xx); return getx(); } + inline virtual f32 suby(f32 yy) { sety(gety() - yy); return gety(); } + inline virtual Vec2 subPos(f32 xx, f32 yy) { return Vec2(subx(xx), suby(yy)); } inline virtual Vec2 subPos(Vec2 pos) { return subPos(pos.x, pos.y); } - inline virtual float subw(float ww) { setw(getw() - ww); return getw(); } - inline virtual float subh(float hh) { seth(geth() - hh); return geth(); } - inline virtual Vec2 subSize(float ww, float hh) { return Vec2(subw(ww), subh(hh)); } + inline virtual f32 subw(f32 ww) { setw(getw() - ww); return getw(); } + inline virtual f32 subh(f32 hh) { seth(geth() - hh); return geth(); } + inline virtual Vec2 subSize(f32 ww, f32 hh) { return Vec2(subw(ww), subh(hh)); } inline virtual Vec2 subSize(Vec2 size) { return subPos(size.x, size.y); } - inline virtual float mulx(float xx) { setx(getx() * xx); return getx(); } - inline virtual float muly(float yy) { sety(gety() * yy); return gety(); } - inline virtual Vec2 mulPos(float xx, float yy) { return Vec2(mulx(xx), muly(yy)); } + inline virtual f32 mulx(f32 xx) { setx(getx() * xx); return getx(); } + inline virtual f32 muly(f32 yy) { sety(gety() * yy); return gety(); } + inline virtual Vec2 mulPos(f32 xx, f32 yy) { return Vec2(mulx(xx), muly(yy)); } inline virtual Vec2 mulPos(Vec2 pos) { return mulPos(pos.x, pos.y); } - inline virtual float mulw(float ww) { setw(getw() * ww); return getw(); } - inline virtual float mulh(float hh) { seth(geth() * hh); return geth(); } - inline virtual Vec2 mulSize(float ww, float hh) { return Vec2(mulw(ww), mulh(hh)); } + inline virtual f32 mulw(f32 ww) { setw(getw() * ww); return getw(); } + inline virtual f32 mulh(f32 hh) { seth(geth() * hh); return geth(); } + inline virtual Vec2 mulSize(f32 ww, f32 hh) { return Vec2(mulw(ww), mulh(hh)); } inline virtual Vec2 mulSize(Vec2 size) { return mulPos(size.x, size.y); } - inline virtual float divx(float xx) { setx(getx() / xx); return getx(); } - inline virtual float divy(float yy) { sety(gety() / yy); return gety(); } - inline virtual Vec2 divPos(float xx, float yy) { return Vec2(divx(xx), divy(yy)); } + inline virtual f32 divx(f32 xx) { setx(getx() / xx); return getx(); } + inline virtual f32 divy(f32 yy) { sety(gety() / yy); return gety(); } + inline virtual Vec2 divPos(f32 xx, f32 yy) { return Vec2(divx(xx), divy(yy)); } inline virtual Vec2 divPos(Vec2 pos) { return divPos(pos.x, pos.y); } - inline virtual float divw(float ww) { setw(getw() / ww); return getw(); } - inline virtual float divh(float hh) { seth(geth() / hh); return geth(); } - inline virtual Vec2 divSize(float ww, float hh) { return Vec2(divw(ww), divh(hh)); } + inline virtual f32 divw(f32 ww) { setw(getw() / ww); return getw(); } + inline virtual f32 divh(f32 hh) { seth(geth() / hh); return geth(); } + inline virtual Vec2 divSize(f32 ww, f32 hh) { return Vec2(divw(ww), divh(hh)); } inline virtual Vec2 divSize(Vec2 size) { return divPos(size.x, size.y); } inline virtual Vec2 topLeft(void) const { return getPosition(); } @@ -371,10 +370,10 @@ namespace ostd inline virtual Vec2 bottomLeft(void) const { return Vec2(getx(), gety() + geth()); } inline virtual Vec2 bottomRight(void) const { return Vec2(getx() + getw(), gety() + geth()); } - inline virtual float left(void) const { return getx(); } - inline virtual float right(void) const { return getw(); } - inline virtual float top(void) const { return gety(); } - inline virtual float bottom(void) const { return geth(); } + inline virtual f32 left(void) const { return getx(); } + inline virtual f32 right(void) const { return getw(); } + inline virtual f32 top(void) const { return gety(); } + inline virtual f32 bottom(void) const { return geth(); } inline String toString(void) const override { return String("{ ").add(x).add(", ").add(y).add(", ").add(w).add(", ").add(h).add(" }"); } @@ -400,10 +399,10 @@ namespace ostd { if (!intersects(rect, includeBounds)) return Rectangle(); - float leftX = std::max(x, rect.x); - float rightX = std::min(x + w, rect.x + rect.w); - float topY = std::max(y, rect.y); - float bottomY = std::min(y + h, rect.y + rect.h); + f32 leftX = std::max(x, rect.x); + f32 rightX = std::min(x + w, rect.x + rect.w); + f32 topY = std::max(y, rect.y); + f32 bottomY = std::min(y + h, rect.y + rect.h); return { leftX, topY, rightX - leftX, bottomY - topY }; } inline virtual bool contains(Vec2 p, bool includeBounds = false) const @@ -413,15 +412,15 @@ namespace ostd else return p.x > x && p.y > y && p.x < x + w && p.y < y + h; } - inline bool contains(float xx, float yy, bool includeBounds = false) const { return contains({ xx, yy }, includeBounds); } + inline bool contains(f32 xx, f32 yy, bool includeBounds = false) const { return contains({ xx, yy }, includeBounds); } - inline virtual float getDistance(Vec2 p) const { return sqrt(fabs((p.x - getx()) * (p.x - getx()) + (p.y - gety()) * (p.y - gety()))); } + inline virtual f32 getDistance(Vec2 p) const { return sqrt(fabs((p.x - getx()) * (p.x - getx()) + (p.y - gety()) * (p.y - gety()))); } public: - float x; - float y; - float w; - float h; + f32 x; + f32 y; + f32 w; + f32 h; }; template @@ -439,16 +438,16 @@ namespace ostd Point size; }; - typedef Rect FRect; - typedef Rect DRect; - typedef Rect UIRect; - typedef Rect UI64Rect; - typedef Rect UI16Rect; - typedef Rect UI8Rect; - typedef Rect IRect; - typedef Rect I64Rect; - typedef Rect I16Rect; - typedef Rect I8Rect; + typedef Rect FRect; + typedef Rect DRect; + typedef Rect UIRect; + typedef Rect UI64Rect; + typedef Rect UI16Rect; + typedef Rect UI8Rect; + typedef Rect IRect; + typedef Rect I64Rect; + typedef Rect I16Rect; + typedef Rect I8Rect; template class Line : public __i_stringeable @@ -465,14 +464,14 @@ namespace ostd Point p2; }; - typedef Line FLine; - typedef Line DLine; - typedef Line UILine; - typedef Line UI64Line; - typedef Line UI16Line; - typedef Line UI8Line; - typedef Line ILine; - typedef Line I64Line; - typedef Line I16Line; - typedef Line I8Line; + typedef Line FLine; + typedef Line DLine; + typedef Line UILine; + typedef Line UI64Line; + typedef Line UI16Line; + typedef Line UI8Line; + typedef Line ILine; + typedef Line I64Line; + typedef Line I16Line; + typedef Line I8Line; } diff --git a/src/ostd/math/MathUtils.cpp b/src/ostd/math/MathUtils.cpp index 5e90585..67bc7e8 100644 --- a/src/ostd/math/MathUtils.cpp +++ b/src/ostd/math/MathUtils.cpp @@ -23,9 +23,9 @@ namespace ostd { - float MathUtils::map_value(float input, float input_start, float input_end, float output_start, float output_end) + f32 MathUtils::map_value(f32 input, f32 input_start, f32 input_end, f32 output_start, f32 output_end) { - float slope = 1.0 * (output_end - output_start) / (input_end - input_start); + f32 slope = 1.0 * (output_end - output_start) / (input_end - input_start); return output_start + round(slope * (input - input_start)); } } diff --git a/src/ostd/math/MathUtils.hpp b/src/ostd/math/MathUtils.hpp index 0865c84..62cfa25 100644 --- a/src/ostd/math/MathUtils.hpp +++ b/src/ostd/math/MathUtils.hpp @@ -27,8 +27,8 @@ namespace ostd class MathUtils { public: - static float map_value(float input, float input_start, float input_end, float output_start, float output_end); + static f32 map_value(f32 input, f32 input_start, f32 input_end, f32 output_start, f32 output_end); //Implemented in - static int32_t solveIntegerExpression(const String& expr); + static i32 solveIntegerExpression(const String& expr); }; } diff --git a/src/ostd/math/Random.cpp b/src/ostd/math/Random.cpp index bf1013b..e3d648e 100755 --- a/src/ostd/math/Random.cpp +++ b/src/ostd/math/Random.cpp @@ -3,7 +3,7 @@ namespace ostd { - void RandomGenerator::seed(int64_t _seed) + void RandomGenerator::seed(i64 _seed) { m_engine.seed(_seed); m_noiseGen.SetSeed(_seed); @@ -17,89 +17,89 @@ namespace ostd m_noiseGen.SetSeed(m_seed); } - int64_t RandomGenerator::getSeed(void) + i64 RandomGenerator::getSeed(void) { return m_seed; } - float RandomGenerator::getf32(float min, float max) + f32 RandomGenerator::getf32(f32 min, f32 max) { - __swap_if_first_is_bigger(min, max); - std::uniform_real_distribution dist(min, max); + __swap_if_first_is_bigger(min, max); + std::uniform_real_distribution dist(min, max); return dist(m_engine); } - double RandomGenerator::getf64(double min, double max) + f64 RandomGenerator::getf64(f64 min, f64 max) { - __swap_if_first_is_bigger(min, max); - std::uniform_real_distribution dist(min, max); + __swap_if_first_is_bigger(min, max); + std::uniform_real_distribution dist(min, max); return dist(m_engine); } - uint64_t RandomGenerator::getui64(uint64_t min, uint64_t max) + u64 RandomGenerator::getui64(u64 min, u64 max) { - __swap_if_first_is_bigger(min, max); - std::uniform_int_distribution dist(min, max); + __swap_if_first_is_bigger(min, max); + std::uniform_int_distribution dist(min, max); return dist(m_engine); } - uint32_t RandomGenerator::getui32(uint32_t min, uint32_t max) + u32 RandomGenerator::getui32(u32 min, u32 max) { - __swap_if_first_is_bigger(min, max); - std::uniform_int_distribution dist(min, max); + __swap_if_first_is_bigger(min, max); + std::uniform_int_distribution dist(min, max); return dist(m_engine); } - uint16_t RandomGenerator::getui16(uint16_t min, uint16_t max) + u16 RandomGenerator::getui16(u16 min, u16 max) { - __swap_if_first_is_bigger(min, max); - std::uniform_int_distribution dist(min, max); + __swap_if_first_is_bigger(min, max); + std::uniform_int_distribution dist(min, max); return dist(m_engine); } - uint8_t RandomGenerator::getui8(uint8_t min, uint8_t max) + u8 RandomGenerator::getui8(u8 min, u8 max) { - __swap_if_first_is_bigger(min, max); - std::uniform_int_distribution dist(min, max); + __swap_if_first_is_bigger(min, max); + std::uniform_int_distribution dist(min, max); return dist(m_engine); } - int64_t RandomGenerator::geti64(int64_t min, int64_t max) + i64 RandomGenerator::geti64(i64 min, i64 max) { - __swap_if_first_is_bigger(min, max); - std::uniform_int_distribution dist(min, max); + __swap_if_first_is_bigger(min, max); + std::uniform_int_distribution dist(min, max); return dist(m_engine); } - int32_t RandomGenerator::geti32(int32_t min, int32_t max) + i32 RandomGenerator::geti32(i32 min, i32 max) { - __swap_if_first_is_bigger(min, max); - std::uniform_int_distribution dist(min, max); + __swap_if_first_is_bigger(min, max); + std::uniform_int_distribution dist(min, max); return dist(m_engine); } - int16_t RandomGenerator::geti16(int16_t min, int16_t max) + i16 RandomGenerator::geti16(i16 min, i16 max) { - __swap_if_first_is_bigger(min, max); - std::uniform_int_distribution dist(min, max); + __swap_if_first_is_bigger(min, max); + std::uniform_int_distribution dist(min, max); return dist(m_engine); } - int8_t RandomGenerator::geti8(int8_t min, int8_t max) + i8 RandomGenerator::geti8(i8 min, i8 max) { - __swap_if_first_is_bigger(min, max); - std::uniform_int_distribution dist(min, max); + __swap_if_first_is_bigger(min, max); + std::uniform_int_distribution dist(min, max); return dist(m_engine); } - bool RandomGenerator::getb(float true_percentage) + bool RandomGenerator::getb(f32 true_percentage) { return getf32() >= (1.0f - std::clamp(true_percentage, 0.0f, 1.0f)); } - Vec2 RandomGenerator::getVec2(float min, float max, bool match_xy) + Vec2 RandomGenerator::getVec2(f32 min, f32 max, bool match_xy) { - float x = getf32(min, max); + f32 x = getf32(min, max); return { x, (match_xy ? x : getf32(min, max)) }; } @@ -108,7 +108,7 @@ namespace ostd return { getf32(minmax_x.x, minmax_x.y), getf32(minmax_y.x, minmax_y.y) }; } - float RandomGenerator::getOpenSimplex2D(float x, float y) + f32 RandomGenerator::getOpenSimplex2D(f32 x, f32 y) { m_noiseGen.SetNoiseType(FastNoiseLite::NoiseType_OpenSimplex2); return m_noiseGen.GetNoise(x, y); diff --git a/src/ostd/math/Random.hpp b/src/ostd/math/Random.hpp index 93e466e..6db1d23 100755 --- a/src/ostd/math/Random.hpp +++ b/src/ostd/math/Random.hpp @@ -31,33 +31,33 @@ namespace ostd { public: inline RandomGenerator(bool auto_seed = true) { if (auto_seed) autoSeed(); } - inline RandomGenerator(int64_t _seed) { seed(_seed); } + inline RandomGenerator(i64 _seed) { seed(_seed); } - void seed(int64_t _seed); + void seed(i64 _seed); void autoSeed(void); - int64_t getSeed(void); + i64 getSeed(void); - float getf32(float min = 0.0f, float max = 1.0f); - double getf64(double min = 0.0f, double max = 1.0f); - int64_t geti64(int64_t min = LLONG_MIN, int64_t max = LLONG_MAX); - int32_t geti32(int32_t min = INT_MIN, int32_t max = INT_MAX); - int16_t geti16(int16_t min = SHRT_MIN, int16_t max = SHRT_MAX); - int8_t geti8(int8_t min = CHAR_MIN, int8_t max = CHAR_MAX); - uint64_t getui64(uint64_t min = 0, uint64_t max = ULLONG_MAX); - uint32_t getui32(uint32_t min = 0, uint32_t max = UINT_MAX); - uint16_t getui16(uint16_t min = 0, uint16_t max = USHRT_MAX); - uint8_t getui8(uint8_t min = 0, uint8_t max = UCHAR_MAX); - bool getb(float true_percentage = 0.5f); - Vec2 getVec2(float min = 0.0f, float max = 1.0f, bool match_xy = false); + f32 getf32(f32 min = 0.0f, f32 max = 1.0f); + f64 getf64(f64 min = 0.0f, f64 max = 1.0f); + i64 geti64(i64 min = LLONG_MIN, i64 max = LLONG_MAX); + i32 geti32(i32 min = INT_MIN, i32 max = INT_MAX); + i16 geti16(i16 min = SHRT_MIN, i16 max = SHRT_MAX); + i8 geti8(i8 min = CHAR_MIN, i8 max = CHAR_MAX); + u64 getui64(u64 min = 0, u64 max = ULLONG_MAX); + u32 getui32(u32 min = 0, u32 max = UINT_MAX); + u16 getui16(u16 min = 0, u16 max = USHRT_MAX); + u8 getui8(u8 min = 0, u8 max = UCHAR_MAX); + bool getb(f32 true_percentage = 0.5f); + Vec2 getVec2(f32 min = 0.0f, f32 max = 1.0f, bool match_xy = false); Vec2 getVec2(Vec2 minmax_x = { 0.0f, 1.0f }, Vec2 minmax_y = { 0.0f, 1.0f }); - float getOpenSimplex2D(float x, float y); + f32 getOpenSimplex2D(f32 x, f32 y); inline FastNoiseLite& getNoiseGenerator(void) { return m_noiseGen; } template - inline T& getFromStdVec(std::vector& list) + inline T& getFromStdVec(stdvec& list) { - uint64_t index = static_cast(geti64(0, list.size())); + u64 index = cast(geti64(0, list.size())); return list[index]; } @@ -72,7 +72,7 @@ namespace ostd } private: - int64_t m_seed { 0 }; + i64 m_seed { 0 }; std::mt19937_64 m_engine; FastNoiseLite m_noiseGen; }; @@ -80,27 +80,27 @@ namespace ostd class Random { public: - inline static void seed(int64_t _seed) { Random::s_gen.seed(_seed); } + inline static void seed(i64 _seed) { Random::s_gen.seed(_seed); } inline static void autoSeed(void) { Random::s_gen.autoSeed(); } - inline static int64_t getSeed(void) { return Random::s_gen.getSeed(); } + inline static i64 getSeed(void) { return Random::s_gen.getSeed(); } - inline static float getf32(float min = 0.0f, float max = 1.0f) { return Random::s_gen.getf32(min, max); } - inline static double getf64(double min = 0.0f, double max = 1.0f) { return Random::s_gen.getf64(min, max); } - inline static int64_t geti64(int64_t min = LLONG_MIN, int64_t max = LLONG_MAX) { return Random::s_gen.geti64(min, max); } - inline static int32_t geti32(int32_t min = INT_MIN, int32_t max = INT_MAX) { return Random::s_gen.geti32(min, max); } - inline static int16_t geti16(int16_t min = SHRT_MIN, int16_t max = SHRT_MAX) { return Random::s_gen.geti16(min, max); } - inline static int8_t geti8(int8_t min = CHAR_MIN, int8_t max = CHAR_MAX) { return Random::s_gen.geti8(min, max); } - inline static uint64_t getui64(uint64_t min = 0, uint64_t max = ULLONG_MAX) { return Random::s_gen.getui64(min, max); } - inline static uint32_t getui32(uint32_t min = 0, uint32_t max = UINT_MAX) { return Random::s_gen.getui32(min, max); } - inline static uint16_t getui16(uint16_t min = 0, uint16_t max = USHRT_MAX) { return Random::s_gen.getui16(min, max); } - inline static uint8_t getui8(uint8_t min = 0, uint8_t max = UCHAR_MAX) { return Random::s_gen.getui8(min, max); } - inline static bool getb(float true_percentage = 0.5f) { return Random::s_gen.getb(true_percentage); } - inline static Vec2 getVec2(float min = 0.0f, float max = 1.0f, bool match_xy = false) { return Random::s_gen.getVec2(min, max, match_xy); } + inline static f32 getf32(f32 min = 0.0f, f32 max = 1.0f) { return Random::s_gen.getf32(min, max); } + inline static f64 getf64(f64 min = 0.0f, f64 max = 1.0f) { return Random::s_gen.getf64(min, max); } + inline static i64 geti64(i64 min = LLONG_MIN, i64 max = LLONG_MAX) { return Random::s_gen.geti64(min, max); } + inline static i32 geti32(i32 min = INT_MIN, i32 max = INT_MAX) { return Random::s_gen.geti32(min, max); } + inline static i16 geti16(i16 min = SHRT_MIN, i16 max = SHRT_MAX) { return Random::s_gen.geti16(min, max); } + inline static i8 geti8(i8 min = CHAR_MIN, i8 max = CHAR_MAX) { return Random::s_gen.geti8(min, max); } + inline static u64 getui64(u64 min = 0, u64 max = ULLONG_MAX) { return Random::s_gen.getui64(min, max); } + inline static u32 getui32(u32 min = 0, u32 max = UINT_MAX) { return Random::s_gen.getui32(min, max); } + inline static u16 getui16(u16 min = 0, u16 max = USHRT_MAX) { return Random::s_gen.getui16(min, max); } + inline static u8 getui8(u8 min = 0, u8 max = UCHAR_MAX) { return Random::s_gen.getui8(min, max); } + inline static bool getb(f32 true_percentage = 0.5f) { return Random::s_gen.getb(true_percentage); } + inline static Vec2 getVec2(f32 min = 0.0f, f32 max = 1.0f, bool match_xy = false) { return Random::s_gen.getVec2(min, max, match_xy); } inline static Vec2 getVec2(Vec2 minmax_x = { 0.0f, 1.0f }, Vec2 minmax_y = { 0.0f, 1.0f }) { return Random::s_gen.getVec2(minmax_x, minmax_y); } - inline static float getOpenSimplex2D(float x, float y) { return Random::s_gen.getOpenSimplex2D(x, y); } + inline static f32 getOpenSimplex2D(f32 x, f32 y) { return Random::s_gen.getOpenSimplex2D(x, y); } template - inline static T& getFromStdVec(std::vector& list) { return Random::s_gen.getFromStdVec(list); } + inline static T& getFromStdVec(stdvec& list) { return Random::s_gen.getFromStdVec(list); } private: inline static RandomGenerator s_gen; diff --git a/src/ostd/math/ShuntingYard.cpp b/src/ostd/math/ShuntingYard.cpp index ed8259b..5d29e6e 100644 --- a/src/ostd/math/ShuntingYard.cpp +++ b/src/ostd/math/ShuntingYard.cpp @@ -1,7 +1,7 @@ #include "MathUtils.hpp" #include "../string/String.hpp" #include -#include + #include #include #include @@ -25,7 +25,7 @@ namespace ostd Token(Type type, const std::string& s, - int precedence = -1, + i32 precedence = -1, bool rightAssociative = false, bool unary = false ) @@ -38,7 +38,7 @@ namespace ostd const Type type; const std::string str; - const int precedence; + const i32 precedence; const bool rightAssociative; const bool unary; }; @@ -95,13 +95,13 @@ namespace ostd exit(0); return {}; } - int64_t tmpInt = String(s).toInt(); + i64 tmpInt = String(s).toInt(); //------------------------------------------------- tokens.push_back(Token { Token::Type::Number, String().add(tmpInt) }); --p; } else { Token::Type t = Token::Type::Unknown; - int precedence = -1; + i32 precedence = -1; bool rightAssociative = false; bool unary = false; char c = *p; @@ -145,7 +145,7 @@ namespace ostd std::deque shuntingYard(const std::deque& tokens) { std::deque queue; - std::vector stack; + stdvec stack; // While there are tokens to be read: for(auto token : tokens) { @@ -253,15 +253,15 @@ namespace ostd return queue; } - int32_t MathUtils::solveIntegerExpression(const String& expr) + i32 MathUtils::solveIntegerExpression(const String& expr) { // printf("Tokenize\n"); // printf(reportFmt, "Token", "Queue", "Stack", ""); const auto tokens = exprToTokens(expr); auto queue = shuntingYard(tokens); - std::vector stack; + stdvec stack; - // printf("\nCalculation\n"); + // pri32f("\nCalculation\n"); // printf(reportFmt, "Token", "Queue", "Stack", ""); while(! queue.empty()) { @@ -304,7 +304,7 @@ namespace ostd exit(0); break; case '^': - stack.push_back(static_cast(pow(lhs, rhs))); + stack.push_back(cast(pow(lhs, rhs))); break; case '*': stack.push_back(lhs * rhs); diff --git a/src/ostd/math/SineWave.cpp b/src/ostd/math/SineWave.cpp index 7bfcce9..859e9aa 100755 --- a/src/ostd/math/SineWave.cpp +++ b/src/ostd/math/SineWave.cpp @@ -2,9 +2,9 @@ namespace ostd { - float AdditiveWave::evaluate(float x) + f32 AdditiveWave::evaluate(f32 x) { - float y = 0.0f; + f32 y = 0.0f; for (auto& wave : waves) y += wave.evaluate(x); for (auto& wave : additiveWaves) diff --git a/src/ostd/math/SineWave.hpp b/src/ostd/math/SineWave.hpp index c00edee..070189e 100755 --- a/src/ostd/math/SineWave.hpp +++ b/src/ostd/math/SineWave.hpp @@ -20,7 +20,6 @@ #pragma once -#include #include #include @@ -30,14 +29,14 @@ namespace ostd { public: inline SineWave(void) { period = 1.0f; phase = 0.0f; amplitude = 1.0f; } - inline SineWave(float pr, float am, float ph = 0.0f) { set(pr, am, ph); } - inline SineWave& set(float pr, float am, float ph = 0.0f) { period = pr; phase = ph; amplitude = am; return *this; } - inline float evaluate(float x) { return std::sin(phase + TWO_PI * x / period) * amplitude; } + inline SineWave(f32 pr, f32 am, f32 ph = 0.0f) { set(pr, am, ph); } + inline SineWave& set(f32 pr, f32 am, f32 ph = 0.0f) { period = pr; phase = ph; amplitude = am; return *this; } + inline f32 evaluate(f32 x) { return std::sin(phase + TWO_PI * x / period) * amplitude; } public: - float period; - float phase; - float amplitude; + f32 period; + f32 phase; + f32 amplitude; }; class AdditiveWave : public SineWave @@ -46,10 +45,10 @@ namespace ostd inline AdditiveWave(void) { waves.clear(); } inline AdditiveWave& addWave(SineWave wave) { waves.push_back(wave); return *this; } inline AdditiveWave& addWave(AdditiveWave wave) { additiveWaves.push_back(wave); return *this; } - float evaluate(float x); + f32 evaluate(f32 x); public: - std::vector waves; - std::vector additiveWaves; + stdvec waves; + stdvec additiveWaves; }; } diff --git a/src/ostd/math/Spline.cpp b/src/ostd/math/Spline.cpp index 817d0f8..ae2b4ab 100755 --- a/src/ostd/math/Spline.cpp +++ b/src/ostd/math/Spline.cpp @@ -16,10 +16,10 @@ namespace ostd // } // if (signal.ID == BuiltinSignals::MousePressed) // { - // ogfx::MouseEventData& evt = static_cast(signal.userData); + // ogfx::MouseEventData& evt = cast(signal.userData); // for (auto& node : m_points) // { - // if (ostd::Rectangle(node.position.x - 20, node.position.y - 20, 40, 40).contains((float)evt.position_x, (float)evt.position_y)) + // if (ostd::Rectangle(node.position.x - 20, node.position.y - 20, 40, 40).contains((f32)evt.position_x, (f32)evt.position_y)) // { // m_selectedNode = &node; // return; @@ -34,91 +34,91 @@ namespace ostd // } // else if (signal.ID == BuiltinSignals::MouseMoved) // { - // ogfx::MouseEventData& evt = static_cast(signal.userData); + // ogfx::MouseEventData& evt = cast(signal.userData); // if (m_selectedNode != nullptr) - // m_selectedNode->position = { (float)evt.position_x, (float)evt.position_y }; + // m_selectedNode->position = { (f32)evt.position_x, (f32)evt.position_y }; // } } - tSplineNode Spline::getPoint(float t) + tSplineNode Spline::getPoint(f32 t) { - int32_t p0, p1, p2, p3; + i32 p0, p1, p2, p3; if (!isLooping()) { - p1 = (int32_t)t + 1; + p1 = (i32)t + 1; p2 = p1 + 1; p3 = p2 + 1; p0 = p1 - 1; } else { - p1 = (int32_t)t; + p1 = (i32)t; p2 = (p1 + 1) % m_points.size(); p3 = (p2 + 1) % m_points.size(); p0 = p1 >= 1 ? p1 - 1 : m_points.size() - 1; } - t = t - (int32_t)t; + t = t - (i32)t; - float tt = t * t; - float ttt = tt * t; + f32 tt = t * t; + f32 ttt = tt * t; - float q1 = -ttt + 2.0f*tt - t; - float q2 = 3.0f*ttt - 5.0f*tt + 2.0f; - float q3 = -3.0f*ttt + 4.0f*tt + t; - float q4 = ttt - tt; + f32 q1 = -ttt + 2.0f*tt - t; + f32 q2 = 3.0f*ttt - 5.0f*tt + 2.0f; + f32 q3 = -3.0f*ttt + 4.0f*tt + t; + f32 q4 = ttt - tt; - float tx = 0.5f * (m_points[p0].position.x * q1 + m_points[p1].position.x * q2 + m_points[p2].position.x * q3 + m_points[p3].position.x * q4); - float ty = 0.5f * (m_points[p0].position.y * q1 + m_points[p1].position.y * q2 + m_points[p2].position.y * q3 + m_points[p3].position.y * q4); + f32 tx = 0.5f * (m_points[p0].position.x * q1 + m_points[p1].position.x * q2 + m_points[p2].position.x * q3 + m_points[p3].position.x * q4); + f32 ty = 0.5f * (m_points[p0].position.y * q1 + m_points[p1].position.y * q2 + m_points[p2].position.y * q3 + m_points[p3].position.y * q4); return { { tx, ty }, 0.0f }; } - tSplineNode Spline::getGradient(float t) + tSplineNode Spline::getGradient(f32 t) { - int32_t p0, p1, p2, p3; + i32 p0, p1, p2, p3; if (!isLooping()) { - p1 = (int32_t)t + 1; + p1 = (i32)t + 1; p2 = p1 + 1; p3 = p2 + 1; p0 = p1 - 1; } else { - p1 = (int32_t)t; + p1 = (i32)t; p2 = (p1 + 1) % m_points.size(); p3 = (p2 + 1) % m_points.size(); p0 = p1 >= 1 ? p1 - 1 : m_points.size() - 1; } - t = t - (int32_t)t; + t = t - (i32)t; - float tt = t * t; - float ttt = tt * t; + f32 tt = t * t; + f32 ttt = tt * t; - float q1 = -3.0f * tt + 4.0f*t - 1; - float q2 = 9.0f*tt - 10.0f*t; - float q3 = -9.0f*tt + 8.0f*t + 1.0f; - float q4 = 3.0f*tt - 2.0f*t; + f32 q1 = -3.0f * tt + 4.0f*t - 1; + f32 q2 = 9.0f*tt - 10.0f*t; + f32 q3 = -9.0f*tt + 8.0f*t + 1.0f; + f32 q4 = 3.0f*tt - 2.0f*t; - float tx = 0.5f * (m_points[p0].position.x * q1 + m_points[p1].position.x * q2 + m_points[p2].position.x * q3 + m_points[p3].position.x * q4); - float ty = 0.5f * (m_points[p0].position.y * q1 + m_points[p1].position.y * q2 + m_points[p2].position.y * q3 + m_points[p3].position.y * q4); + f32 tx = 0.5f * (m_points[p0].position.x * q1 + m_points[p1].position.x * q2 + m_points[p2].position.x * q3 + m_points[p3].position.x * q4); + f32 ty = 0.5f * (m_points[p0].position.y * q1 + m_points[p1].position.y * q2 + m_points[p2].position.y * q3 + m_points[p3].position.y * q4); return { { tx, ty }, 0.0f }; } - float Spline::updateSegmentLength(int32_t node) + f32 Spline::updateSegmentLength(i32 node) { - float fLength = 0.0f; - float fStepSize = 0.005; + f32 fLength = 0.0f; + f32 fStepSize = 0.005; tSplineNode old_point, new_point; - old_point = getPoint((float)node); + old_point = getPoint((f32)node); - for (float t = 0; t < 1.0f; t += fStepSize) + for (f32 t = 0; t < 1.0f; t += fStepSize) { - new_point = getGradient((float)node + t); + new_point = getGradient((f32)node + t); fLength += std::sqrt((new_point.position.x - old_point.position.x)*(new_point.position.x - old_point.position.x) + (new_point.position.y - old_point.position.y)*(new_point.position.y - old_point.position.y)); old_point = new_point; @@ -126,15 +126,15 @@ namespace ostd return fLength; } - float Spline::getNormalisedOffset(float p) + f32 Spline::getNormalisedOffset(f32 p) { - int32_t i = 0; + i32 i = 0; while (p > m_points[i].length) { p -= m_points[i].length; i++; } - return (float)i + (p / m_points[i].length); + return (f32)i + (p / m_points[i].length); } void Spline::connectSignals(void) @@ -149,7 +149,7 @@ namespace ostd void Spline::updateTotalLength(void) { m_totalLength = 0.0f; - for (int i = 0; i < m_points.size(); i++) + for (i32 i = 0; i < m_points.size(); i++) { m_totalLength += (m_points[i].length = updateSegmentLength(i)); } diff --git a/src/ostd/math/Spline.hpp b/src/ostd/math/Spline.hpp index 2f380ba..88e5a64 100755 --- a/src/ostd/math/Spline.hpp +++ b/src/ostd/math/Spline.hpp @@ -29,33 +29,33 @@ namespace ostd struct tSplineNode { Vec2 position; - float length; + f32 length; }; class Spline : public BaseObject { public: using EventHandlerCallback = std::function; - using DrawCallback = std::function; + using DrawCallback = std::function; public: Spline(void); void handleSignal(Signal& signal) override; - tSplineNode getPoint(float t); - tSplineNode getGradient(float t); - float updateSegmentLength(int32_t node); - float getNormalisedOffset(float p); + tSplineNode getPoint(f32 t); + tSplineNode getGradient(f32 t); + f32 updateSegmentLength(i32 node); + f32 getNormalisedOffset(f32 p); void connectSignals(void); void updateTotalLength(void); - inline void draw(float resolution = 0.01f, float lineWidth = 4.0f, float controlPointSize = 9.0f) { if (m_drawCallback) m_drawCallback(resolution, lineWidth, controlPointSize); } + inline void draw(f32 resolution = 0.01f, f32 lineWidth = 4.0f, f32 controlPointSize = 9.0f) { if (m_drawCallback) m_drawCallback(resolution, lineWidth, controlPointSize); } inline bool exists(void) { return m_points.size() > 1; } inline void addPoint(Vec2 position) { m_points.push_back({ position, 0.0f }); updateTotalLength(); } - inline float getTotalLength(void) { return m_totalLength; } + inline f32 getTotalLength(void) { return m_totalLength; } inline bool isEditable(void) { return m_editable; } inline bool isLooping(void) { return m_looping; } inline void setEditable(bool e) { m_editable = e; } inline void setLooping(bool l) { m_looping = l; } - inline uint32_t getPointCount(void) { return m_points.size(); } + inline u32 getPointCount(void) { return m_points.size(); } inline void clear(void) { m_points.clear(); } inline bool isEnabled(void) { return m_enabled; } inline void enable(bool e = true) { m_enabled = e; } @@ -64,8 +64,8 @@ namespace ostd inline void setDrawCallback(DrawCallback drawCallback) { m_drawCallback = drawCallback; } protected: - std::vector m_points; - float m_totalLength = 0.0f; + stdvec m_points; + f32 m_totalLength = 0.0f; tSplineNode* m_selectedNode { nullptr }; bool m_editable { false }; bool m_looping { true }; diff --git a/src/ostd/string/String.cpp b/src/ostd/string/String.cpp index ab2bfd9..411eb29 100644 --- a/src/ostd/string/String.cpp +++ b/src/ostd/string/String.cpp @@ -22,7 +22,7 @@ namespace ostd String& String::ltrim(void) { - m_data.erase(m_data.begin(), std::find_if(m_data.begin(), m_data.end(), [](unsigned char ch) { + m_data.erase(m_data.begin(), std::find_if(m_data.begin(), m_data.end(), [](uchar ch) { return !std::isspace(ch); })); return *this; @@ -30,7 +30,7 @@ namespace ostd String& String::rtrim(void) { - m_data.erase(std::find_if(m_data.rbegin(), m_data.rend(), [](unsigned char ch) { + m_data.erase(std::find_if(m_data.rbegin(), m_data.rend(), [](uchar ch) { return !std::isspace(ch); }).base(), m_data.end()); return *this; @@ -43,22 +43,22 @@ namespace ostd String& String::toLower(void) { - std::transform(m_data.begin(), m_data.end(), m_data.begin(), [](unsigned char c){ return std::tolower(c); }); + std::transform(m_data.begin(), m_data.end(), m_data.begin(), [](uchar c){ return std::tolower(c); }); return *this; } String& String::toUpper(void) { - std::transform(m_data.begin(), m_data.end(), m_data.begin(), [](unsigned char c){ return std::toupper(c); }); + std::transform(m_data.begin(), m_data.end(), m_data.begin(), [](uchar c){ return std::toupper(c); }); return *this; } - String& String::addPadding(uint32_t new_string_length, char c, ePaddingBehavior padding_behavior) + String& String::addPadding(u32 new_string_length, char c, ePaddingBehavior padding_behavior) { if (len() - 1 >= new_string_length) return *this; - uint32_t diff = new_string_length - len(); - int32_t leftPadding = 0; - int32_t rightPadding = 0; + u32 diff = new_string_length - len(); + i32 leftPadding = 0; + i32 rightPadding = 0; switch (padding_behavior) { case ePaddingBehavior::ForceEvenNegative: @@ -96,7 +96,7 @@ namespace ostd return addLeftPadding(len() + leftPadding, c).addRightPadding(len() + rightPadding, c); } - String& String::addLeftPadding(uint32_t new_string_length, char c) + String& String::addLeftPadding(u32 new_string_length, char c) { reverse(); while (len() < new_string_length) @@ -105,7 +105,7 @@ namespace ostd return *this; } - String& String::addRightPadding(uint32_t new_string_length, char c) + String& String::addRightPadding(u32 new_string_length, char c) { while (len() < new_string_length) m_data += c; @@ -127,7 +127,7 @@ namespace ostd String& String::replaceFirst(const String& what, const String& with) { - int32_t index = indexOf(what); + i32 index = indexOf(what); if (index == -1) return *this; m_data.replace(index, what.len(), with.cpp_str()); return *this; @@ -149,26 +149,26 @@ namespace ostd return *this; } - String& String::put(uint32_t index, char c) + String& String::put(u32 index, char c) { if (index < m_data.length()) m_data[index] = c; return *this; } - String& String::substr(uint32_t start, int32_t end) + String& String::substr(u32 start, i32 end) { if (end < 0) m_data = m_data.substr(start); else m_data = m_data.substr(start, end - start); return *this; } - String& String::fixedLength(uint32_t length, char fill_character, const String& truncate_indicator) + String& String::fixedLength(u32 length, char fill_character, const String& truncate_indicator) { if (length < truncate_indicator.len()) return *this; if (len() > length) { - int32_t tr_len = truncate_indicator.len(); + i32 tr_len = truncate_indicator.len(); substr(0, length - tr_len); return add(truncate_indicator); } @@ -190,55 +190,55 @@ namespace ostd return *this; } - String& String::add(uint8_t i) + String& String::add(u8 i) { m_data += std::to_string(i); return *this; } - String& String::add(int8_t i) + String& String::add(i8 i) { m_data += std::to_string(i); return *this; } - String& String::add(uint16_t i) + String& String::add(u16 i) { m_data += std::to_string(i); return *this; } - String& String::add(int16_t i) + String& String::add(i16 i) { m_data += std::to_string(i); return *this; } - String& String::add(uint32_t i) + String& String::add(u32 i) { m_data += std::to_string(i); return *this; } - String& String::add(int32_t i) + String& String::add(i32 i) { m_data += std::to_string(i); return *this; } - String& String::add(uint64_t i) + String& String::add(u64 i) { m_data += std::to_string(i); return *this; } - String& String::add(int64_t i) + String& String::add(i64 i) { m_data += std::to_string(i); return *this; } - String& String::add(float f, uint8_t precision) + String& String::add(f32 f, u8 precision) { std::stringstream stream; if (precision != 0) @@ -249,7 +249,7 @@ namespace ostd return add(s); } - String& String::add(double f, uint8_t precision) + String& String::add(f64 f, u8 precision) { std::stringstream stream; if (precision != 0) @@ -293,19 +293,19 @@ namespace ostd return __str.toUpper(); } - String String::new_addPadding(uint32_t new_string_length, char c, ePaddingBehavior padding_behavior) const + String String::new_addPadding(u32 new_string_length, char c, ePaddingBehavior padding_behavior) const { String __str = m_data; return __str.addPadding(new_string_length, c, padding_behavior); } - String String::new_addLeftPadding(uint32_t new_string_length, char c) const + String String::new_addLeftPadding(u32 new_string_length, char c) const { String __str = m_data; return __str.addLeftPadding(new_string_length, c); } - String String::new_addRightPadding(uint32_t new_string_length, char c) const + String String::new_addRightPadding(u32 new_string_length, char c) const { String __str = m_data; return __str.addRightPadding(new_string_length, c); @@ -335,19 +335,19 @@ namespace ostd return __str.regexReplace(regex_pattern, replace_with, case_insensitive); } - String String::new_put(uint32_t index, char c) const + String String::new_put(u32 index, char c) const { String __str = m_data; return __str.put(index, c); } - String String::new_substr(uint32_t start, int32_t end) const + String String::new_substr(u32 start, i32 end) const { String __str = m_data; return __str.substr(start, end); } - String String::new_fixedLength(uint32_t length, char fill_character, const String& truncate_indicator) const + String String::new_fixedLength(u32 length, char fill_character, const String& truncate_indicator) const { String __str = m_data; return __str.fixedLength(length, fill_character, truncate_indicator); @@ -366,61 +366,61 @@ namespace ostd return __str.add(se); } - String String::new_add(uint8_t i) const + String String::new_add(u8 i) const { String __str = m_data; return __str.add(i); } - String String::new_add(int8_t i) const + String String::new_add(i8 i) const { String __str = m_data; return __str.add(i); } - String String::new_add(uint16_t i) const + String String::new_add(u16 i) const { String __str = m_data; return __str.add(i); } - String String::new_add(int16_t i) const + String String::new_add(i16 i) const { String __str = m_data; return __str.add(i); } - String String::new_add(uint32_t i) const + String String::new_add(u32 i) const { String __str = m_data; return __str.add(i); } - String String::new_add(int32_t i) const + String String::new_add(i32 i) const { String __str = m_data; return __str.add(i); } - String String::new_add(uint64_t i) const + String String::new_add(u64 i) const { String __str = m_data; return __str.add(i); } - String String::new_add(int64_t i) const + String String::new_add(i64 i) const { String __str = m_data; return __str.add(i); } - String String::new_add(float f, uint8_t precision) const + String String::new_add(f32 f, u8 precision) const { String __str = m_data; return __str.add(f, precision); } - String String::new_add(double f, uint8_t precision) const + String String::new_add(f64 f, u8 precision) const { String __str = m_data; return __str.add(f, precision); @@ -429,12 +429,12 @@ namespace ostd //Utility - int64_t String::toInt(void) const + i64 String::toInt(void) const { if (!isNumeric(false)) return 0; - ostd::String str = String(m_data).trim().toLower(); + String str = String(m_data).trim().toLower(); if (!str.isInt()) return 0; - int32_t base = 10; + i32 base = 10; if (str.cpp_str().rfind("0x", 0) == 0) { str = str.substr(2); @@ -448,13 +448,13 @@ namespace ostd return strtoul(str.c_str(), NULL, base); } - float String::toFloat(void) const + f32 String::toFloat(void) const { if (!isNumeric(true)) return 0; return std::stof(m_data); } - double String::toDouble(void) const + f64 String::toDouble(void) const { if (!isNumeric(true)) return 0; return std::stod(m_data); @@ -465,7 +465,7 @@ namespace ostd if (decimal) { std::istringstream iss(m_data); - double f; + f64 f; iss >> std::noskipws >> f; return iss.eof() && !iss.fail(); } @@ -474,20 +474,20 @@ namespace ostd bool String::isInt(void) const { - ostd::String str = String(m_data).trim().toLower(); + String str = String(m_data).trim().toLower(); bool isNumber = std::ranges::all_of(str.begin(), str.end(), [](char c){ return isdigit(c) != 0; }); return str.isHex() || str.isBin() || isNumber; } bool String::isHex(void) const { - ostd::String hex = String(m_data).trim().toLower(); + String hex = String(m_data).trim().toLower(); return hex.cpp_str().compare(0, 2, "0x") == 0 && hex.cpp_str().size() > 2 && hex.cpp_str().find_first_not_of("0123456789abcdef", 2) == std::string::npos; } bool String::isBin(void) const { - ostd::String bin = String(m_data).trim().toLower(); + String bin = String(m_data).trim().toLower(); return bin.cpp_str().compare(0, 2, "0b") == 0 && bin.cpp_str().size() > 2 && bin.cpp_str().find_first_not_of("01", 2) == std::string::npos; } @@ -513,56 +513,56 @@ namespace ostd bool String::regexMatches(const String& regex_pattern, bool case_insensitive) const { - try - { - boost::regex rgx(regex_pattern.cpp_str(), case_insensitive ? boost::regex_constants::icase : boost::regex_constants::normal); - return boost::regex_search(m_data, rgx); - } - catch (const boost::regex_error& err) - { - std::cerr << err.what() << '\n'; //TODO: Better error handling - return false; - } + try + { + boost::regex rgx(regex_pattern.cpp_str(), case_insensitive ? boost::regex_constants::icase : boost::regex_constants::normal); + return boost::regex_search(m_data, rgx); + } + catch (const boost::regex_error& err) + { + std::cerr << err.what() << '\n'; //TODO: Better error handling + return false; + } } - uint32_t String::count(const String& str) const + u32 String::count(const String& str) const { Tokens tok = tokenize(str, false, true); if (tok.count() < 1) return 0; return tok.count() - 1; } - int32_t String::indexOf(char c, uint32_t start) const + i32 String::indexOf(char c, u32 start) const { cpp_string cc = ""; cc += c; - int32_t pos = m_data.find(cc.c_str(), start); + i32 pos = m_data.find(cc.c_str(), start); if (pos == std::string::npos) return -1; return pos; } - int32_t String::indexOf(const String& str, uint32_t start) const + i32 String::indexOf(const String& str, u32 start) const { - int32_t pos = m_data.find(str.c_str(), start); + i32 pos = m_data.find(str.c_str(), start); if (pos == std::string::npos) return -1; return pos; } - int32_t String::lastIndexOf(char c) const + i32 String::lastIndexOf(char c) const { String se(m_data); se.reverse(); - int32_t pos = se.indexOf(c); + i32 pos = se.indexOf(c); if (pos < 0) return -1; return len() - pos - 1; } - int32_t String::lastIndexOf(const String& str) const + i32 String::lastIndexOf(const String& str) const { String se(m_data); se.reverse(); String se2(str); - int32_t pos = se.indexOf(se2.new_reverse()); + i32 pos = se.indexOf(se2.new_reverse()); if (pos < 0) return -1; return len() - pos - str.len(); } @@ -570,8 +570,8 @@ namespace ostd String::Tokens String::tokenize(const String& delimiter, bool trim_tokens, bool allow_white_space_only_tokens) const { Tokens tokens; - int32_t sindex = 0; - int32_t eindex = 0; + i32 sindex = 0; + i32 eindex = 0; String __token = ""; while ((eindex = indexOf(delimiter, sindex)) != -1) { @@ -608,91 +608,91 @@ namespace ostd return tokens; } - String String::getHexStr(uint64_t value, bool prefix, uint8_t nbytes) + String String::getHexStr(u64 value, bool prefix, u8 nbytes) { union { - uint64_t val; - uint8_t bytes[8]; + u64 val; + u8 bytes[8]; } __tmp_editor; __tmp_editor.val = value; if (nbytes < 1 || nbytes > 8) nbytes = 1; std::ostringstream oss; if (prefix) oss << "0x"; - for (int8_t b = nbytes - 1; b >= 0; b--) - oss << std::setw(2) << std::setfill('0') << std::uppercase << std::hex << (int)__tmp_editor.bytes[b]; + for (i8 b = nbytes - 1; b >= 0; b--) + oss << std::setw(2) << std::setfill('0') << std::uppercase << std::hex << (i32)__tmp_editor.bytes[b]; return oss.str(); } - String String::getBinStr(uint64_t value, bool prefix, uint8_t nbytes) + String String::getBinStr(u64 value, bool prefix, u8 nbytes) { union { - uint64_t val; - uint8_t bytes[8]; + u64 val; + u8 bytes[8]; } __tmp_editor; __tmp_editor.val = value; if (nbytes < 1 || nbytes > 8) nbytes = 1; std::ostringstream oss; if (prefix) oss << "0b "; - for (int8_t b = nbytes - 1; b >= 0; b--) + for (i8 b = nbytes - 1; b >= 0; b--) oss << std::bitset<8>((char)__tmp_editor.bytes[b]) << " "; return oss.str(); } - String String::duplicateChar(unsigned char c, uint16_t count) + String String::duplicateChar(uchar c, u16 count) { String str = ""; - for (uint16_t i = 0; i < count; i++) + for (u16 i = 0; i < count; i++) str = str += c; return str; } - std::vector String::decodeUTF8(const ostd::String& s) + stdvec String::decodeUTF8(const String& s) { - std::vector out; - const char* p = s.m_data.data(); - const char* end = p + s.m_data.size(); + stdvec out; + const char* p = s.m_data.data(); + const char* end = p + s.m_data.size(); - while (p < end) - out.push_back(utf8_next(p, end)); + while (p < end) + out.push_back(utf8_next(p, end)); - return out; + return out; } - uint32_t String::utf8_next(const char*& p, const char* end) + u32 String::utf8_next(const char*& p, const char* end) { - uint8_t c = static_cast(*p++); + u8 c = cast(*p++); - // ASCII fast path - if (c < 0x80) - return c; + // ASCII fast path + if (c < 0x80) + return c; - // 2-byte sequence - if ((c >> 5) == 0x6) { - uint32_t cp = (c & 0x1F) << 6; - cp |= (static_cast(*p++) & 0x3F); - return cp; - } + // 2-byte sequence + if ((c >> 5) == 0x6) { + u32 cp = (c & 0x1F) << 6; + cp |= (cast(*p++) & 0x3F); + return cp; + } - // 3-byte sequence - if ((c >> 4) == 0xE) { - uint32_t cp = (c & 0x0F) << 12; - cp |= (static_cast(*p++) & 0x3F) << 6; - cp |= (static_cast(*p++) & 0x3F); - return cp; - } + // 3-byte sequence + if ((c >> 4) == 0xE) { + u32 cp = (c & 0x0F) << 12; + cp |= (cast(*p++) & 0x3F) << 6; + cp |= (cast(*p++) & 0x3F); + return cp; + } - // 4-byte sequence - if ((c >> 3) == 0x1E) { - uint32_t cp = (c & 0x07) << 18; - cp |= (static_cast(*p++) & 0x3F) << 12; - cp |= (static_cast(*p++) & 0x3F) << 6; - cp |= (static_cast(*p++) & 0x3F); - return cp; - } + // 4-byte sequence + if ((c >> 3) == 0x1E) { + u32 cp = (c & 0x07) << 18; + cp |= (cast(*p++) & 0x3F) << 12; + cp |= (cast(*p++) & 0x3F) << 6; + cp |= (cast(*p++) & 0x3F); + return cp; + } - // Invalid byte → return replacement character - return 0xFFFD; + // Invalid byte → return replacement character + return 0xFFFD; } String operator+(const cpp_string& str1, const String& str) diff --git a/src/ostd/string/String.hpp b/src/ostd/string/String.hpp index 0f5c389..1f26975 100644 --- a/src/ostd/string/String.hpp +++ b/src/ostd/string/String.hpp @@ -1,21 +1,21 @@ /* - OmniaFramework - A collection of useful functionality - Copyright (C) 2025 OmniaX-Dev + OmniaFramework - A collection of useful functionality + Copyright (C) 2025 OmniaX-Dev - This file is part of OmniaFramework. + This file is part of OmniaFramework. - OmniaFramework is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + OmniaFramework is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - OmniaFramework is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + OmniaFramework is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with OmniaFramework. If not, see . + You should have received a copy of the GNU General Public License + along with OmniaFramework. If not, see . */ #pragma once @@ -38,9 +38,9 @@ namespace ostd inline bool hasPrevious(void) { return m_tokens.size() > 0 && m_current_index > 0; } String next(void); String previous(void); - inline uint32_t count(void) { return m_tokens.size(); } - inline std::vector getRawData(void) { return m_tokens; } - inline uint32_t getCurrentIndex(void) { return m_current_index; } + inline u32 count(void) { return m_tokens.size(); } + inline stdvec getRawData(void) { return m_tokens; } + inline u32 getCurrentIndex(void) { return m_current_index; } inline void cycle(void) { m_current_index = 0; } inline auto begin(void) { return m_tokens.begin(); } @@ -54,8 +54,8 @@ namespace ostd inline Tokens(void) { m_current_index = 0; } private: - std::vector m_tokens; - uint32_t m_current_index; + stdvec m_tokens; + u32 m_current_index; friend class String; }; @@ -69,11 +69,11 @@ namespace ostd inline cpp_string cpp_str(void) const { return m_data; } inline cpp_string& cpp_str_ref(void) { return m_data; } inline const char* c_str(void) const { return m_data.c_str(); } - inline char at(uint32_t index) const { return m_data[index]; } - inline uint32_t len(void) const { return m_data.length(); } - inline char operator[](uint32_t index) const { return m_data[index]; } + inline char at(u32 index) const { return m_data[index]; } + inline u32 len(void) const { return m_data.length(); } + inline char operator[](u32 index) const { return m_data[index]; } inline bool operator== (const char* str2) const { return std::strcmp(c_str(), str2) == 0; } - inline bool operator!= (const char* str2) const { return std::strcmp(c_str(), str2) != 0; } + inline bool operator!= (const char* str2) const { return std::strcmp(c_str(), str2) != 0; } inline String operator+(const String& str2) const { return m_data + str2.cpp_str(); } friend String operator+(const cpp_string& str1, const String& str); inline String& operator+=(const String& str2) { m_data += str2.cpp_str(); return *this; } @@ -83,7 +83,7 @@ namespace ostd inline operator std::filesystem::path() const { return cpp_str(); } inline String& clr(void) { m_data = ""; return *this; } inline String& set(const cpp_string& str) { m_data = str; return *this; } - inline std::vector getUTF8Codepoints(void) const { return decodeUTF8(m_data); } + inline stdvec getUTF8Codepoints(void) const { return decodeUTF8(m_data); } inline auto begin(void) { return m_data.begin(); } inline auto end(void) { return m_data.end(); } @@ -98,29 +98,29 @@ namespace ostd String& trim(void); String& toLower(void); String& toUpper(void); - String& addPadding(uint32_t new_string_length, char c = ' ', ePaddingBehavior padding_behavior = ePaddingBehavior::ForceEvenPositive); - String& addLeftPadding(uint32_t new_string_length, char c = ' '); - String& addRightPadding(uint32_t new_string_length, char c = ' '); + String& addPadding(u32 new_string_length, char c = ' ', ePaddingBehavior padding_behavior = ePaddingBehavior::ForceEvenPositive); + String& addLeftPadding(u32 new_string_length, char c = ' '); + String& addRightPadding(u32 new_string_length, char c = ' '); String& reverse(void); String& replaceAll(const String& what, const String& with); String& replaceFirst(const String& what, const String& with); String& regexReplace(const String& regex_pattern, const String& replace_with, bool case_insensitive = false); - String& put(uint32_t index, char c); - String& substr(uint32_t start, int32_t end = -1); - String& fixedLength(uint32_t length, char fill_character = ' ', const String& truncate_indicator = "... "); + String& put(u32 index, char c); + String& substr(u32 start, i32 end = -1); + String& fixedLength(u32 length, char fill_character = ' ', const String& truncate_indicator = "... "); String& addChar(char c); String& add(const String& se); - String& add(uint8_t i); - String& add(int8_t i); - String& add(uint16_t i); - String& add(int16_t i); - String& add(uint32_t i); - String& add(int32_t i); - String& add(uint64_t i); - String& add(int64_t i); - String& add(float f, uint8_t precision = 0); - String& add(double f, uint8_t precision = 0); + String& add(u8 i); + String& add(i8 i); + String& add(u16 i); + String& add(i16 i); + String& add(u32 i); + String& add(i32 i); + String& add(u64 i); + String& add(i64 i); + String& add(f32 f, u8 precision = 0); + String& add(f64 f, u8 precision = 0); //New String String new_ltrim(void) const; @@ -128,34 +128,34 @@ namespace ostd String new_trim(void) const; String new_toLower(void) const; String new_toUpper(void) const; - String new_addPadding(uint32_t new_string_length, char c = ' ', ePaddingBehavior padding_behavior = ePaddingBehavior::ForceEvenPositive) const; - String new_addLeftPadding(uint32_t new_string_length, char c = ' ') const; - String new_addRightPadding(uint32_t new_string_length, char c = ' ') const; + String new_addPadding(u32 new_string_length, char c = ' ', ePaddingBehavior padding_behavior = ePaddingBehavior::ForceEvenPositive) const; + String new_addLeftPadding(u32 new_string_length, char c = ' ') const; + String new_addRightPadding(u32 new_string_length, char c = ' ') const; String new_reverse(void) const; String new_replaceAll(const String& what, const String& with) const; String new_replaceFirst(const String& what, const String& with) const; String new_regexReplace(const String& regex_pattern, const String& replace_with, bool case_insensitive = false) const; - String new_put(uint32_t index, char c) const; - String new_substr(uint32_t start, int32_t end = -1) const; - String new_fixedLength(uint32_t length, char fill_character = ' ', const String& truncate_indicator = "... ") const; + String new_put(u32 index, char c) const; + String new_substr(u32 start, i32 end = -1) const; + String new_fixedLength(u32 length, char fill_character = ' ', const String& truncate_indicator = "... ") const; String new_addChar(char c) const; String new_add(const String& se) const; - String new_add(uint8_t i) const; - String new_add(int8_t i) const; - String new_add(uint16_t i) const; - String new_add(int16_t i) const; - String new_add(uint32_t i) const; - String new_add(int32_t i) const; - String new_add(uint64_t i) const; - String new_add(int64_t i) const; - String new_add(float f, uint8_t precision = 0) const; - String new_add(double f, uint8_t precision = 0) const; + String new_add(u8 i) const; + String new_add(i8 i) const; + String new_add(u16 i) const; + String new_add(i16 i) const; + String new_add(u32 i) const; + String new_add(i32 i) const; + String new_add(u64 i) const; + String new_add(i64 i) const; + String new_add(f32 f, u8 precision = 0) const; + String new_add(f64 f, u8 precision = 0) const; //Utility - int64_t toInt(void) const; - float toFloat(void) const; - double toDouble(void) const; + i64 toInt(void) const; + f32 toFloat(void) const; + f64 toDouble(void) const; bool isNumeric(bool decimal = false) const; bool isInt(void) const; bool isHex(void) const; @@ -165,22 +165,22 @@ namespace ostd bool startsWith(const String& str) const; bool endsWith(const String& str) const; bool regexMatches(const String& regex_pattern, bool case_insensitive = false) const; - uint32_t count(const String& str) const; - int32_t indexOf(char c, uint32_t start = 0) const; - int32_t indexOf(const String& str, uint32_t start = 0) const; - int32_t lastIndexOf(char c) const; - int32_t lastIndexOf(const String& str) const; + u32 count(const String& str) const; + i32 indexOf(char c, u32 start = 0) const; + i32 indexOf(const String& str, u32 start = 0) const; + i32 lastIndexOf(char c) const; + i32 lastIndexOf(const String& str) const; Tokens tokenize(const String& delimiter = " ", bool trim_tokens = true, bool allow_white_space_only_tokens = false) const; - static String getHexStr(uint64_t value, bool prefix = true, uint8_t nbytes = 1); - static String getBinStr(uint64_t value, bool prefix = true, uint8_t nbytes = 1); - static String duplicateChar(unsigned char c, uint16_t count); - static std::vector decodeUTF8(const ostd::String& s); + static String getHexStr(u64 value, bool prefix = true, u8 nbytes = 1); + static String getBinStr(u64 value, bool prefix = true, u8 nbytes = 1); + static String duplicateChar(uchar c, u16 count); + static stdvec decodeUTF8(const String& s); friend std::ostream& operator<<(std::ostream& out, const String& val); private: - static uint32_t utf8_next(const char*& p, const char* end); + static u32 utf8_next(const char*& p, const char* end); private: ostd::cpp_string m_data; @@ -201,12 +201,12 @@ namespace ostd } } - +using String = ostd::String; template <> -struct std::hash +struct std::hash { - std::size_t operator()(const ostd::String& str) const + std::size_t operator()(const String& str) const { hash hasher; return hasher(str.cpp_str()); diff --git a/src/ostd/string/TextStyleParser.cpp b/src/ostd/string/TextStyleParser.cpp index 233bc20..058ee6d 100644 --- a/src/ostd/string/TextStyleParser.cpp +++ b/src/ostd/string/TextStyleParser.cpp @@ -7,7 +7,7 @@ namespace ostd { if (!str.validate()) return os; ostd::ConsoleOutputHandler out; - for (int32_t i = 0; i < str.text.len(); i++) + for (i32 i = 0; i < str.text.len(); i++) out.bg(str.backgroundColors[i].consoleColor).fg(str.foregroundColors[i].consoleColor).pChar(str.text[i]); out.reset(); return os; @@ -33,7 +33,7 @@ namespace ostd text += str; background.background = true; foreground.background = false; - for (int32_t i = 0; i < str.len(); i++) + for (i32 i = 0; i < str.len(); i++) { backgroundColors.push_back(background); foregroundColors.push_back(foreground); @@ -55,7 +55,7 @@ namespace ostd tStyledString rstring; bool insideBlock = false; bool validBlockStart = false; - int32_t countBlockStart = 0; + i32 countBlockStart = 0; defaultBackgorundColor.background = true; defaultForegroundColor.background = false; s_defaultBackgroundColor = defaultBackgorundColor; @@ -64,7 +64,7 @@ namespace ostd tColor bgcol = defaultBackgorundColor; String blockText = ""; String _styledString = String(styledString).trim(); - for (int32_t i = 0; i < _styledString.len(); i++) + for (i32 i = 0; i < _styledString.len(); i++) { char c = _styledString[i]; if (c == '[') @@ -223,70 +223,70 @@ namespace ostd return *this; } - TextStyleBuilder::Console& TextStyleBuilder::Console::add(uint8_t i) + TextStyleBuilder::Console& TextStyleBuilder::Console::add(u8 i) { String edit(""); edit.add(i); return add(edit); } - TextStyleBuilder::Console& TextStyleBuilder::Console::add(int8_t i) + TextStyleBuilder::Console& TextStyleBuilder::Console::add(i8 i) { String edit(""); edit.add(i); return add(edit); } - TextStyleBuilder::Console& TextStyleBuilder::Console::add(uint16_t i) + TextStyleBuilder::Console& TextStyleBuilder::Console::add(u16 i) { String edit(""); edit.add(i); return add(edit); } - TextStyleBuilder::Console& TextStyleBuilder::Console::add(int16_t i) + TextStyleBuilder::Console& TextStyleBuilder::Console::add(i16 i) { String edit(""); edit.add(i); return add(edit); } - TextStyleBuilder::Console& TextStyleBuilder::Console::add(uint32_t i) + TextStyleBuilder::Console& TextStyleBuilder::Console::add(u32 i) { String edit(""); edit.add(i); return add(edit); } - TextStyleBuilder::Console& TextStyleBuilder::Console::add(int32_t i) + TextStyleBuilder::Console& TextStyleBuilder::Console::add(i32 i) { String edit(""); edit.add(i); return add(edit); } - TextStyleBuilder::Console& TextStyleBuilder::Console::add(uint64_t i) + TextStyleBuilder::Console& TextStyleBuilder::Console::add(u64 i) { String edit(""); edit.add(i); return add(edit); } - TextStyleBuilder::Console& TextStyleBuilder::Console::add(int64_t i) + TextStyleBuilder::Console& TextStyleBuilder::Console::add(i64 i) { String edit(""); edit.add(i); return add(edit); } - TextStyleBuilder::Console& TextStyleBuilder::Console::add(float f) + TextStyleBuilder::Console& TextStyleBuilder::Console::add(f32 f) { String edit(""); edit.add(f); return add(edit); } - TextStyleBuilder::Console& TextStyleBuilder::Console::add(double f) + TextStyleBuilder::Console& TextStyleBuilder::Console::add(f64 f) { String edit(""); edit.add(f); diff --git a/src/ostd/string/TextStyleParser.hpp b/src/ostd/string/TextStyleParser.hpp index c0b6040..ca8d12b 100644 --- a/src/ostd/string/TextStyleParser.hpp +++ b/src/ostd/string/TextStyleParser.hpp @@ -37,8 +37,8 @@ namespace ostd public: struct tStyledString { String text { "" }; - std::vector backgroundColors; - std::vector foregroundColors; + stdvec backgroundColors; + stdvec foregroundColors; void add(const String& str, tColor background, tColor foreground); bool validate(void) const; @@ -71,9 +71,9 @@ namespace ostd friend std::ostream& operator<<(std::ostream&, IRichStringBase const&); inline void setDefaultBackgroundColor(TextStyleParser::tColor color) { m_defaultBackgroundColor = color; } - inline void setDefaultBackgroundColor(Color color) { m_defaultBackgroundColor = { color, "", true }; } + inline void setDefaultBackgroundColor(const Color& color) { m_defaultBackgroundColor = { color, "", true }; } inline void setDefaultForegroundColor(TextStyleParser::tColor color) { m_defaultForegroundColor = color; } - inline void setDefaultForegroundColor(Color color) { m_defaultForegroundColor = { color, "", true }; } + inline void setDefaultForegroundColor(const Color& color) { m_defaultForegroundColor = { color, "", true }; } inline TextStyleParser::tColor getDefaultBackgroundColor(void) { return m_defaultBackgroundColor; } inline TextStyleParser::tColor getDefaultForegroundColor(void) { return m_defaultForegroundColor; } @@ -90,16 +90,16 @@ namespace ostd Console& fg(const String& consoleColor); Console& clr(void); Console& add(const String& text); - Console& add(uint8_t i); - Console& add(int8_t i); - Console& add(uint16_t i); - Console& add(int16_t i); - Console& add(uint32_t i); - Console& add(int32_t i); - Console& add(uint64_t i); - Console& add(int64_t i); - Console& add(float f); - Console& add(double f); + Console& add(u8 i); + Console& add(i8 i); + Console& add(u16 i); + Console& add(i16 i); + Console& add(u32 i); + Console& add(i32 i); + Console& add(u64 i); + Console& add(i64 i); + Console& add(f32 f); + Console& add(f64 f); Console& addc(char c); Console& print(OutputHandlerBase& out); diff --git a/src/ostd/utils/Defines.hpp b/src/ostd/utils/Defines.hpp index 120c73e..5cb93a0 100755 --- a/src/ostd/utils/Defines.hpp +++ b/src/ostd/utils/Defines.hpp @@ -55,5 +55,5 @@ #define OX_RELEASE_BUILD #endif #else - #define _DEBUG(n) std::cout << (int)n << "\n"; + #define _DEBUG(n) std::cout << (i32)n << "\n"; #endif diff --git a/src/ostd/utils/Hash.cpp b/src/ostd/utils/Hash.cpp index 67a1e39..f8b50e6 100644 --- a/src/ostd/utils/Hash.cpp +++ b/src/ostd/utils/Hash.cpp @@ -27,61 +27,61 @@ // Rotation amounts namespace { - constexpr uint32_t S11 = 7; - constexpr uint32_t S12 = 12; - constexpr uint32_t S13 = 17; - constexpr uint32_t S14 = 22; - constexpr uint32_t S21 = 5; - constexpr uint32_t S22 = 9; - constexpr uint32_t S23 = 14; - constexpr uint32_t S24 = 20; - constexpr uint32_t S31 = 4; - constexpr uint32_t S32 = 11; - constexpr uint32_t S33 = 16; - constexpr uint32_t S34 = 23; - constexpr uint32_t S41 = 6; - constexpr uint32_t S42 = 10; - constexpr uint32_t S43 = 15; - constexpr uint32_t S44 = 21; + constexpr u32 S11 = 7; + constexpr u32 S12 = 12; + constexpr u32 S13 = 17; + constexpr u32 S14 = 22; + constexpr u32 S21 = 5; + constexpr u32 S22 = 9; + constexpr u32 S23 = 14; + constexpr u32 S24 = 20; + constexpr u32 S31 = 4; + constexpr u32 S32 = 11; + constexpr u32 S33 = 16; + constexpr u32 S34 = 23; + constexpr u32 S41 = 6; + constexpr u32 S42 = 10; + constexpr u32 S43 = 15; + constexpr u32 S44 = 21; - inline uint32_t F(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (~x & z); } - inline uint32_t G(uint32_t x, uint32_t y, uint32_t z) { return (x & z) | (y & ~z); } - inline uint32_t H(uint32_t x, uint32_t y, uint32_t z) { return x ^ y ^ z; } - inline uint32_t I(uint32_t x, uint32_t y, uint32_t z) { return y ^ (x | ~z); } + inline u32 F(u32 x, u32 y, u32 z) { return (x & y) | (~x & z); } + inline u32 G(u32 x, u32 y, u32 z) { return (x & z) | (y & ~z); } + inline u32 H(u32 x, u32 y, u32 z) { return x ^ y ^ z; } + inline u32 I(u32 x, u32 y, u32 z) { return y ^ (x | ~z); } - inline uint32_t rotate_left(uint32_t x, uint32_t n) { return (x << n) | (x >> (32 - n)); } + inline u32 rotate_left(u32 x, u32 n) { return (x << n) | (x >> (32 - n)); } - inline void FF(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) { + inline void FF(u32& a, u32 b, u32 c, u32 d, u32 x, u32 s, u32 ac) { a += F(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } - inline void GG(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) { + inline void GG(u32& a, u32 b, u32 c, u32 d, u32 x, u32 s, u32 ac) { a += G(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } - inline void HH(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) { + inline void HH(u32& a, u32 b, u32 c, u32 d, u32 x, u32 s, u32 ac) { a += H(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } - inline void II(uint32_t& a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) { + inline void II(u32& a, u32 b, u32 c, u32 d, u32 x, u32 s, u32 ac) { a += I(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } } -ostd::String ostd::Hash::md5(const ostd::String& _str) { +String ostd::Hash::md5(const String& _str) { std::string str = _str.cpp_str(); // Initial state (RFC 1321) - uint32_t state[4] = { + u32 state[4] = { 0x67452301u, 0xefcdab89u, 0x98badcfeu, 0x10325476u }; // Process input in 64-byte blocks - const uint8_t* input = reinterpret_cast(str.data()); + const u8* input = reinterpret_cast(str.data()); size_t inputLen = str.size(); // Process full 64-byte chunks @@ -91,7 +91,7 @@ ostd::String ostd::Hash::md5(const ostd::String& _str) { } // Buffer for remaining bytes + padding + length - uint8_t buffer[64]; + u8 buffer[64]; size_t rem = inputLen - i; std::memset(buffer, 0, sizeof(buffer)); if (rem > 0) { @@ -113,32 +113,32 @@ ostd::String ostd::Hash::md5(const ostd::String& _str) { } // Append original length in bits, little-endian - uint64_t bitLen = static_cast(inputLen) * 8ull; - for (int j = 0; j < 8; ++j) { - buffer[56 + j] = static_cast((bitLen >> (8 * j)) & 0xFF); + u64 bitLen = cast(inputLen) * 8ull; + for (i32 j = 0; j < 8; ++j) { + buffer[56 + j] = cast((bitLen >> (8 * j)) & 0xFF); } // Final transform __md5_transform(buffer, state); // Output digest (little-endian) - uint8_t digest[16]; + u8 digest[16]; __md5_encode(digest, state, 16); std::ostringstream oss; oss << std::hex << std::setfill('0'); - for (int j = 0; j < 16; ++j) { - oss << std::setw(2) << static_cast(digest[j]); + for (i32 j = 0; j < 16; ++j) { + oss << std::setw(2) << cast(digest[j]); } return oss.str(); } -void ostd::Hash::__md5_transform(const uint8_t block[64], uint32_t state[4]) { - uint32_t a = state[0]; - uint32_t b = state[1]; - uint32_t c = state[2]; - uint32_t d = state[3]; - uint32_t x[16]; +void ostd::Hash::__md5_transform(const u8 block[64], u32 state[4]) { + u32 a = state[0]; + u32 b = state[1]; + u32 c = state[2]; + u32 d = state[3]; + u32 x[16]; __md5_decode(x, block, 64); @@ -220,22 +220,22 @@ void ostd::Hash::__md5_transform(const uint8_t block[64], uint32_t state[4]) { state[3] += d; } -void ostd::Hash::__md5_encode(uint8_t* output, const uint32_t* input, size_t len) { +void ostd::Hash::__md5_encode(u8* output, const u32* input, size_t len) { // Convert 32-bit words to bytes (little-endian) for (size_t i = 0, j = 0; j < len; ++i, j += 4) { - output[j + 0] = static_cast( input[i] & 0xFF); - output[j + 1] = static_cast((input[i] >> 8) & 0xFF); - output[j + 2] = static_cast((input[i] >> 16) & 0xFF); - output[j + 3] = static_cast((input[i] >> 24) & 0xFF); + output[j + 0] = cast( input[i] & 0xFF); + output[j + 1] = cast((input[i] >> 8) & 0xFF); + output[j + 2] = cast((input[i] >> 16) & 0xFF); + output[j + 3] = cast((input[i] >> 24) & 0xFF); } } -void ostd::Hash::__md5_decode(uint32_t* output, const uint8_t* input, size_t len) { +void ostd::Hash::__md5_decode(u32* output, const u8* input, size_t len) { // Convert bytes to 32-bit words (little-endian) for (size_t i = 0, j = 0; j < len; ++i, j += 4) { - output[i] = static_cast(input[j + 0]) - | (static_cast(input[j + 1]) << 8) - | (static_cast(input[j + 2]) << 16) - | (static_cast(input[j + 3]) << 24); + output[i] = cast(input[j + 0]) + | (cast(input[j + 1]) << 8) + | (cast(input[j + 2]) << 16) + | (cast(input[j + 3]) << 24); } } diff --git a/src/ostd/utils/Hash.hpp b/src/ostd/utils/Hash.hpp index 5f70de2..3263217 100644 --- a/src/ostd/utils/Hash.hpp +++ b/src/ostd/utils/Hash.hpp @@ -30,8 +30,8 @@ namespace ostd static String md5(const String& str); private: - static void __md5_transform(const uint8_t block[64], uint32_t state[4]); - static void __md5_encode(uint8_t* output, const uint32_t* input, size_t len); - static void __md5_decode(uint32_t* output, const uint8_t* input, size_t len); + static void __md5_transform(const u8 block[64], u32 state[4]); + static void __md5_encode(u8* output, const u32* input, size_t len); + static void __md5_decode(u32* output, const u8* input, size_t len); }; } diff --git a/src/ostd/utils/Logic.cpp b/src/ostd/utils/Logic.cpp index a95a783..d8586ac 100755 --- a/src/ostd/utils/Logic.cpp +++ b/src/ostd/utils/Logic.cpp @@ -1,21 +1,21 @@ /* - OmniaFramework - A collection of useful functionality - Copyright (C) 2025 OmniaX-Dev + OmniaFramework - A collection of useful functionality + Copyright (C) 2025 OmniaX-Dev - This file is part of OmniaFramework. + This file is part of OmniaFramework. - OmniaFramework is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + OmniaFramework is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - OmniaFramework is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + OmniaFramework is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with OmniaFramework. If not, see . + You should have received a copy of the GNU General Public License + along with OmniaFramework. If not, see . */ #include "Logic.hpp" @@ -26,28 +26,27 @@ namespace ostd { - bool LogicEvaluator::eval(String exp) + bool LogicEvaluator::eval(const String& _exp) { - String se(exp); - se = se.replaceAll("true", "1"); - se = se.replaceAll("false", "0"); - se = se.replaceAll("and", "&"); - se = se.replaceAll("or", "+"); - se = se.replaceAll("xor", "^"); - se = se.replaceAll("nand", "%"); - se = se.replaceAll("nor", "*"); - se = se.replaceAll("xnor", ">"); - se = se.replaceAll("not", "!"); - se = se.replaceAll(" ", ""); - se = se.replaceAll("!1", "0"); - se = se.replaceAll("!0", "1"); - se = se.trim(); - exp = se; + String exp(_exp); + exp.replaceAll("true", "1"); + exp.replaceAll("false", "0"); + exp.replaceAll("and", "&"); + exp.replaceAll("or", "+"); + exp.replaceAll("xor", "^"); + exp.replaceAll("nand", "%"); + exp.replaceAll("nor", "*"); + exp.replaceAll("xnor", ">"); + exp.replaceAll("not", "!"); + exp.replaceAll(" ", ""); + exp.replaceAll("!1", "0"); + exp.replaceAll("!0", "1"); + exp.trim(); std::stack values; std::stack ops; char c = 0; - for (unsigned int i = 0; i < exp.len(); i++) + for (u32 i = 0; i < exp.len(); i++) { c = exp[i]; if (c == ' ' || c == '#') continue; diff --git a/src/ostd/utils/Logic.hpp b/src/ostd/utils/Logic.hpp index 2486b21..6c12790 100755 --- a/src/ostd/utils/Logic.hpp +++ b/src/ostd/utils/Logic.hpp @@ -43,7 +43,7 @@ namespace ostd class LogicEvaluator { public: - static bool eval(String exp); + static bool eval(const String& exp); private: static bool applyOp(bool a, bool b, eLogicOp op); diff --git a/src/ostd/utils/PathFinder.cpp b/src/ostd/utils/PathFinder.cpp index 788e857..e7fc4ab 100755 --- a/src/ostd/utils/PathFinder.cpp +++ b/src/ostd/utils/PathFinder.cpp @@ -4,7 +4,7 @@ namespace ostd { - KeyNode::KeyNode(int32_t xx, int32_t yy, float f) + KeyNode::KeyNode(i32 xx, i32 yy, f32 f) { x = xx; y = yy; @@ -56,12 +56,12 @@ namespace ostd return false; } - const KeyNode& OpenSet::operator[](uint32_t index) const + const KeyNode& OpenSet::operator[](u32 index) const { return m_list[index]; } - int32_t OpenSet::size(void) const + i32 OpenSet::size(void) const { return m_list.size(); } @@ -71,7 +71,7 @@ namespace ostd remove(m_lowest_index); } - void OpenSet::remove(uint32_t index) + void OpenSet::remove(u32 index) { if (isEmpty() || index >= size()) return; if (size() == 1) @@ -84,7 +84,7 @@ namespace ostd { m_lowest = &m_list[0]; m_lowest_index = 0; - for (uint32_t i = 1; i < m_list.size(); i++) + for (u32 i = 1; i < m_list.size(); i++) { auto& k = m_list[i]; if (k.fscore < m_lowest->fscore) @@ -108,7 +108,7 @@ namespace ostd return *m_lowest; } - int32_t OpenSet::getLowestIndex(void) + i32 OpenSet::getLowestIndex(void) { return m_lowest_index; } @@ -120,7 +120,7 @@ namespace ostd init(32, 32); } - void PathFinder::init(int32_t w, int32_t h, eHeuristicType ht) + void PathFinder::init(i32 w, i32 h, eHeuristicType ht) { m_initialized = true; openSet.clear(); @@ -130,21 +130,21 @@ namespace ostd __ht = ht; m_width = w; m_height = h; - for (int32_t y = 0; y < h; y++) + for (i32 y = 0; y < h; y++) { - for (int32_t x = 0; x < w; x++) + for (i32 x = 0; x < w; x++) { - gscores[{x, y, 0}] = std::numeric_limits::infinity(); + gscores[{x, y, 0}] = std::numeric_limits::infinity(); } } } - void PathFinder::setObstacle(int32_t x, int32_t y, bool obst) + void PathFinder::setObstacle(i32 x, i32 y, bool obst) { obstacle[{x, y, 0}] = obst; } - void PathFinder::setKeyPoints(int32_t startx, int32_t starty, int32_t endx, int32_t endy) + void PathFinder::setKeyPoints(i32 startx, i32 starty, i32 endx, i32 endy) { if (!m_initialized) return; init(m_width, m_height, __ht); @@ -173,13 +173,13 @@ namespace ostd return path; } openSet.removeLowest(); - int32_t tmpx = current.x; - int32_t tmpy = current.y; - float tg = 0; + i32 tmpx = current.x; + i32 tmpy = current.y; + f32 tg = 0; KeyNode neighbor; - for (int8_t x = -1; x <= 1; x++) + for (i8 x = -1; x <= 1; x++) { - for (int8_t y = -1; y <= 1; y++) + for (i8 y = -1; y <= 1; y++) { if (x == 0 && y == 0) continue; if (tmpx + x < 0 || tmpx + x >= m_width || tmpy + y < 0 || tmpy + y >= m_height) continue; @@ -201,13 +201,13 @@ namespace ostd return std::deque(); } - float PathFinder::heuristics(KeyNode n) + f32 PathFinder::heuristics(KeyNode n) { - float hh = 0; + f32 hh = 0; switch (__ht) { case eHeuristicType::Euclidean: - hh = (float)std::sqrt(std::pow(n.x - __goal.x, 2) + std::pow(n.y - __goal.y, 2)); + hh = (f32)std::sqrt(std::pow(n.x - __goal.x, 2) + std::pow(n.y - __goal.y, 2)); break; case eHeuristicType::Manhattan: hh = std::abs(n.x - __goal.x) + std::abs(n.y - __goal.y); diff --git a/src/ostd/utils/PathFinder.hpp b/src/ostd/utils/PathFinder.hpp index b629b4c..4473def 100755 --- a/src/ostd/utils/PathFinder.hpp +++ b/src/ostd/utils/PathFinder.hpp @@ -1,29 +1,28 @@ /* - OmniaFramework - A collection of useful functionality - Copyright (C) 2025 OmniaX-Dev + OmniaFramework - A collection of useful functionality + Copyright (C) 2025 OmniaX-Dev - This file is part of OmniaFramework. + This file is part of OmniaFramework. - OmniaFramework is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + OmniaFramework is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - OmniaFramework is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + OmniaFramework is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with OmniaFramework. If not, see . + You should have received a copy of the GNU General Public License + along with OmniaFramework. If not, see . */ #pragma once -#include #include #include -#include +#include #include namespace ostd @@ -37,11 +36,11 @@ namespace ostd struct KeyNode { - int32_t x; - int32_t y; - float fscore; + i32 x; + i32 y; + f32 fscore; - KeyNode(int32_t xx = 0, int32_t yy = 0, float f = 0.0f); + KeyNode(i32 xx = 0, i32 yy = 0, f32 f = 0.0f); bool operator==(const KeyNode &other) const; bool operator<(const KeyNode &other) const; @@ -57,17 +56,17 @@ namespace ostd bool isEmpty(void) const; void push(const KeyNode& k); bool contains(const KeyNode& k); - const KeyNode& operator[](uint32_t index) const; - int32_t size(void) const; + const KeyNode& operator[](u32 index) const; + i32 size(void) const; void removeLowest(void); - void remove(uint32_t index); + void remove(u32 index); void clear(void); KeyNode& getLowest(void); - int32_t getLowestIndex(void); + i32 getLowestIndex(void); private: - int32_t m_lowest_index; - std::vector m_list; + i32 m_lowest_index; + stdvec m_list; KeyNode* m_lowest; }; @@ -75,16 +74,16 @@ namespace ostd { public: PathFinder(void); - void init(int32_t w, int32_t h, eHeuristicType ht = eHeuristicType::Euclidean); - void setObstacle(int32_t x, int32_t y, bool obst = true); - void setKeyPoints(int32_t startx, int32_t starty, int32_t endx, int32_t endy); + void init(i32 w, i32 h, eHeuristicType ht = eHeuristicType::Euclidean); + void setObstacle(i32 x, i32 y, bool obst = true); + void setKeyPoints(i32 startx, i32 starty, i32 endx, i32 endy); std::deque findPath(void); private: - float heuristics(KeyNode n); + f32 heuristics(KeyNode n); private: - std::unordered_map gscores; + std::unordered_map gscores; std::unordered_map pathMap; std::unordered_map obstacle; OpenSet openSet; @@ -93,8 +92,8 @@ namespace ostd KeyNode __goal; eHeuristicType __ht; - int32_t m_width; - int32_t m_height; + i32 m_width; + i32 m_height; bool m_initialized; }; diff --git a/src/ostd/utils/QuadTree.cpp b/src/ostd/utils/QuadTree.cpp index 535bc3d..b2bfaa8 100755 --- a/src/ostd/utils/QuadTree.cpp +++ b/src/ostd/utils/QuadTree.cpp @@ -32,7 +32,7 @@ namespace ostd setValid(false); } - void QuadTree::create(Rectangle bounds, uint16_t capacity) + void QuadTree::create(Rectangle bounds, u16 capacity) { m_bounds = bounds; m_capacity = capacity; @@ -89,11 +89,11 @@ namespace ostd return false; } - void QuadTree::query(Rectangle range, std::vector& list) + void QuadTree::query(Rectangle range, stdvec& list) { if (!m_bounds.intersects(range, true)) return; - for (uint16_t i = 0; i < m_currentSize; i++) + for (u16 i = 0; i < m_currentSize; i++) { auto& elem = m_points[i]; if (range.contains({ elem.pos.x, elem.pos.y })) diff --git a/src/ostd/utils/QuadTree.hpp b/src/ostd/utils/QuadTree.hpp index e8e58d8..0f626d9 100755 --- a/src/ostd/utils/QuadTree.hpp +++ b/src/ostd/utils/QuadTree.hpp @@ -20,7 +20,6 @@ #pragma once -#include #include #include #include @@ -41,18 +40,18 @@ namespace ostd m_se(nullptr),m_ne(nullptr), m_subdivided(false), m_capacity(0), m_currentSize(0) { invalidate(); } - inline QuadTree(Rectangle bounds, uint16_t capacity) { create(bounds, capacity); } + inline QuadTree(Rectangle bounds, u16 capacity) { create(bounds, capacity); } inline ~QuadTree(void) { destroy(); } void destroy(void); - void create(Rectangle bounds, uint16_t capacity); + void create(Rectangle bounds, u16 capacity); void subdivide(void); bool insert(Vec2 point, void* data = nullptr); - void query(Rectangle range, std::vector& list); + void query(Rectangle range, stdvec& list); private: tElement* m_points; - uint16_t m_currentSize; - uint16_t m_capacity; + u16 m_currentSize; + u16 m_capacity; Rectangle m_bounds; bool m_subdivided; std::unique_ptr m_nw; diff --git a/src/ostd/utils/Signals.cpp b/src/ostd/utils/Signals.cpp index 22def90..4f080ab 100755 --- a/src/ostd/utils/Signals.cpp +++ b/src/ostd/utils/Signals.cpp @@ -1,5 +1,6 @@ #include "Signals.hpp" #include "../data/BaseObject.hpp" +#include "io/Memory.hpp" namespace ostd { @@ -20,7 +21,7 @@ namespace ostd m_DelegateRecievers.clear(); } - void SignalHandler::emitSignal(uint32_t signal_id, uint8_t prio, BaseObject& userData) + void SignalHandler::emitSignal(u32 signal_id, u8 prio, BaseObject& userData) { if (prio == Signal::Priority::Normal) { @@ -37,8 +38,16 @@ namespace ostd } } - void SignalHandler::connect(BaseObject& object, uint32_t signal_id) + void SignalHandler::connect(BaseObject& object, u32 signal_id) { m_recievers[signal_id].push_back(&object); } + + void SignalHandler::disconnect(BaseObject& object, u32 signal_id) + { + auto it = m_recievers.find(signal_id); + if (it == m_recievers.end()) + return; + STDVEC_REMOVE(it->second, &object); + } } diff --git a/src/ostd/utils/Signals.hpp b/src/ostd/utils/Signals.hpp index 946c380..b2dc09a 100755 --- a/src/ostd/utils/Signals.hpp +++ b/src/ostd/utils/Signals.hpp @@ -1,96 +1,97 @@ /* - OmniaFramework - A collection of useful functionality - Copyright (C) 2025 OmniaX-Dev + OmniaFramework - A collection of useful functionality + Copyright (C) 2025 OmniaX-Dev - This file is part of OmniaFramework. + This file is part of OmniaFramework. - OmniaFramework is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + OmniaFramework is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - OmniaFramework is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + OmniaFramework is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with OmniaFramework. If not, see . + You should have received a copy of the GNU General Public License + along with OmniaFramework. If not, see . */ #pragma once #include #include -#include -#include + + namespace ostd { struct BuiltinSignals { - inline static constexpr uint32_t NoSignal = 0x0000; + inline static constexpr u32 NoSignal = 0x0000; /** Builtin Signals **/ - inline static constexpr uint32_t KeyPressed = 0x0001; - inline static constexpr uint32_t KeyReleased = 0x0002; - inline static constexpr uint32_t MousePressed = 0x0003; - inline static constexpr uint32_t MouseReleased = 0x0004; - inline static constexpr uint32_t MouseMoved = 0x0005; - inline static constexpr uint32_t MouseDragged = 0x0006; - inline static constexpr uint32_t TextEntered = 0x0007; - inline static constexpr uint32_t MouseScrolled = 0x0008; + inline static constexpr u32 KeyPressed = 0x0001; + inline static constexpr u32 KeyReleased = 0x0002; + inline static constexpr u32 MousePressed = 0x0003; + inline static constexpr u32 MouseReleased = 0x0004; + inline static constexpr u32 MouseMoved = 0x0005; + inline static constexpr u32 MouseDragged = 0x0006; + inline static constexpr u32 TextEntered = 0x0007; + inline static constexpr u32 MouseScrolled = 0x0008; - inline static constexpr uint32_t OnGuiEvent = 0x2001; - inline static constexpr uint32_t FileDragAndDropped = 0x2002; - inline static constexpr uint32_t TextDragAndDropped = 0x2003; + inline static constexpr u32 OnGuiEvent = 0x2001; + inline static constexpr u32 FileDragAndDropped = 0x2002; + inline static constexpr u32 TextDragAndDropped = 0x2003; - inline static constexpr uint32_t BeforeSDLShutdown = 0x3001; + inline static constexpr u32 BeforeSDLShutdown = 0x3001; - inline static constexpr uint32_t WindowResized = 0x1001; - inline static constexpr uint32_t WindowClosed = 0x1002; - inline static constexpr uint32_t WindowFocused = 0x1003; - inline static constexpr uint32_t WindowLostFocus = 0x1004; + inline static constexpr u32 WindowResized = 0x1001; + inline static constexpr u32 WindowClosed = 0x1002; + inline static constexpr u32 WindowFocused = 0x1003; + inline static constexpr u32 WindowLostFocus = 0x1004; /*********************/ - inline static constexpr uint32_t CustomSignalBase = 0xFF0000; + inline static constexpr u32 CustomSignalBase = 0xFF0000; }; struct Signal { struct Priority { - inline static constexpr uint8_t RealTime = 0; - inline static constexpr uint8_t Normal = 1; + inline static constexpr u8 RealTime = 0; + inline static constexpr u8 Normal = 1; }; - const uint8_t priority; - const uint32_t ID; + const u8 priority; + const u32 ID; bool handled { false }; BaseObject& userData; - inline Signal(uint32_t id, BaseObject& _userData = BaseObject::InvalidRef(), uint8_t prio = Signal::Priority::Normal) : priority(prio), ID(id), userData(_userData) { } + inline Signal(u32 id, BaseObject& _userData = BaseObject::InvalidRef(), u8 prio = Signal::Priority::Normal) : priority(prio), ID(id), userData(_userData) { } }; class SignalHandler { private: struct DelegateSignal { - uint32_t id; + u32 id; BaseObject& ud; - inline DelegateSignal(uint32_t _id, BaseObject& _ud) : id(_id), ud(_ud) { } + inline DelegateSignal(u32 _id, BaseObject& _ud) : id(_id), ud(_ud) { } }; public: static void init(bool allow_reinit = false); static void handleDelegateSignals(void); - static void emitSignal(uint32_t signal_id, uint8_t prio = Signal::Priority::RealTime, BaseObject& userData = BaseObject::InvalidRef()); - static void connect(BaseObject& object, uint32_t signal_id); - inline static uint32_t newCustomSignal(uint32_t sub_id) { return BuiltinSignals::CustomSignalBase + sub_id; } + static void emitSignal(u32 signal_id, u8 prio = Signal::Priority::RealTime, BaseObject& userData = BaseObject::InvalidRef()); + static void connect(BaseObject& object, u32 signal_id); + static void disconnect(BaseObject& object, u32 signal_id); + inline static u32 newCustomSignal(u32 sub_id) { return BuiltinSignals::CustomSignalBase + sub_id; } private: - inline static std::unordered_map> m_recievers; - inline static std::vector m_DelegateRecievers; - inline static constexpr uint16_t __SIGNAL_BUFFER_START_SIZE { 2048 }; - inline static constexpr uint16_t __DELEGATE_SIGNALS_BUFFER_START_SIZE { 2048 }; + inline static stdumap> m_recievers; + inline static stdvec m_DelegateRecievers; + inline static constexpr u16 __SIGNAL_BUFFER_START_SIZE { 2048 }; + inline static constexpr u16 __DELEGATE_SIGNALS_BUFFER_START_SIZE { 2048 }; inline static bool m_initialized { false }; }; } diff --git a/src/ostd/utils/Time.cpp b/src/ostd/utils/Time.cpp index 148ff0e..713e3b6 100644 --- a/src/ostd/utils/Time.cpp +++ b/src/ostd/utils/Time.cpp @@ -20,10 +20,10 @@ namespace ostd m_totalSeconds = 0.0f; } - const float& GameClock::start(void) + const f32& GameClock::start(void) { m_rtClock.start(false, "", eTimeUnits::Seconds); - m_timeOfDay = CAP((1.0f / ((float)(TM_G_MINUTES_FOR_G_HOUR * TM_G_HOURS_FOR_G_DAY))) * ((hours * TM_G_MINUTES_FOR_G_HOUR) + (minutes)), 1.0f); + m_timeOfDay = CAP((1.0f / ((f32)(TM_G_MINUTES_FOR_G_HOUR * TM_G_HOURS_FOR_G_DAY))) * ((hours * TM_G_MINUTES_FOR_G_HOUR) + (minutes)), 1.0f); return m_timeOfDay; } @@ -31,13 +31,13 @@ namespace ostd { std::ostringstream ss; ss << "Time: " << getFormattedTime() << " / "; - ss << (int32_t)(days + 1) << " " << convertMonth() << " " << (int32_t)(years); + ss << (i32)(days + 1) << " " << convertMonth() << " " << (i32)(years); return String(ss.str()); } void GameClock::update(void) { - int64_t elapsed = m_rtClock.start(false, "", eTimeUnits::Seconds); + i64 elapsed = m_rtClock.start(false, "", eTimeUnits::Seconds); if (hours == 255) hours = TM_G_HOURS_FOR_G_DAY - 1; else if (hours >= TM_G_HOURS_FOR_G_DAY) @@ -51,26 +51,26 @@ namespace ostd if (hours >= TM_G_HOURS_FOR_G_DAY) { days++; - if ((months == (uint8_t)eMonths::January || months == (uint8_t)eMonths::March || - months == (uint8_t)eMonths::May || months == (uint8_t)eMonths::July || - months == (uint8_t)eMonths::August || months == (uint8_t)eMonths::October || - months == (uint8_t)eMonths::December) && days >= TM_G_DAYS_FOR_G_LONG_MONTH) + if ((months == (u8)eMonths::January || months == (u8)eMonths::March || + months == (u8)eMonths::May || months == (u8)eMonths::July || + months == (u8)eMonths::August || months == (u8)eMonths::October || + months == (u8)eMonths::December) && days >= TM_G_DAYS_FOR_G_LONG_MONTH) { months++; - if (months > (uint8_t)eMonths::December) + if (months > (u8)eMonths::December) { years++; - months = (uint8_t)eMonths::January; + months = (u8)eMonths::January; } days = 0; } - else if ((months == (uint8_t)eMonths::April || months == (uint8_t)eMonths::June || - months == (uint8_t)eMonths::September || months == (uint8_t)eMonths::November) && days >= TM_G_DAYS_FOR_G_MEDIUM_MONTH) + else if ((months == (u8)eMonths::April || months == (u8)eMonths::June || + months == (u8)eMonths::September || months == (u8)eMonths::November) && days >= TM_G_DAYS_FOR_G_MEDIUM_MONTH) { months++; days = 0; } - else if (months == (uint8_t)eMonths::February) + else if (months == (u8)eMonths::February) { if ((years % 4 == 0 && days >= TM_G_DAYS_FOR_G_SHORT_MONTH + 1) || (years % 4 != 0 && days >= TM_G_DAYS_FOR_G_SHORT_MONTH)) @@ -85,16 +85,16 @@ namespace ostd } m_totalSeconds += elapsed; m_rtClock.start(false, "", eTimeUnits::Seconds); - m_timeOfDay = CAP((1.0f / ((float)(TM_G_MINUTES_FOR_G_HOUR * TM_G_HOURS_FOR_G_DAY))) * ((hours * TM_G_MINUTES_FOR_G_HOUR) + (minutes)), 1.0f); + m_timeOfDay = CAP((1.0f / ((f32)(TM_G_MINUTES_FOR_G_HOUR * TM_G_HOURS_FOR_G_DAY))) * ((hours * TM_G_MINUTES_FOR_G_HOUR) + (minutes)), 1.0f); } } String GameClock::getFormattedTime(void) { - bool zh = (int32_t)(hours / 10) < 1; - bool zm = (int32_t)(minutes / 10) < 1; + bool zh = (i32)(hours / 10) < 1; + bool zm = (i32)(minutes / 10) < 1; std::ostringstream ss; - ss << (zh ? "0" : "") << (int32_t)hours << ":" << (zm ? "0" : "") << (int32_t)minutes; + ss << (zh ? "0" : "") << (i32)hours << ":" << (zm ? "0" : "") << (i32)minutes; return String(ss.str()); } @@ -102,29 +102,29 @@ namespace ostd { switch (months) { - case (uint8_t)eMonths::January: + case (u8)eMonths::January: return "January"; - case (uint8_t)eMonths::February: + case (u8)eMonths::February: return "February"; - case (uint8_t)eMonths::March: + case (u8)eMonths::March: return "March"; - case (uint8_t)eMonths::April: + case (u8)eMonths::April: return "April"; - case (uint8_t)eMonths::May: + case (u8)eMonths::May: return "May"; - case (uint8_t)eMonths::June: + case (u8)eMonths::June: return "June"; - case (uint8_t)eMonths::July: + case (u8)eMonths::July: return "July"; - case (uint8_t)eMonths::August: + case (u8)eMonths::August: return "August"; - case (uint8_t)eMonths::September: + case (u8)eMonths::September: return "September"; - case (uint8_t)eMonths::October: + case (u8)eMonths::October: return "October"; - case (uint8_t)eMonths::November: + case (u8)eMonths::November: return "November"; - case (uint8_t)eMonths::December: + case (u8)eMonths::December: return "December"; default: break; @@ -154,43 +154,43 @@ namespace ostd return ss.str(); } - int32_t LocalTime::hours(void) const + i32 LocalTime::hours(void) const { __get_local_time(); return __now_t->tm_hour; } - int32_t LocalTime::minutes(void) const + i32 LocalTime::minutes(void) const { __get_local_time(); return __now_t->tm_min; } - int32_t LocalTime::seconds(void) const + i32 LocalTime::seconds(void) const { __get_local_time(); return __now_t->tm_sec; } - int32_t LocalTime::day(void) const + i32 LocalTime::day(void) const { __get_local_time(); return __now_t->tm_mday; } - int32_t LocalTime::month(void) const + i32 LocalTime::month(void) const { __get_local_time(); return __now_t->tm_mon + 1; } - int32_t LocalTime::year(void) const + i32 LocalTime::year(void) const { __get_local_time(); return __now_t->tm_year + 1900; } - int32_t LocalTime::weekDay(void) const + i32 LocalTime::weekDay(void) const { __get_local_time(); return __now_t->tm_wday; @@ -199,78 +199,78 @@ namespace ostd String LocalTime::shours(bool leading_zero) const { std::ostringstream ss; - int32_t h = hours(); + i32 h = hours(); if (leading_zero && h < 10) - ss << "0" << (int32_t)h; + ss << "0" << (i32)h; else - ss << (int32_t)h; + ss << (i32)h; return ss.str(); } String LocalTime::sminutes(bool leading_zero) const { std::ostringstream ss; - int32_t h = minutes(); + i32 h = minutes(); if (leading_zero && h < 10) - ss << "0" << (int32_t)h; + ss << "0" << (i32)h; else - ss << (int32_t)h; + ss << (i32)h; return ss.str(); } String LocalTime::sseconds(bool leading_zero) const { std::ostringstream ss; - int32_t h = seconds(); + i32 h = seconds(); if (leading_zero && h < 10) - ss << "0" << (int32_t)h; + ss << "0" << (i32)h; else - ss << (int32_t)h; + ss << (i32)h; return ss.str(); } String LocalTime::sday(bool leading_zero) const { std::ostringstream ss; - int32_t h = day(); + i32 h = day(); if (leading_zero && h < 10) - ss << "0" << (int32_t)h; + ss << "0" << (i32)h; else - ss << (int32_t)h; + ss << (i32)h; return ss.str(); } String LocalTime::smonth(bool leading_zero, bool month_name) const { - int32_t h = month(); + i32 h = month(); if (month_name) return monthToText(h); std::ostringstream ss; if (leading_zero && h < 10) - ss << "0" << (int32_t)h; + ss << "0" << (i32)h; else - ss << (int32_t)h; + ss << (i32)h; return ss.str(); } String LocalTime::syear(void) const { std::ostringstream ss; - int32_t h = year(); - ss << (int32_t)h; + i32 h = year(); + ss << (i32)h; return ss.str(); } String LocalTime::sWeekDay(bool day_name) const { - int32_t h = weekDay(); + i32 h = weekDay(); if (day_name) return weekDayToText(h); std::ostringstream ss; - ss << (int32_t)h; + ss << (i32)h; return ss.str(); } - String LocalTime::monthToText(int32_t month) const + String LocalTime::monthToText(i32 month) const { switch (month) { @@ -290,7 +290,7 @@ namespace ostd } } - String LocalTime::weekDayToText(int32_t day) const + String LocalTime::weekDayToText(i32 day) const { switch (day) { @@ -305,7 +305,7 @@ namespace ostd } } - String LocalTime_IT::monthToText(int32_t month) const + String LocalTime_IT::monthToText(i32 month) const { switch (month) { @@ -325,7 +325,7 @@ namespace ostd } } - String LocalTime_IT::weekDayToText(int32_t day) const + String LocalTime_IT::weekDayToText(i32 day) const { switch (day) { @@ -340,7 +340,7 @@ namespace ostd } } - String LocalTime_ES::monthToText(int32_t month) const + String LocalTime_ES::monthToText(i32 month) const { switch (month) { @@ -360,7 +360,7 @@ namespace ostd } } - String LocalTime_ES::weekDayToText(int32_t day) const + String LocalTime_ES::weekDayToText(i32 day) const { switch (day) { @@ -375,7 +375,7 @@ namespace ostd } } - String LocalTime_DE::monthToText(int32_t month) const + String LocalTime_DE::monthToText(i32 month) const { switch (month) { @@ -395,7 +395,7 @@ namespace ostd } } - String LocalTime_DE::weekDayToText(int32_t day) const + String LocalTime_DE::weekDayToText(i32 day) const { switch (day) { @@ -412,7 +412,7 @@ namespace ostd - uint64_t Timer::start(bool print, String name, eTimeUnits timeUnit, OutputHandlerBase* __destination) + u64 Timer::start(bool print, const String& name, eTimeUnits timeUnit, OutputHandlerBase* __destination) { m_timeUnit = timeUnit; m_started = true; @@ -459,7 +459,7 @@ namespace ostd return 0; } - uint64_t Timer::startCount(eTimeUnits timeUnit) + u64 Timer::startCount(eTimeUnits timeUnit) { m_timeUnit = timeUnit; m_started = true; @@ -483,12 +483,12 @@ namespace ostd return 0; } - uint64_t Timer::end(bool print) + u64 Timer::end(bool print) { if (!m_started) return 0; m_started = false; m_dest = nullptr; - int64_t diff; + i64 diff; String unit; switch (m_timeUnit) { @@ -537,11 +537,11 @@ namespace ostd return diff; } - uint64_t Timer::endCount(bool stop) + u64 Timer::endCount(bool stop) { if (!m_started) return 0; m_started = !stop; - int64_t diff; + i64 diff; switch (m_timeUnit) { case eTimeUnits::Nanoseconds: @@ -562,19 +562,19 @@ namespace ostd return diff; } - uint64_t Timer::restart(eTimeUnits timeUnit) + u64 Timer::restart(eTimeUnits timeUnit) { if (!m_started) { startCount(timeUnit); return 0; } - uint64_t elapsed = endCount(); + u64 elapsed = endCount(); startCount(timeUnit); return elapsed; } - uint64_t Timer::getEpoch(eTimeUnits timeUnit) + u64 Timer::getEpoch(eTimeUnits timeUnit) { switch (timeUnit) { @@ -597,7 +597,7 @@ namespace ostd - StepTimer& StepTimer::create(double updatesPerSecond, StepTimer::Callback callback) + StepTimer& StepTimer::create(f64 updatesPerSecond, StepTimer::Callback callback) { m_targetDt = 1.0 / updatesPerSecond; m_callback = std::move(callback); @@ -616,10 +616,10 @@ namespace ostd m_prevTime = currentTime; // Convert to seconds - double frameTime = std::chrono::duration(frameDuration).count(); + f64 frameTime = std::chrono::duration(frameDuration).count(); // Clamp to prevent spiral of death (5 FPS minimum) - constexpr double MAX_FRAME_TIME = 0.2; + constexpr f64 MAX_FRAME_TIME = 0.2; if (frameTime > MAX_FRAME_TIME) frameTime = MAX_FRAME_TIME; @@ -649,7 +649,7 @@ namespace ostd s_startTime_ms = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); } - void Time::sleep(uint32_t __time, eTimeUnits __unit) + void Time::sleep(u32 __time, eTimeUnits __unit) { switch (__unit) { @@ -669,16 +669,16 @@ namespace ostd } } - uint64_t Time::getRunningTime_ms(void) + u64 Time::getRunningTime_ms(void) { return std::chrono::duration_cast (std::chrono::system_clock::now().time_since_epoch()).count() - s_startTime_ms; } - String Time::secondsToFormattedString(int32_t totalSeconds) + String Time::secondsToFormattedString(i32 totalSeconds) { - int32_t hours = totalSeconds / 3600; - int32_t minutes = (totalSeconds % 3600) / 60; - int32_t seconds = totalSeconds % 60; + i32 hours = totalSeconds / 3600; + i32 minutes = (totalSeconds % 3600) / 60; + i32 seconds = totalSeconds % 60; String fmtstr = ""; fmtstr.add(String("").add(hours).addLeftPadding(2, '0')).add(":"); fmtstr.add(String("").add(minutes).addLeftPadding(2, '0')).add(":"); diff --git a/src/ostd/utils/Time.hpp b/src/ostd/utils/Time.hpp index 640ab1c..ec576d4 100644 --- a/src/ostd/utils/Time.hpp +++ b/src/ostd/utils/Time.hpp @@ -87,29 +87,29 @@ namespace ostd bool m_counting { false }; }; - typedef _Counter Counter; - typedef _Counter FloatCounter; - typedef _Counter DoubleCounter; + typedef _Counter Counter; + typedef _Counter FloatCounter; + typedef _Counter DoubleCounter; class OutputHandlerBase; class Timer { public: inline Timer(void) { m_started = false; m_current = 0; m_timeUnit = eTimeUnits::Nanoseconds; m_dest = nullptr; } - uint64_t start(bool print = true, String name = "", eTimeUnits timeUnit = eTimeUnits::Nanoseconds, OutputHandlerBase* __destination = nullptr); - uint64_t startCount(eTimeUnits timeUnit = eTimeUnits::Nanoseconds); - uint64_t end(bool print = true); - uint64_t endCount(bool stop = true); - uint64_t restart(eTimeUnits timeUnit = eTimeUnits::Nanoseconds); + u64 start(bool print = true, const String& name = "", eTimeUnits timeUnit = eTimeUnits::Nanoseconds, OutputHandlerBase* __destination = nullptr); + u64 startCount(eTimeUnits timeUnit = eTimeUnits::Nanoseconds); + u64 end(bool print = true); + u64 endCount(bool stop = true); + u64 restart(eTimeUnits timeUnit = eTimeUnits::Nanoseconds); - static uint64_t getEpoch(eTimeUnits timeUnit = eTimeUnits::Milliseconds); + static u64 getEpoch(eTimeUnits timeUnit = eTimeUnits::Milliseconds); inline const String& getName(void) const { return m_name; } - inline uint64_t read(void) { if (!m_started) return 0; return endCount(false); } + inline u64 read(void) { if (!m_started) return 0; return endCount(false); } private: bool m_started; - int64_t m_current; + i64 m_current; eTimeUnits m_timeUnit; String m_name; OutputHandlerBase* m_dest; @@ -118,26 +118,26 @@ namespace ostd class StepTimer { public: - using Callback = std::function; + using Callback = std::function; using Clock = std::chrono::high_resolution_clock; using TimePoint = Clock::time_point; using Duration = Clock::duration; public: StepTimer() = default; - inline StepTimer(double updatesPerSecond, Callback callback) { create(updatesPerSecond, callback); } - StepTimer& create(double updatesPerSecond, Callback callback); + inline StepTimer(f64 updatesPerSecond, Callback callback) { create(updatesPerSecond, callback); } + StepTimer& create(f64 updatesPerSecond, Callback callback); void update(void); void reset(void); - inline double getInterpolationAlpha(void) const { return m_valid && m_targetDt > 0.0 ? m_accumulator / m_targetDt : 0.0; } + inline f64 getInterpolationAlpha(void) const { return m_valid && m_targetDt > 0.0 ? m_accumulator / m_targetDt : 0.0; } inline void invalidate(void) { m_valid = false; } inline bool isValid(void) const { return m_valid; } private: TimePoint m_prevTime; - double m_targetDt { 0.0 }; + f64 m_targetDt { 0.0 }; Callback m_callback { nullptr }; - double m_accumulator { 0.0 }; + f64 m_accumulator { 0.0 }; bool m_valid { false }; }; @@ -145,8 +145,8 @@ namespace ostd { public: GameClock(void); - const float& start(void); - inline const float& getTimeOfDay(void) const { return m_timeOfDay; } + const f32& start(void); + inline const f32& getTimeOfDay(void) const { return m_timeOfDay; } String asString(void); void update(void); @@ -155,16 +155,16 @@ namespace ostd String convertMonth(void); public: - uint8_t minutes; - uint8_t hours; - uint16_t days; - uint8_t months; - uint16_t years; + u8 minutes; + u8 hours; + u16 days; + u8 months; + u16 years; private: Timer m_rtClock; - float m_timeOfDay; - float m_totalSeconds; + f32 m_timeOfDay; + f32 m_totalSeconds; }; class LocalTime @@ -173,13 +173,13 @@ namespace ostd String getFullString(bool include_date = true, bool include_time = true, bool day_name = true, bool month_as_name = true, bool include_seconds = true) const; inline String getDateString(bool day_name = true, bool month_as_name = true) { return getFullString(true, false, day_name, month_as_name, false); } inline String getTimeString(bool include_seconds = true) { return getFullString(false, true, false, false, include_seconds); } - int32_t hours(void) const; - int32_t minutes(void) const; - int32_t seconds(void) const; - int32_t day(void) const; - int32_t month(void) const; - int32_t year(void) const; - int32_t weekDay(void) const; + i32 hours(void) const; + i32 minutes(void) const; + i32 seconds(void) const; + i32 day(void) const; + i32 month(void) const; + i32 year(void) const; + i32 weekDay(void) const; String shours(bool leading_zero = true) const; String sminutes(bool leading_zero = true) const; String sseconds(bool leading_zero = true) const; @@ -189,40 +189,40 @@ namespace ostd String sWeekDay(bool day_name = true) const; protected: - virtual String monthToText(int32_t month) const; - virtual String weekDayToText(int32_t day) const; + virtual String monthToText(i32 month) const; + virtual String weekDayToText(i32 day) const; }; typedef LocalTime LocalTime_EN; class LocalTime_IT : public LocalTime { protected: - String monthToText(int32_t month) const override; - String weekDayToText(int32_t day) const override; + String monthToText(i32 month) const override; + String weekDayToText(i32 day) const override; }; class LocalTime_ES : public LocalTime { protected: - String monthToText(int32_t month) const override; - String weekDayToText(int32_t day) const override; + String monthToText(i32 month) const override; + String weekDayToText(i32 day) const override; }; class LocalTime_DE : public LocalTime { protected: - String monthToText(int32_t month) const override; - String weekDayToText(int32_t day) const override; + String monthToText(i32 month) const override; + String weekDayToText(i32 day) const override; }; class Time { public: static void startRunningTimer(void); - static inline const uint64_t getStartTime(void) { return s_startTime_ms; } - static void sleep(uint32_t __time, eTimeUnits __unit = eTimeUnits::Milliseconds); - static uint64_t getRunningTime_ms(void); - static String secondsToFormattedString(int32_t totalSeconds); + static inline const u64 getStartTime(void) { return s_startTime_ms; } + static void sleep(u32 __time, eTimeUnits __unit = eTimeUnits::Milliseconds); + static u64 getRunningTime_ms(void); + static String secondsToFormattedString(i32 totalSeconds); private: - inline static uint64_t s_startTime_ms; + inline static u64 s_startTime_ms; }; } diff --git a/src/test/GraphicsWindowTest.cpp b/src/test/GraphicsWindowTest.cpp index e94fec5..a2cb886 100644 --- a/src/test/GraphicsWindowTest.cpp +++ b/src/test/GraphicsWindowTest.cpp @@ -47,16 +47,16 @@ class Window : public ogfx::GraphicsWindow { auto l_rndPoint = [&](void) -> ostd::FPoint { using rnd = ostd::Random; - return rnd::getVec2({ 0, (float)getWindowWidth() }, { 0, (float)getWindowHeight() }); + return rnd::getVec2({ 0, (f32)getWindowWidth() }, { 0, (f32)getWindowHeight() }); }; - for (int32_t i = 0; i < 10000; i++) + for (i32 i = 0; i < 10000; i++) m_gfx.drawLine({ l_rndPoint(), l_rndPoint() }, ostd::Colors::Crimson, 10); m_gfx.endFrame(); } - inline void onFixedUpdate(double frameTime_s) override + inline void onFixedUpdate(f64 frameTime_s) override { - std::cout << (int)getFPS() << "\n"; + std::cout << (i32)getFPS() << "\n"; } inline void onUpdate(void) override @@ -67,7 +67,7 @@ class Window : public ogfx::GraphicsWindow ogfx::BasicRenderer2D m_gfx; }; -int main(int argc, char** argv) +i32 main(i32 argc, char** argv) { Window window; window.initialize(800, 600, "OmniaFramework - Test Window"); diff --git a/src/test/GuiTest.cpp b/src/test/GuiTest.cpp index 2207a9a..da47a18 100644 --- a/src/test/GuiTest.cpp +++ b/src/test/GuiTest.cpp @@ -31,6 +31,20 @@ class Window : public ogfx::gui::Window inline Window(void) { } inline void onInitialize(void) override { + m_img.loadFromFile("./img.png", m_gfx); + ogfx::Animation::AnimationData ad; + ad.backwards = false; + ad.columns = 9; + ad.rows = 4; + ad.frame_width = 256; + ad.frame_height = 256; + ad.length = 36; + ad.random = false; + ad.still = false; + ad.speed = 0; + m_anim.create(ad); + m_anim.setSpriteSheet(m_img); + m_panel1.setSize(300, 140); m_panel1.setPosition(350, 50); m_panel1.setMousePressedCallback([&](const ogfx::gui::Event& event) -> void { @@ -103,7 +117,7 @@ class Window : public ogfx::gui::Window m_label2.setDragAndDropCallback([&](const ogfx::gui::Event& event) -> void { if (event.drop.userObject->getTypeName() == "ogfx::gui::widgets::Label") { - std::cout << static_cast(*event.drop.userObject).getText() << "!\n"; + std::cout << cast(*event.drop.userObject).getText() << "!\n"; } }); m_panel1.addChild(m_label2); @@ -138,9 +152,15 @@ class Window : public ogfx::gui::Window void onRedraw(ogfx::BasicRenderer2D& gfx) override { + gfx.drawAnimation(m_anim, { 200, 200 }); wout().xy(100, 100).fg(ostd::Colors::Crimson).p("CIAO BELLA").resetColors(); } + void onFixedUpdate(void) override + { + m_anim.update(); + } + private: ogfx::gui::widgets::Label m_label1 { *this }; ogfx::gui::widgets::Label m_label2 { *this }; @@ -150,9 +170,11 @@ class Window : public ogfx::gui::Window ogfx::gui::widgets::CheckBox m_check1 { *this }; ostd::Stylesheet m_theme; ostd::Vec2 pos { 0, 0 }; + ogfx::Animation m_anim; + ogfx::Image m_img; }; -int main(int argc, char** argv) +i32 main(i32 argc, char** argv) { ostd::initialize(); Window window;