<html><head><meta http-equiv="content-type" content="text/html; charset=us-ascii"></head><body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">Thanks all, Zoltan and Peter on point as usual.<div><br></div><div>I had a good long think about what I am doing, writing an IDE as there are not enough editors in the world already, one that is customised to the transpiler I have written, also written in Mercury, in fact the two may well become a single application but for now the remain separated. I can't decide wether to implement LSP in the transpiler as a command line option, making my editor more generic, or to use zeromq and just make them talk sooner. First world problem.</div><div><br></div><div>Anyway, I realised that, writing an editor, I am far more concerned with having all of the wonderful advantages that the Mercury compiler gives me rather than worry about performance over bit fiddling some colour values, thus I opted to do any bit shifting etc at the point of creation of my ui objects and then just as Peter recommended, pass a uint32 across the FFI boundary. So far this is working absolutely fine, so thank you all again for your guiding input.</div><div><br></div><div>The code I have ended up with so far is (so far) structured like this.</div><div><br></div><div>For the creation of new entities that can on-screen:</div><div><br></div><div><div><font face="Courier New">new_cursor(X, Y, Color) = cursor(X, Y, to_rgba(Color)).</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">new_text(Str, X, Y, Size, Color) =</font></div><div><font face="Courier New"> text(Str, X, Y, Size, to_rgba(Color)).</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">:- func to_rgba(color::in) = (uint32::out) is det.</font></div><div><font face="Courier New">to_rgba(C) = RGBA :-</font></div><div><font face="Courier New"> color_parts(C, R, G, B, A),</font></div><div><font face="Courier New"> RGBA = uint32.from_bytes_le(R, G, B, A).</font></div></div><div><br></div><div>These are then rendered on a case by case basis, I will add more state to them as the need arise, the raylib library has tweening functions for example, so I intend to make things be able to fade in, out, move about etc as you interact with the code. That's the vision!</div><div><br></div><div><div><font face="Courier New">% Drawing the graphics objects.</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New"> % Cursor</font></div><div><font face="Courier New">ui_draw(cursor(X, Y, C), !IO) :-</font></div><div><font face="Courier New"> draw_rectangle(X, Y, 10, 20, C, !IO).</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">ui_draw(text(Str, X, Y, Size, C), !IO) :-</font></div><div><font face="Courier New"> draw_text(Str, X, Y, Size, C, !IO).</font></div></div><div><br></div><div><br></div><div>And my very simple UI main loop just checks to see if it show/not show the cursor, I will move that functionality into the UI objects I think, giving a reference to the current world state so each object can make it's own decisions on how to render, or not. As I say it is early days.</div><div><br></div><div><div><font face="Courier New">:- type world</font></div><div><font face="Courier New"> ---> world(</font></div><div><font face="Courier New"> wFrameTime ::float,</font></div><div><font face="Courier New"> wTime ::float,</font></div><div><font face="Courier New"> f1Hz ::bool</font></div><div><font face="Courier New"> ).</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">:- pred run_loop(world::in, world::out, io::di, io::uo) is det.</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">run_loop(!W, !IO) :-</font></div><div><font face="Courier New"> window_should_close(X, !IO),</font></div><div><font face="Courier New"> (</font></div><div><font face="Courier New"> X = yes,</font></div><div><font face="Courier New"> trace_log("Stopped by user", [], !IO)</font></div><div><font face="Courier New"> ;</font></div><div><font face="Courier New"> X = no,</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New"> % Update world state.</font></div><div><font face="Courier New"> get_frame_time(FT, !IO),</font></div><div><font face="Courier New"> get_time(T, !IO),</font></div><div><font face="Courier New"> !:W = !.W ^wFrameTime := FT,</font></div><div><font face="Courier New"> !:W = !.W ^wTime := T,</font></div><div><font face="Courier New"> % 1Hz timer flag</font></div><div><font face="Courier New"> Hz1 = float.round_to_int(wTime(!.W)) mod 2,</font></div><div><font face="Courier New"> (if Hz1 = 1 then Hz1On = yes else Hz1On = no),</font></div><div><font face="Courier New"> !:W = !.W ^f1Hz := Hz1On,</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New"> begin_drawing(!IO),</font></div><div><font face="Courier New"> clear_background(color(raywhite), !IO),</font></div><div><font face="Courier New"> draw_fps(0, 0, !IO),</font></div><div><font face="Courier New"><br></font></div><div><span style="font-family: "Courier New";"> ( if f1Hz(!.W) = yes then</span></div><div><font face="Courier New"> ui_draw(new_cursor(140, 100, color(purple)), !IO)</font></div><div><font face="Courier New"> else</font></div><div><font face="Courier New"> true</font></div><div><font face="Courier New"> ),</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New"> ui_draw(new_text(</font></div><div><font face="Courier New"> string.format("frameTime: %f", [ f(wFrameTime(!.W))]),</font></div><div><font face="Courier New"> 120, 130, 20, color(red)), !IO),</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New"> ui_draw(new_text(</font></div><div><font face="Courier New"> string.format("time: %f", [ f(wTime(!.W))]),</font></div><div><font face="Courier New"> 120, 150, 20, color(blue)), !IO),</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New"> end_drawing(!IO),</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New"> % File dropping</font></div><div><font face="Courier New"> dropped_files(Files, !IO),</font></div><div><font face="Courier New"> ( if list.is_not_empty(Files) then</font></div><div><font face="Courier New"> io.write_list(Files, "\n", io.print_line, !IO)</font></div><div><font face="Courier New"> else</font></div><div><font face="Courier New"> true</font></div><div><font face="Courier New"> ),</font></div><div><font face="Courier New"> run_loop(!W, !IO)</font></div><div><font face="Courier New"> ).</font></div></div><div><br></div><div>My influences for the project are the Squeak Morphic system (its inheritence and approach, I was a big Squeak addict once) and of course 'that demo' by Douglas Englebart in the DARPA video.</div><div><br></div><div>I have no idea where this is taking me but it sure is a pleasant journey and a whole lot of fun! Mercury just makes me know that the code I write is going to be robust and well thought out, I live in fear of dangling references with C/assembler which is why my C FFI code checks every single things passed to it and only calls the C function if it is satisfied with its inputs!</div><div><br></div><div>Thanks,</div><div>Sean.</div><div><br></div><div><br></div><div><div><br><blockquote type="cite"><div>On 14 Jul 2023, at 08:51, Peter Wang <novalazy@gmail.com> wrote:</div><br class="Apple-interchange-newline"><div><div>On Fri, 14 Jul 2023 07:29:10 +0100 "Sean Charles (emacstheviking)" <objitsu@gmail.com> wrote:<br><blockquote type="cite"><br>The only real way I could find to model that in Mercury has been to literally<br>re-invent the weel and create this union type and then some helpers:<br><br> :- type p_color<br> ---> lightgray<br> ; gray<br> ; yellow<br> :<br> ; raywhite. % FInal colour from header file palette<br><br> :- type color<br> ---> rgb(uint8, uint8, uint8)<br> ; rgba(uint8, uint8, uint8, uint8)<br> ; c(p_color).<br></blockquote><br>I expect you don't actually need color to be a Mercury d.u. type,<br>so you can define color as a uint32, and have predicates/functions<br>that convert between colors and color components.<br><br>Peter<br></div></div></blockquote></div><br></div></body></html>