<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>