Re: [m-users.] Calling pass-by-value with C FFI with raylib

"Sean Charles (emacstheviking)" <[email protected]>
Newsgroups gmane.comp.lang.mercury.general
Message-ID <[email protected]>
Thanks all, Zoltan and Peter on point as usual.

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.

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.

The code I have ended up with so far is (so far) structured like this.

For the creation of new entities that can on-screen:

new_cursor(X, Y, Color) = cursor(X, Y, to_rgba(Color)).

new_text(Str, X, Y, Size, Color) =
    text(Str, X, Y, Size, to_rgba(Color)).


:- func to_rgba(color::in) = (uint32::out) is det.
to_rgba(C) = RGBA :-
    color_parts(C, R, G, B, A),
    RGBA = uint32.from_bytes_le(R, G, B, A).

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!

% Drawing the graphics objects.

    % Cursor
ui_draw(cursor(X, Y, C), !IO) :-
    draw_rectangle(X, Y, 10, 20, C, !IO).

ui_draw(text(Str, X, Y, Size, C), !IO) :-
    draw_text(Str, X, Y, Size, C, !IO).


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.

:- type world
    --->    world(
                wFrameTime  ::float,
                wTime       ::float,
                f1Hz        ::bool
            ).

:- pred run_loop(world::in, world::out, io::di, io::uo) is det.

run_loop(!W, !IO) :-
    window_should_close(X, !IO),
    (
        X = yes,
        trace_log("Stopped by user", [], !IO)
    ;
        X = no,

        % Update world state.
        get_frame_time(FT, !IO),
        get_time(T, !IO),
        !:W = !.W ^wFrameTime := FT,
        !:W = !.W ^wTime := T,
        % 1Hz timer flag
        Hz1 = float.round_to_int(wTime(!.W)) mod 2,
        (if Hz1 = 1 then Hz1On = yes else Hz1On = no),
        !:W = !.W ^f1Hz := Hz1On,

        begin_drawing(!IO),
            clear_background(color(raywhite), !IO),
            draw_fps(0, 0, !IO),

            ( if f1Hz(!.W) = yes then
                ui_draw(new_cursor(140, 100, color(purple)), !IO)
            else
                true
            ),

            ui_draw(new_text(
                string.format("frameTime: %f", [ f(wFrameTime(!.W))]),
                120, 130, 20, color(red)), !IO),

            ui_draw(new_text(
                string.format("time: %f", [ f(wTime(!.W))]),
                120, 150, 20, color(blue)), !IO),

        end_drawing(!IO),

            % File dropping
        dropped_files(Files, !IO),
        ( if list.is_not_empty(Files) then
            io.write_list(Files, "\n", io.print_line, !IO)
        else
            true
        ),
        run_loop(!W, !IO)
    ).

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.

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!

Thanks,
Sean.



> On 14 Jul 2023, at 08:51, Peter Wang <[email protected]> wrote:
> 
> On Fri, 14 Jul 2023 07:29:10 +0100 "Sean Charles (emacstheviking)" <[email protected]> wrote:
>> 
>> The only real way I could find to model that in Mercury has been to literally
>> re-invent the weel and create this union type and then some helpers:
>> 
>>    :- type p_color
>>        --->    lightgray
>>        ;       gray
>>        ;       yellow
>>        :
>>        ;       raywhite. % FInal colour from header file palette
>> 
>>    :- type color
>>        --->    rgb(uint8, uint8, uint8)
>>        ;       rgba(uint8, uint8, uint8, uint8)
>>        ;       c(p_color).
> 
> I expect you don't actually need color to be a Mercury d.u. type,
> so you can define color as a uint32, and have predicates/functions
> that convert between colors and color components.
> 
> Peter

_______________________________________________
users mailing list
[email protected]
https://lists.mercurylang.org/listinfo/users
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.