From 45f659cdd78ffcc768b68963f10509da735e79cf Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Sun, 24 Nov 2024 21:37:17 +0200 Subject: [PATCH] add window icon executable icon --- build.zig | 11 ++++++++++- src/assets/icon.ico | Bin 0 -> 16958 bytes src/assets/icon.png | Bin 0 -> 2797 bytes src/assets/icon.xcf | Bin 0 -> 4047 bytes src/main.zig | 38 +++++++++++++++++++------------------- src/platform.zig | 33 +++++++++++++++++++++++++++++++++ 6 files changed, 62 insertions(+), 20 deletions(-) create mode 100644 src/assets/icon.ico create mode 100644 src/assets/icon.png create mode 100644 src/assets/icon.xcf create mode 100644 src/platform.zig diff --git a/build.zig b/build.zig index 49f795a..23771f8 100644 --- a/build.zig +++ b/build.zig @@ -28,8 +28,18 @@ pub fn build(b: *std.Build) !void { exe.linkSystemLibrary("nidaqmx"); + // TODO: Emebed all assets using build.zig + // https://github.com/ziglang/zig/issues/14637#issuecomment-1428689051 + if (target.result.os.tag == .windows) { exe.subsystem = if (optimize == .Debug) .Console else .Windows; + + const resource_file = b.addWriteFiles(); + + // TODO: Generate icon file at build time + exe.addWin32ResourceFile(.{ + .file = resource_file.add("daq-view.rc", "IDI_ICON ICON \"./src/assets/icon.ico\""), + }); } b.installArtifact(exe); @@ -42,7 +52,6 @@ pub fn build(b: *std.Build) !void { const run_step = b.step("run", "Run the program"); run_step.dependOn(&run_cmd.step); - const unit_tests = b.addTest(.{ .root_source_file = b.path("src/main.zig"), .target = target, diff --git a/src/assets/icon.ico b/src/assets/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..23dc7800f9b2e163e5e39101736cf64fbef8103d GIT binary patch literal 16958 zcmeI3NoZ6{6oy-#;7Z;uE8#svvrGUUES$GI>`w)b*t)Bo%7dxPTh{h+L*t> z!kGF0ckG{{Sgarxi~VCBlN6h69@2A3p69hSPe1egXPyf4+%r$Dd48Fvu?ZQ-LMF1& z0bSbW5@T3hMn-S*l$ht0d72ub6T0;d)4d^Srp}(`DK}5P5W4nk2xcj3>M1r)b-n<% z^hD=k!I5cb%62kOnN?rDzJj4sCio41ck}GcSHK~9gQdGm8yG(Ny*Xi*<^WULabS3w z!zX@-u89UTdt5%Q^O^P+7?bu!la^2Wd#0EZ`OEEjU@|$^wKURm zq5;miv87Q7W59sMmT8LT`Nr-KFpC}MBC(mf z^5sjA$;5Jv|I?>W0lCPos;Uaey?y(3fTyUa$ousxtvjN^RDvHNEq(m>(JLq@2*^N> z%a<=Fm36_NIKGoAu@VxoA@|UsLl%eU?b@{~Nw=3TUj}$WB4Edtl9tY#IivNjS+hpR z+VbVglgj2A|Ni~^Rd(mjo&ERu^XCWTPM$p3PcJMiRNk{^&jxrxBF;XmdGqFJy^OuN zbLaZ;4jnppj8B_#jbCK3_Li2G`f_OpSp)3(v3vJ!9jEZ7p|lf(^6%fj*Zv+nc(6aO zjvqg+?Q!nhxquiK{EXqK=fHsjT3=mVoyU3yZ*g(4zvoCf*;{Vjys34OHgV!aKR$f; zaIL2yFDFi%(E7J;-|koS?%g|0Td-h3p!!_mfAZvs%0YH*ZLP*DDpiAn;S*F~+YLc5;_4jkzH{P|PsIehrA$~krFl%~7jcU}KiuU@S( zUcHJRQyB-~qra=Gt2KY`-niT5`Sa(RwsYrB)hnBqW5!aH~F_&U%>vSx55YzWC1N8W=650a`HGiHqHQd3jo=jRH) z-M99BXRr6{Kj_9B@$63Wu>3&f?xVC zDg?`wD_2y$jBSxCYrK@7G-;A#`JsIt3hTE3b40|R-&?k93FWfaXBlg`!Y}h2jEU<7 z^IEVIvIp37_3Bm4PdqEye5u}LU8Vl}_wPrt4jnpFWxaj-Hn9KL`-MGLY~91&>HjHH zrf9va!#3G_KIIc_QS^{{mn>Og7j1oSZGqMnXl;Sk7HDmOX43-f&x;o?_8k45S>cY_ zzd37<7%{>tD=YJ`J#4alvX34;va!{8av!^XJbipKVLw<5{|NVNZ6M@8aTom32Aqo_Y!$gPz+W8IH@2OHpIyimJ8~aCek{crCA9I|=W+Uou{~qP z4DBb||IR%@Sbv43_2|*V`}*~(uRn9z=D`>6;>8PpjxpEmJl?U19DLqcw@nm&sgS-F zyBm9yICSgQtt4F&b(c76h)_vMiI!Wxe!V2?d}pp<|J(N-+1h$qd5V{G_$g}l%iX(o z{o3$hVm}MURH3~__U+qO%V5t4u@){{w#<9_^r@e;VZ#RHvwf$+pR3RXziqQ#ym(PX z+xDuo3z_(qr9DQC8m0Wq0ZAV)V1TBFy4uCpc@Z0^LcsC|K8{3zJ4;S5; z!;A$XyZ`aKrXt3Z;Af4@fWZFSah;~13x4jVMVCaM3H~w3V-C~DvUV+9x->~T<6ijj z1xC@qg9nw5`=1O5?A!r5Q9AtS80C*d0Cxm(hl;<7`62ic{WtJ)&nWqV0Zrh!NzavmH5tiPxdAo5AXI`E#(q@mv)(r8#gLG z;SUR$NB8bI4`mSncD?~|A{YFOe|z6cteCT+ZRdc6y&;O|YtBSrm?aH+2!C%D1a{}| zpQ7+{X63GxvwBp&+q!Mtx>fOTZ|_2!i%O0Chn>k8lQzU=K&LG4IJr#oe=}mj5*Hns z8IS+{n;AoV1J}EmVRM0_-#^y3L5uzVwH|+q{{FeX4O;B?@8E~b#QAN2yUe2e;z{}Y zhkE>-45avn6#0cMowi^~`}>#rHt62W+5qfMzkdQhL|d7sIm`txIQ4rRdGNm}%bFN% ze45NAO6VN=Tc04p^f6Npdt*MG570H~H$Lf+rsgnpa!%x|9RCo_yfh&~Cv*#(>rx}i zF4xGwX2N#De#C~x@Whwm>`ODe*^>CIkcn)uVSQUBQ$*fZO8n({RfO$4Z#H2Y4+G7R zR~HZe_1O$#O+5amgjMl)yUKX@hlI1^@ir31qpkm4TR_@P!pe9-ZQrVRyq)xegwjva QZ_EX>4Tx04R}tkv&MmKpe$iTcx5c4t6NTAwzZ1f~bh2RIvyaN?V~-2a`*`ph-iL z;^HW{799LotU9+0Yt2!bCV&JIqBE>hzEl0u6Z503ls?%w0>9pG(NnPT)z0E%kr z=|o(})LBR@N2bY2v7?sFd%` zIV^MD;;dBbtbI@Z!azY?$#9+KFcMfo5-A9fP)7w-n26D;l42lD`*9b4#P+AiC6TKF zMvev4pg^?!;D7MDTcbEN=_Cc>K<|rXeT)G9U7*#ltnXvXYMlVSXW&Zh_-jpI_LKBR zM~fZ-gWJHxbw`u-fXf{q{G^GxXiGkt-eM7WKcjET14Fk!|C-ZVdmpC{K$f~%z5xyn zfzc9Wue-dvue-N@&$Rpd0l2+#!;C^d!T_CX>@2HM@dakSAh-}000QYNklt{=z&Ebks3rM72)#|g;a2ZiV(iYG9Ou*W!U46(N_=zm6eaeXQj=InL1)ISJH8O z&iejvW;e%~Y3590+-Ca0fpyMa`?dBuYp=cb-W==z5lsfL0l*pnD*-G4Fb9Aq01gui z0-yoV1>ggKHvpaic*Jqsh|t0~fgN8BU>ATG0JHJ$!e;)%ib(NKL;U)I{{>k92$q5f##}k3u3^BDC|NMD#Z~5B?^iP$47lOr19t!V;^q z01*`e*bV2zRgUB0j6aCR8$2iOJOJz-Zx}h_sSd#Z0C>Z>@ehFia2!`TUIPxgK&Vho&*5oBoYZ5 zk^cUEUV3kDFZuZRuu-q5s9@#Q)zz7lcj?k4mY$!VZ?;W+eSNfT+cw7c_U&6C8qgxr zM{*o9!Fqe+z<~p7M8+G$nwlDPcXtB-LPJ9l7#Ik#SPTGo^yraUqiev{ty|63>FMc- z#Kc7Q{{H=YAx)km(uc7e20uSPMt}YKm6vw+?p**tbaXU)eSIMoi;XVq;?= z5{tHQ6+m1E9jfZ&A4H>}>WuFE5XMzkK;JbGoiwyGCNMnDNQwazT!OLj*89JWNWZ zl8zla#?rI0vRL~0^XF|AKv-B94Gatr5z&VaA9!gOFJ7dst}arkRCN0EX_LH%4<9C- zPWN*JV9gzFZ*ON>;pgW^04N|Jz{EE&AT2G8<*%x$V&8Lfb8Qx0TU(o8U)bRSkVqu- z>eVZj=lS#JEUloRz+%~zm6ePyGc%K?UA77#F)@+q>+5NBboA#6Kq{3|e0)3=78a69 zrQ+qu$jD%PN~O|b*+WA^yhYOI&!2he3Wb6S3JPe?o;?&25<(FX5tNdWLgnS<%q9S! zh=>S_T4oL$5s@=2?&WehZr{F*(9lpsMn>B12sn!X?1cy}j^6_KEr8zw_$>g7ICSU` zTeQgKa*KRBckX0-YPA~0#l`GhsZ?5xDw}(>S}jsjQ`vh@PY#DFI}xx zv$V5k&)O$|&6_tfy0Ws;EKf&A2aEq@WMp9G%$W`womHz=@#-TM5ZCJiK3jY57j8-TVytJoJpYq--Dk@AIBLfyMUTmKL zX3d&~w6rt;!2SF8d24+G3}Gt(Sg~S-;Ha{t$KBl>3l=P3{KhKY-`~%oOA?6$0FaxT z3$0emcxr2F0RTQeK8(jMBWOIT#vv;J=v>Mx$ zQ>RX`kXlMGZx3@PA9z4hkjTtmyydAOI z57@YIBclzK^z`)L%$YL)fFnnaVA`~46QTjeVRpG(j=sJ=T)1$7H@a)rt_1)T6%}E4 zco;1$Ei8|(ukViwKq{584UC&NZ-R(;MoGx>Qz+)lnZvZ}_3PKX|9|Pyr93TBC=_UK zZ)bxP7Z=Cc{XGF#T@HJBc_BSL9RN^PR))5=Hl~IWi3EXxfr2~sy;;E6@J^aE3EQ`C z2LP0omZGMnhN<@a`SSq)3l}cr*`@2(uLA%gA|kBDghd!Tcx)Bx)~#do!-o%<`X?tR z!^6X4LfzGnkPtS)2CE+z7l+A{Cj$UHJUoz`oD2ZS%F1HfZ_Ab~vsSc5gt1fCRuL2w z1RozC0KmR|``Dob8>IZhFm_}Nmfm=C1pwBpS;I4s0DsHO0=h&PJ92Ino}Qj2r#S)w z0&J18;8}pRXya1HSA z@ZjwLOQlki9U#MItMNL99FO?m-D72!}RkruzK}sM#sj+vj5)zcXxLr zB_;8GSsU<-(;t%R#J}$X#6;sWfVm?5HIp(IjD?hO95-Tcgo<2H07c9b)ZejjB_XhT zMaHi1e=&BD*xB)qzOVeXfd2IKX%`T{X~Riz;P-_Iv#Y_A0AxjUiFGtr}z-+xRgWn$k2|>eSACc+T~` z)@>OQ?AN3n>pkZ^@B5thp3mnTN1{W!jdcH@@zvE$O~TaWh|+&ZSw<-;Vpc^7Y@kUA z({hSV2~esXUE!{y%u&iC3?1rE3=Ns_6zig#AJ{N#hEwK%@wI4bhjHtct+y*rr45Y^ zg(GGtG8`RHHidq4RWdaiGmT^-79D6PT{Rf#Ps9?##wxoA4M+OI#%lZ5)IfLNJGh$+ z`={LLYw0q@{oHR9dKCPf?iSZCf^dN%?##V=AGjc?RWXrGI)4^ZdLkyJ{4qC|#vm zimTt~(MvtL;nA0P^fHfL?$Il#t94d=`3S{NQQuJU>m8ki)F~ZIELV7Rcdr!F#{E(B zF_!s7PnqddC>9${VuNTn zX^h(I9}CALBiximtr-uEBvquoaMBD7M2F4(R5TGcVyR&ouicgTO{w? z%)yjuok)j<5(B0&Fd7dJMf)9-z3U3S*b!wnxJ~Uos9EtO?S!Y|ZX0K{wHM#PN0T<= z+Q;71S0Y4@5Q^0BQ zKo0=Dgg!v%xKHN44D6K#U`E&Et^GjSi~S1lU1HA?`y#RT1GkEtVXn#SE5OYzmLdJ} zW*zX9NDYvKMecbPi%Uhm0sPn}7aM_R#RCt>zs})pO?rU`f!n1xgVR1aw*vSlCua|E z&o$^Hz$fGYvi0nev;aTQWaf|d1e}3&LjfGX`R|B~00Z(@JR>jR53&=uQ^X)vOj}A-3@G#ZOqQ%jbh210=l0@ zu9_3%#N~7ZW%g-g58+CwR0H2%#GztYhy#yV__cO5@XCF_6+GpWD=**@u&Y?C>lZbk z?;0HLpm8sk<9?QnC4%4iU@a`u3d0E^*Gp!nx0|TX(L3uSEW*`0rh8Co{j)CvnE=Zw z3;2~^vdgo;-PfXW6Tp+YNJ-=S>pCBjprsmS%+5}rDmitrj( z{x`xa|6d7@^Yeb=yTC6vac*)qi^F$;Q?7%h>!TWY#kG&=2Kmkr`K4gLj@+*Juz5uLj8$oyRJd76$CTXxf z>$6F&SF~kYr+^dO@F(z(Q@9vplZ`%He7wcKY}>2A-+A$o4SO}o)+;*mN#=${j3>yi zn&ch>9@gdU4^9I-01C%L@+7dCurx{OMhm|o>^x9kEc4$c0TfWA-#(wro+aVRGq89! zSCI2cWd1hbh>M#39*_`e1%4)y1jcxA15-qG15XrCjAe>E0Bq$Y5B#l2#X3(E8R`)i zwQy4TOJ)K%w_fA|?+uZSPqfLy0QoFG#)X;;tZMl}5U(B-c^u#(K8oCf96On)4+! zsYeYj`6>yaQW{Y%%_x;M2uK_JloDABUD}~he6kKj6v$X`5A%G@=XiA@OPp2#Mkr;Z zaz?CVasAAD~?@7Z^JYR;;`f;BgFd|!`VBa7|h(<`tzJ>Fg=R_kN~tjX3& zvC_({Bdm$KQn8wkHo-dD9H8xJGqpOuU}6n0!RtER#z&aW2p8Jeu9dtr zxfYn@F=}r|u3coD#klCx?fjPBvkq3zK4$xlGdn)TY-*0#oW&)y#uyLOEX%gpUK?k( zVB5tW6(={XJ5hz-Ks&!>e^V>;f;?*Xi}CD!`U^eh7@W~?T+RqNR%g^4zcUk6p82Vf z|C~SdN2YMDD?V?=ocH?HaB`P&Ih(!k)*vN1f3B4G|NnDku#Fp&&s1AibW%xi4&O(q k+TCL5Cij1lf_hTLI4fO_IKGNw9)Rnksp2`;K2|CCHz&sR1^@s6 literal 0 HcmV?d00001 diff --git a/src/main.zig b/src/main.zig index 5a319f8..6071e32 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,13 +1,8 @@ const std = @import("std"); -const builtin = @import("builtin"); const rl = @import("raylib"); const NIDaq = @import("ni-daq.zig"); const TaskPool = @import("./task-pool.zig"); -const windows = @cImport({ - @cDefine("_WIN32_WINNT", "0x0500"); - @cInclude("windows.h"); -}); - +const Platform = @import("./platform.zig"); const raylib_h = @cImport({ @cInclude("stdio.h"); @cInclude("raylib.h"); @@ -20,6 +15,8 @@ const FontFace = @import("font-face.zig"); const assert = std.debug.assert; const Vec2 = rl.Vector2; +const icon_png = @embedFile("./assets/icon.png"); + fn toRaylibTraceLogLevel(log_level: std.log.Level) rl.TraceLogLevel { return switch (log_level) { .err => rl.TraceLogLevel.log_error, @@ -48,14 +45,16 @@ fn raylibTraceLogCallback(logType: c_int, text: [*c]const u8, args: raylib_h.va_ const max_tracelog_msg_length = 256; // from utils.c in raylib var buffer: [max_tracelog_msg_length:0]u8 = undefined; @memset(&buffer, 0); - _ = raylib_h.vsnprintf(&buffer, buffer.len, text, args); + const text_length = raylib_h.vsnprintf(&buffer, buffer.len, text, args); + + const formatted_text = buffer[0..@intCast(text_length)]; const raylib_log = std.log.scoped(.raylib); switch (log_level) { - .debug => raylib_log.debug("{s}", .{ buffer }), - .info => raylib_log.info("{s}", .{ buffer }), - .warn => raylib_log.warn("{s}", .{ buffer }), - .err => raylib_log.err("{s}", .{ buffer }) + .debug => raylib_log.debug("{s}", .{ formatted_text }), + .info => raylib_log.info("{s}", .{ formatted_text }), + .warn => raylib_log.warn("{s}", .{ formatted_text }), + .err => raylib_log.err("{s}", .{ formatted_text }) } } @@ -111,13 +110,6 @@ pub fn nanoToSeconds(ns: i128) f32 { pub fn main() !void { const start_time = std.time.nanoTimestamp(); - // if (builtin.os.tag == .windows) { - // const hWnd = windows.GetConsoleWindow(); - // std.debug.print("{any}\n", .{hWnd}); - // //_ = windows.ShowWindow(hWnd, windows.SW_HIDE); - // _ = windows.ShowWindow(hWnd, windows.SW_SHOW); - // } - raylib_h.SetTraceLogCallback(raylibTraceLogCallback); rl.setTraceLogLevel(toRaylibTraceLogLevel(std.log.default_level)); @@ -138,7 +130,7 @@ pub fn main() !void { const devices = try ni_daq.listDeviceNames(); - std.debug.print("NI-DAQ version: {}\n", .{try NIDaq.version()}); + log.info("NI-DAQ version: {}", .{try NIDaq.version()}); std.debug.print("Devices ({}):\n", .{devices.len}); for (devices) |device| { @@ -221,9 +213,13 @@ pub fn main() !void { app.channel_samples = channel_samples; + var icon_image = rl.loadImageFromMemory(".png", icon_png); + defer icon_image.unload(); + rl.initWindow(800, 450, "DAQ view"); defer rl.closeWindow(); rl.setWindowState(.{ .window_resizable = true }); + rl.setWindowIcon(icon_image); rl.setTargetFPS(60); @@ -301,6 +297,10 @@ pub fn main() !void { zoom *= 0.9; } + if (rl.isKeyPressed(rl.KeyboardKey.key_f3)) { + Platform.toggleConsoleWindow(); + } + const now_ns = std.time.nanoTimestamp(); const now_since_start = nanoToSeconds(now_ns - start_time); const now_since_samping_start = nanoToSeconds(now_ns - channel_samples.started_sampling_ns.?); diff --git a/src/platform.zig b/src/platform.zig new file mode 100644 index 0000000..863899f --- /dev/null +++ b/src/platform.zig @@ -0,0 +1,33 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const windows_h = @cImport({ + @cDefine("_WIN32_WINNT", "0x0500"); + @cInclude("windows.h"); +}); + +const assert = std.debug.assert; +const log = std.log.scoped(.platform); + +pub fn toggleConsoleWindow() void { + if (builtin.os.tag != .windows) { + return; + } + + var hWnd = windows_h.GetConsoleWindow(); + if (hWnd == null) { + if (windows_h.AllocConsole() == 0) { + // TODO: Use windows.FormatMessages + log.err("AllocConsole() failed: {}", .{ windows_h.GetLastError() }); + return; + } + + hWnd = windows_h.GetConsoleWindow(); + assert(hWnd != null); + } + + if (windows_h.IsWindowVisible(hWnd) != 0) { + _ = windows_h.ShowWindow(hWnd, windows_h.SW_HIDE); + } else { + _ = windows_h.ShowWindow(hWnd, windows_h.SW_SHOWNOACTIVATE); + } +} \ No newline at end of file