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

Getting an OpenGL widget to work #680

Open
jeannekamikaze opened this issue Dec 31, 2023 · 1 comment
Open

Getting an OpenGL widget to work #680

jeannekamikaze opened this issue Dec 31, 2023 · 1 comment

Comments

@jeannekamikaze
Copy link

I am unable to get an OpenGL widget working. I used opengl.d as a reference and I noticed that if I don't specify a padding or margins, the widget has 0 size. Moreover, the rect that gets passed in does not seem to map to the widget's location on the screen anyway.

Below is a minimal example where nothing gets drawn. If I replace the OpenGL widget with a button, however, the button does appear on the screen.

Any help on getting this example to work would be appreciated. Thank you.

import bindbc.opengl;
import dlangui;

mixin APP_ENTRY_POINT;

class MainView : VerticalLayout
{
    this(string id)
    {
        super(id);

        layoutWidth = FILL_PARENT;
        layoutHeight = FILL_PARENT;

        backgroundDrawable = DrawableRef(new OpenGLDrawable(&render));
    }

    void render(Rect windowRect, Rect rc)
    {
        // Clear the widget to pink.
        glEnable(GL_SCISSOR_TEST);
        glScissor(rc.left, rc.bottom, rc.width, rc.height);
        glClearColor(1, 0, 1, 0);
        glClear(GL_COLOR_BUFFER_BIT);
        glDisable(GL_SCISSOR_TEST);
    }
}

extern (C) int UIAppMain(string[] args)
{
    Window window = Platform.instance.createWindow("Game Maker", null);

    // Nothing gets rendered. The widget seems to have 0 size.
    window.mainWidget = new MainView("MainView");

    // The button does appear on the screen.
    //window.mainWidget = new Button("Button", "Click me"d);

    window.show();
    return Platform.instance.enterMessageLoop();
}
@jeannekamikaze
Copy link
Author

jeannekamikaze commented Dec 31, 2023

Answering part of my own question: the rect's coordinates appear to be in the window's coordinate system, with the origin at the top left, versus OpenGL's bottom left. Therefore, to get the example above working, one must subtract the rect's bottom from the window's height when computing the rect's y-origin:

glScissor(rc.left, windowRect.height - rc.bottom, rc.width, rc.height);

There is still a problem with the widget's size when it is embedded inside a layout, however, which is the situation I would expect in most non-trivial applications. The following is a minimal example that reproduces this problem.

If you leave the padding = 1 line commented out in the example, you'll see that the widget gets a height of 0. If you uncomment it, then the widget gets the correct height. The same is true if you set the margin instead of the padding, or if you set both. Note that the value per se of the padding or margin does not really matter; it's the fact that it is non-zero that makes the widget work.

import bindbc.opengl;
import dlangui;
import std.stdio;

mixin APP_ENTRY_POINT;

class MainView : FrameLayout
{
    this(string id)
    {
        super(id);

        // Uncomment this line to give the widget a non-zero height.
        //padding = 1;

        layoutWidth = FILL_PARENT;
        layoutHeight = FILL_PARENT;

        backgroundDrawable = DrawableRef(new OpenGLDrawable(&render));
    }

    void render(Rect windowRect, Rect rc)
    {
        writeln(rc);
        writeln("left: ", rc.left, ", bottom: ", rc.bottom, ", width: ", rc
                .width, ", height: ", rc.height);

        // Clear the widget to pink.
        glEnable(GL_SCISSOR_TEST);
        glScissor(rc.left, windowRect.height - rc.bottom, rc.width, rc.height);
        glClearColor(1, 0, 1, 0);
        glClear(GL_COLOR_BUFFER_BIT);
        glDisable(GL_SCISSOR_TEST);
    }
}

extern (C) int UIAppMain(string[] args)
{
    Window window = Platform.instance.createWindow("Game Maker", null);

    window.mainWidget = parseML(q{
        VerticalLayout {
            id: ViewLayout
            layoutWidth: fill; layoutHeight: fill
        }
    });
    auto viewLayout = cast(VerticalLayout) window.mainWidget.childById("ViewLayout");
    viewLayout.addChild(new MainView("MainView"));

    window.show();
    return Platform.instance.enterMessageLoop();
}

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

No branches or pull requests

1 participant