Page 1 of 2 12 LastLast
Results 1 to 20 of 23

Thread: Gui question

  1. #1
    Lesser Knight
    Join Date
    Sep 2010
    Posts
    41

    Default Gui question

    Hello, I spent 2 days to read all stuff about gui. Can I use gui with CL_Window and my own render cycle? I found that I can make my own Window class inherited from CL_Window and change the render function. But in this scope the code doesn't know about methods to be called in this function.
    So, any ideas how to init gui + CL_Window and own cycle?

  2. #2
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Have you looked at all the GUI examples?

    http://clanlib.org/wiki/Examples#GUI_examples

    ( Some GUI usage examples are in the 3D examples as well )

    ClanGUI can be used with your own render loop (Which personally is what I prefer). Of course you can create your own custom GUI component with it's render function.

  3. #3
    Lesser Knight
    Join Date
    Sep 2010
    Posts
    41

    Default

    Quote Originally Posted by rombust View Post
    Have you looked at all the GUI examples?
    Sure I did.

    >ClanGUI can be used with your own render loop (Which personally is what I prefer).

    It's exactly what I need. Almost all samples uses gui.exec() and this function makes her own cycle. So, I need another way. I described the problem in first post. I found the solution:
    inheriting from CL_Window and reworking render method. But, as I said before, in that render functions I don't know objects I need to call in it.
    I need something like (pseudocode):
    Code:
    Window wnd = Window("Title");
    Gui gui = Gui(wnd, theme);
    while (Esc pressed)
    {
        logic.update();
        objects.update();
         gui.update();
        wnd.get_graphic().flip();
    }

  4. #4
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    I believe the following code should do this:

    Code:
    CL_DisplayWindow dispwind(...);
    CL_GraphicContext gc = dispwind.get_gc();
    CL_GUIManager gui(dispwind, "theme.zip");
    CL_GUIWindowManagerTexture wm = gui.get_window_manager();
    CL_Window window(&gui, window_description);
    while (!gui.get_exit_flag())
    {
      logic.update();
      objects.update();
      gui.process_messages(0);
      wm.draw_windows(gc);
      dispwind.flip();
      CL_KeepAlive::process();
    }

  5. #5
    Lesser Knight
    Join Date
    Sep 2010
    Posts
    41

    Default

    Thanks, I think that's what I need.
    But I'm confused a little. What exact window to use for drawing? From CL_DisplayWindow or from CL_Window?

  6. #6
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    OK, I'll try to explain in words what is going on.

    • DisplayWindow is the physical window seen in the operating system.
    • GUIManager is the class responsible for running the clanlib GUI.
    • GUIWindowManagerTexture is the class that creates and manages the textures created for each top-level window displayed in the clanlib GUI.
    • Window is a top-level window in the clanlib GUI. Normally you would probably derive Window and not just create it like I did here, just like you were already doing.


    The clanlib GUI operates with two different types of components: top-level and child. The top-level components are created by calling the GUIComponent constructor with a GUITopLevelDescription object, while child components are created by using the constructor that take a parent component.

    When a top-level component is created, the GUIManager uses the GUIWindowManager to create the actual window. For the texture window manager, this means that it will create a Texture object with the size of the component, while for the system window manager it will create a DisplayWindow object.

    Lets say we create two Window objects where each has 3 LineEdit and 2 PushButton objects, then there will be created two top-level components with 5 child components. Since we are using the texture window manager, this means that we will have two Texture objects - one for each Window.

    The call to GUIManager.process_messages causes the clanlib GUI to process any input messages and update the two textures with content if anything called GUIComponent.request_repaint on any of the components. So this makes the textures up to date, but does not actually draw anything on the DisplayWindow we have created.

    The call to GUIWindowManagerTexture.draw_windows makes it render those two texture objects to the GraphicContext provided. This in combination with the DisplayWindow.flip makes the GUI visible on the screen. However, if you want to do something else with those texture objects, you can draw them yourself in any way you want by calling GUIWindowManagerTexture.get_windows instead.

    I hope that helped a bit.

  7. #7
    Lesser Knight
    Join Date
    Sep 2010
    Posts
    41

    Default

    Many thanks! Great answer.

  8. #8
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Quote Originally Posted by Ockonal View Post
    Sure I did.

    >ClanGUI can be used with your own render loop (Which personally is what I prefer).

    It's exactly what I need. Almost all samples uses gui.exec() and this function makes her own cycle.
    No, that's why I mentioned the 3D examples.

    Code:
    int CL_GUIManager::exec  (  bool  loop_until_complete = true   )   
     
       Processes messages until exit_with_code is called.
    gui.exec(false) is used in them so you can have your own render loop.

    (I personally believe it gives you more power doing it that way, I don't believe the below would be possible any other way ... But I could be wrong )


  9. #9
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    554

    Default

    Somehow that screen-shot always make me smile a little bit.

  10. #10
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Bergen, Norway
    Posts
    588

    Default

    I thought the design of the wm managers was that if you really wanted to do wavy windows, you'd implement your own wm manager. But I could be wrong

  11. #11
    Lesser Knight
    Join Date
    Sep 2010
    Posts
    41

    Default

    rombust, I was told at irc that you've written the code related to this theme. I have the code for init gui with my own render cycle. And I have to split the input for gui and window somehow, could you help me with this? The current code is:
    Code:
            CL_DisplayWindowDescription desc("Some window");
            appManager.initWindow(desc); // This inits the CL_DisplayWindow
    
            guiManager.initGui(appManager.getWindow(), "media/gui_basic/"); // Inith the CL_GUIManager
    
            CL_GraphicContext gc = appManager.getGraphic();
            CL_GUIManager *gui = guiManager.getHandle();
            CL_GUIWindowManager wm = guiManager.getWindowManager();
            ((CL_GUIWindowManagerTexture*) &wm)->func_repaint().set(Application::doNothing);
            CL_GUIComponent area(gui, CL_GUITopLevelDescription());
            CL_PushButton button1(&area);
            button1.set_geometry(CL_Rect(100, 100, 200, 120));
            button1.set_text("Okay!");
    
            while (appManager.getRunning())
            {
                appManager.frameStarted();
    
                gui->process_messages(0);
                ((CL_GUIWindowManagerTexture*) &wm)->draw_windows(gc);
                // TODO: Fix above. The patch for casting is already in svn
    
                appManager.getWindow().flip(1);
                CL_KeepAlive::process(0);
                appManager.frameEnded();
            }

  12. #12
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Quote Originally Posted by sphair View Post
    I thought the design of the wm managers was that if you really wanted to do wavy windows, you'd implement your own wm manager. But I could be wrong
    Good point heh heh

    I just couldn't resist posting that image again

  13. #13
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Quote Originally Posted by Ockonal View Post
    ((CL_GUIWindowManagerTexture*) &wm)->draw_windows(gc);
    // TODO: Fix above. The patch for casting is already in svn
    ?? I have no idea why that was even required.

    Look at the code below...

    Code:
    	
    	...
    	CL_DisplayWindow window(desc);
    	...
    	CL_GUIWindowManagerTexture wm(window);
    	CL_GUIManager gui(wm, "../../../Resources/GUIThemeAero");
    	wm.func_repaint().set(this, &App::wm_repaint);
    
    	while (!quit)
    	{
    		Draw_The_Scene();
    
    		gui.exec(false);
    		wm.draw_windows(gc);
    
    		window.flip(1);
    		//CL_KeepAlive::process(); (DO NOT CALL THIS - gui.exec(false) calls it)
    	}
    
    	return 0;
    }
    
    void App::wm_repaint()
    {
    // Leave this empty
    }
    It is as simple as that, no hacks, nice and simple

    I am not sure why the other developers get confused with it.

    It only gets a bit more complex when you draw the windows to "non standard positions".
    Then, you need to draw the windows manually using wm.get_windows() and modify mouse position via GUI::wm_input_intercept. (See GUI/Gui3D example).
    Last edited by rombust; 10-05-2010 at 07:17 AM.

  14. #14
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    I will try to explain more detail.

    Code:
    wm.func_repaint().set(this, &App::wm_repaint);
    Internally the GUI, contains the following code:
    It is called when the GUI requires repainting (after an GUI event or always if constant repaint flag is set).

    Code:
    	if (!func_repaint.is_null())
    	{
    		func_repaint.invoke();
    	}
    	else
    	{
    		default_repaint();
    	}
    Here func_repaint is called. Note that in my example, it does not draw anything (contains an empty function)

    For reference, default_repaint() calls wm.draw_windows() as follows:

    Code:
    void CL_GUIWindowManagerProvider_Texture::default_repaint()
    {
    	CL_GraphicContext &gc = display_window.get_gc();
    	gc.clear(CL_Colorf::black); 
    	draw_windows(gc);
    	display_window.flip();
    }
    Since I want to be sure that the windows are drawn every frame, I have wm.draw_windows() outside func_repaint() in my main loop. (Although with contant repaint enabled, it probably is not required)

  15. #15
    Lesser Knight
    Join Date
    Sep 2010
    Posts
    41

    Default

    rombust,
    I need your help. I wrote everything like you told me, here is the cycle:
    Code:
            while (appManager.getRunning())
            {
                appManager.frameStarted();
    
                gui.exec(false);
                gui.process_messages(0);
                wm.draw_windows(gc);
    
                appManager.getWindow().flip(1);
                CL_KeepAlive::process(0);
                appManager.frameEnded();
            }
    Initializating of that variables:
    Code:
            // This makes CL_DisplayWindow
            appManager.initWindow("Titile");
            // Makes CL_GUIManager and CL_GUIWindowManagerTexture
            guiManager.initGui(appManager.getWindow(), "media/gui_basic/");
    
            CL_GUIManager gui = guiManager.getHandle();
            CL_GraphicContext gc = appManager.getGraphic();
            CL_GUIWindowManagerTexture wm = guiManager.getWM();
    
            wm.func_repaint().set(Application::doNothing);
    And now some gui fun:

    Code:
            // Get wrapper returns the CL_GUIComponent
            CL_PushButton *mSome = new CL_PushButton(&guiManager.getWrapper());
            mSome->set_geometry(CL_RectPS(mGeom.get_width() - 150 - 5, 40, 150, 30));
            mSome->set_text("Some button");
            mSome->func_clicked().set(this, &MenuState::rainStateChanged);
    
        void rainStateChanged()
        {
            cout << "achtung!";
        }
    and the guiManager.getWrapper() function:
    Code:
        CL_GUITopLevelDescription desc("GUI");
        desc.set_size(CL_Size(width, height), false);
        desc.set_position(CL_Rect(0, 0, width, height), false);
        mWrapper = new CL_GUIComponent(mGuiManager, desc);
    The problem is that rainStateChanged nevers calls. Maybe there is some fail with processing messages? I see the button, but after clicking I don't see the text.

  16. #16
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Very sorry, I made a mistake.

    Do not call: CL_KeepAlive::process();

    CL_GUIManager::exec() internally calls CL_KeepAlive::process().

    This means some of the examples are also broken.

    In the future, to simplify this, I think ClanLib should contain a function:

    Code:
    void CL_GUIWindowManagerTexture::process()
    {
    	provider->setup_painting();
    	provider->window_manager.update();
    	provider->window_manager.complete_painting();
    }
    To call instead of gui.exec(false)

    This would avoid all this confusion.

  17. #17
    ClanLib Developer
    Join Date
    May 2007
    Posts
    1,824

    Default

    Okay. All of this has now been simplied (in SVN ready for a ClanLib 2.2.4 patch release)

    Your main loop should now contain:

    Code:
    	...
    	CL_DisplayWindow window(desc);
    	...
    	CL_GUIWindowManagerTexture wm(window);
    	CL_GUIManager gui(wm, "../../../Resources/GUIThemeAero");
    
    	while (!quit)
    	{
    		Draw_The_Scene();
    
    		wm.process();
    		wm.draw_windows(gc);
    
    		window.flip(1);
    		CL_KeepAlive::process();
    	}
    
    	return 0;
    }
    Now that's simple

  18. #18
    Lesser Knight
    Join Date
    Nov 2010
    Location
    Winfield, BC Canada
    Posts
    32

    Default

    Quote Originally Posted by rombust View Post
    Have you looked at all the GUI examples?

    http://clanlib.org/wiki/Examples#GUI_examples

    ( Some GUI usage examples are in the 3D examples as well )
    Sorry for the necro.

    Perhaps it's just me but those "examples" don't seem to have any actual code associated with them. The image-link takes you to the wiki image file and the text-link takes you to an empty page with just the wiki image thumbnail displayed.

    Is there a good place to find example code that actually compiles under VC++ 2010 using clanLib 2.2.5?

  19. #19
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Bergen, Norway
    Posts
    588

    Default

    All examples are located in the big huge Examples directory, which you get when you download ClanLib source.

    As we write on the download page, "Note, if you want to look at the ClanLib Examples, you also need to download the source package."

  20. #20
    Lesser Knight
    Join Date
    Nov 2010
    Location
    Winfield, BC Canada
    Posts
    32

    Default

    Quote Originally Posted by sphair View Post
    All examples are located in the big huge Examples directory, which you get when you download ClanLib source.

    As we write on the download page, "Note, if you want to look at the ClanLib Examples, you also need to download the source package."
    Thank you so much. I downloaded the precompiled win32 binaries from this download page. It doesn't say anything about examples.

    Anyways, I've got them now - they were in the source package.

Bookmarks

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •