Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add raygui.c3l #37

Merged
merged 9 commits into from
Dec 26, 2024
Merged

add raygui.c3l #37

merged 9 commits into from
Dec 26, 2024

Conversation

Book-reader
Copy link
Contributor

@Book-reader Book-reader commented Dec 9, 2024

This isn't quite done yet.

some issues:

  • some internal functions used when building new elements like guiFade() are static and cannot be accessed like they would be in c, and making them not static causes weird issues. this prevents you from doing things like the custom slider example in raygui
  • directly depends on rayib5::rl for types, as defining them in both would cause conflicts, probably fine as they are not really meant to be used separately.
  • variables such as guiAlpha cannot be accessed from c3 as there are no getter/setter functions in raygui. this could be fixed by bundling a fork of raygui and adding these functions.

I have also not done enough testing yet.

this is the portable window example:

Details

module test;
import std::io;
/*******************************************************************************************
*
*   raygui - portable window
*
*   DEPENDENCIES:
*       raylib 4.0  - Windowing/input management and drawing.
*       raygui 3.0  - Immediate-mode GUI controls.
*
*   COMPILATION (Windows - MinGW):
*       gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
*
*   LICENSE: zlib/libpng
*
*   Copyright (c) 2016-2024 Ramon Santamaria (@raysan5)
*
**********************************************************************************************/

import raylib5::rl;
import raygui::rg;

//#include "raylib.h"

//#define RAYGUI_IMPLEMENTATION
//#include "../../src/raygui.h"

//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
fn int main()
{
    // Initialization
    //---------------------------------------------------------------------------------------
    int screenWidth = 800;
    int screenHeight = 600;
    
    rl::setConfigFlags(rl::FLAG_WINDOW_UNDECORATED);
    rl::initWindow(screenWidth, screenHeight, "raygui - portable window");

    // General variables
    Vector2 mousePosition;
    Vector2 windowPosition = { 500, 200 };
    Vector2 panOffset = mousePosition;
    bool dragWindow = false;
    
    rl::setWindowPosition((int)windowPosition.x, (int)windowPosition.y);
    
    bool exitWindow = false;
    
    rl::setTargetFPS(60);
    //--------------------------------------------------------------------------------------

    // Main game loop
    while (!exitWindow && !rl::windowShouldClose())    // Detect window close button or ESC key
    {
        // Update
        //----------------------------------------------------------------------------------
        mousePosition = rl::getMousePosition();
        
        if (rl::isMouseButtonPressed(MouseButton.LEFT) && !dragWindow)
        {
            if (rl::checkCollisionPointRec(mousePosition, Rectangle{ 0, 0, screenWidth, 20 }))
            {
                dragWindow = true;
                panOffset = mousePosition;
            }
        }

        if (dragWindow)
        {            
            windowPosition.x += (mousePosition.x - panOffset.x);
            windowPosition.y += (mousePosition.y - panOffset.y);

            rl::setWindowPosition((int)windowPosition.x, (int)windowPosition.y);
            
            if (rl::isMouseButtonReleased(MouseButton.LEFT)) dragWindow = false;
        }
        //----------------------------------------------------------------------------------

        // Draw
        //----------------------------------------------------------------------------------
        rl::beginDrawing();

            rl::clearBackground(rl::RAYWHITE);

            exitWindow = rg::guiWindowBox(Rectangle{ 0, 0, screenWidth, screenHeight }, "#198# PORTABLE WINDOW");
            
            rl::drawText(rl::textFormat("Mouse Position: [ %.0f, %.0f ]", mousePosition.x, mousePosition.y), 10, 40, 10, rl::DARKGRAY);
            rl::drawText(rl::textFormat("Window Position: [ %.0f, %.0f ]", windowPosition.x, windowPosition.y), 10, 60, 10, rl::DARKGRAY);

        rl::endDrawing();
        //----------------------------------------------------------------------------------
    }

    // De-Initialization
    //--------------------------------------------------------------------------------------
    rl::closeWindow();        // Close window and OpenGL context
    //--------------------------------------------------------------------------------------

    return 0;
}

I am going to work on porting more complex examples to make sure everything works properly.

@Book-reader Book-reader changed the title add raygui.c5l add raygui.c3l Dec 9, 2024
@Book-reader
Copy link
Contributor Author

I have ported the dark theme and the floating window example. Because the dark theme file was not included in default raygui and it is relatively simple I directly translated it to c3, but I am unsure if that is the best option.

this is the floating windows example:

Details

module test;

import raylib5::rl;
import raygui::rg;

//#include "raylib.h"

//#define RAYGUI_IMPLEMENTATION
//#include "../../src/raygui.h"

//#include "../../styles/dark/style_dark.h"

def DrawContentFn = fn void(Vector2 position, Vector2 scroll);

Vector2 window_position = { 10, 10 };
Vector2 window_size = { 200, 400 };
bool minimized = false;
bool moving = false;
bool resizing = false;
Vector2 scroll;

Vector2 window2_position = { 250, 10 };
Vector2 window2_size = { 200, 400 };
bool minimized2 = false;
bool moving2 = false;
bool resizing2 = false;
Vector2 scroll2;

const RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT @if(!$defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT)) = 24;



const RAYGUI_WINDOW_CLOSEBUTTON_SIZE @if(!$defined(RAYGUI_WINDOW_CLOSEBUTTON_SIZE)) = 18;




fn void guiWindowFloating(Vector2 *position, Vector2 *size, bool *minimized, bool *moving, bool *resizing, DrawContentFn draw_content, Vector2 content_size, Vector2 *scroll, char* title) {

    int close_title_size_delta_half = (RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_WINDOW_CLOSEBUTTON_SIZE) / 2;

    // window movement and resize input and collision check
    if(rl::isMouseButtonPressed(MouseButton.LEFT) && !*moving && !*resizing) {
        Vector2 mouse_position = rl::getMousePosition();

        Rectangle title_collision_rect = { position.x, position.y, size.x - ((float)RAYGUI_WINDOW_CLOSEBUTTON_SIZE + close_title_size_delta_half), RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT };
        Rectangle resize_collision_rect = { position.x + size.x - 20, position.y + size.y - 20, 20, 20 };

        if(rl::checkCollisionPointRec(mouse_position, title_collision_rect)) {
            *moving = true;
        } else if(!*minimized && rl::checkCollisionPointRec(mouse_position, resize_collision_rect)) {
            *resizing = true;
        }
    }

    // window movement and resize update
    if(*moving) {
        Vector2 mouse_delta = rl::getMouseDelta();
        position.x += mouse_delta.x;
        position.y += mouse_delta.y;

        if (rl::isMouseButtonReleased(MouseButton.LEFT)) {
            *moving = false;

            // clamp window position keep it inside the application area
            if(position.x < 0)
            {
                position.x = 0;
            }
            else if(position.x > rl::getScreenWidth() - size.x)
            {
                position.x = rl::getScreenWidth() - size.x;
            }
            if(position.y < 0)
            {
                position.y = 0;
            }
            else if(position.y > rl::getScreenHeight())
            {
                position.y = rl::getScreenHeight() - (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT;
            }
        }

    } else if(*resizing) {
        Vector2 mouse = rl::getMousePosition();
        if (mouse.x > position.x)
        {
            size.x = mouse.x - position.x;
        }
        if (mouse.y > position.y)
        {
            size.y = mouse.y - position.y;
        }

        // clamp window size to an arbitrary minimum value and the window size as the maximum
        if(size.x < 100)
        {
            size.x = 100;
        }
        else if(size.x > rl::getScreenWidth())
        {
            size.x = rl::getScreenWidth();
        }
        if(size.y < 100)
        {
            size.y = 100;
        }
        else if(size.y > rl::getScreenHeight())
        {
            size.y = rl::getScreenHeight();
        }

        if (rl::isMouseButtonReleased(MouseButton.LEFT)) {
            *resizing = false;
        }
    }

    // window and content drawing with scissor and scroll area
    if(*minimized) {
        rg::guiStatusBar({ position.x, position.y, size.x, RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }, title);

        if (rg::guiButton({ position.x + size.x - RAYGUI_WINDOW_CLOSEBUTTON_SIZE - close_title_size_delta_half,
                                   position.y + close_title_size_delta_half,
                                   RAYGUI_WINDOW_CLOSEBUTTON_SIZE,
                                   RAYGUI_WINDOW_CLOSEBUTTON_SIZE },
                                   "#120#")) {
            *minimized = false;
        }

    } else {
        *minimized = rg::guiWindowBox({ position.x, position.y, size.x, size.y }, title);

        // scissor and draw content within a scroll panel
        if(draw_content != null) {
            Rectangle scissor;
            rg::guiScrollPanel({ position.x, position.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT, size.x, size.y - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT },
                                         null,
                                         { position.x, position.y, content_size.x, content_size.y },
                                         scroll,
                                         &scissor);

            bool require_scissor = size.x < content_size.x || size.y < content_size.y;

            if(require_scissor) {
                rl::beginScissorMode((int)scissor.x, (int)scissor.y, (int)scissor.width, (int)scissor.height);
            }

            draw_content(*position, *scroll);

            if(require_scissor) {
                rl::endScissorMode();
            }
        }

        // draw the resize button/icon
        rg::guiDrawIcon(CURSOR_SCALE_LEFT_FILL, (int)(position.x + size.x) - 20, (int)(position.y + size.y) - 20, 1, rl::WHITE);
    }
}

fn void drawContent(Vector2 position, Vector2 scroll) {
    rg::guiButton({ position.x + 20 + scroll.x, position.y + 50  + scroll.y, 100, 25 }, "Button 1");
    rg::guiButton({ position.x + 20 + scroll.x, position.y + 100 + scroll.y, 100, 25 }, "Button 2");
    rg::guiButton({ position.x + 20 + scroll.x, position.y + 150 + scroll.y, 100, 25 }, "Button 3");
    rg::guiLabel({ position.x + 20 + scroll.x, position.y + 200 + scroll.y, 250, 25 }, "A Label");
    rg::guiLabel({ position.x + 20 + scroll.x, position.y + 250 + scroll.y, 250, 25 }, "Another Label");
    rg::guiLabel({ position.x + 20 + scroll.x, position.y + 300 + scroll.y, 250, 25 }, "Yet Another Label");
}

fn int main() {
    rl::initWindow(960, 560, "raygui - floating window example");
    rl::setTargetFPS(60);
    rg::style::dark::load();
    //rg::test::load();

    while(!rl::windowShouldClose()) {
        rl::beginDrawing();
            rl::clearBackground(rl::DARKGREEN);
            guiWindowFloating(&window_position, &window_size, &minimized, &moving, &resizing, &drawContent, { 140, 320 }, &scroll, "Movable & Scalable Window");
            guiWindowFloating(&window2_position, &window2_size, &minimized2, &moving2, &resizing2, &drawContent, { 140, 320 }, &scroll2, "Another window");
        rl::endDrawing();
    }

    rl::closeWindow();

    return 0;
}

@lerno
Copy link
Contributor

lerno commented Dec 26, 2024

Is this ready for inclusion now?

@Book-reader
Copy link
Contributor Author

this can be merged now, it seems to work fine.
If there are any issues that come up related to the raygui bindings then I will be happy to fix them.

@Book-reader
Copy link
Contributor Author

Book-reader commented Dec 26, 2024

I have not provided a windows version of the library because I do not have any windows machines on me.
the linux .a I provided is built off of raygui v4.0 (raysan5/raygui@25c8c65)

@lerno lerno merged commit 0f480a9 into c3lang:main Dec 26, 2024
2 checks passed
@lerno
Copy link
Contributor

lerno commented Dec 26, 2024

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants