Jump to content

Losing EngineWindow Gui on Stacking


photo

Recommended Posts

I'm struggling with getting my head around the window system.
It may be that Window and Group are both `EngineWindow` but seem different.
Same with the "original" window. It seems to have some special behavior.

Scenario:
Creating nested Windows, each with its own Gui.  

I wrote some code to look at `Gui` and `SelfGui` during some window lifecycle stages.

// When the system starts the WindowManager shows 2 windows
// They have the same name, but only one is in accessible.

Profile:A => Gui: _ SelfGui: _
Main-Profile:A => Gui: 1771144857776 SelfGui: 1771144857776

Manager Current Gui Collection. 2 items...
 Profile:A => Gui: _ SelfGui: _
 Profile:A => Gui: 1771144857776 SelfGui: 1771144857776
 ...

// Iterate and that is resolved. No problems here, just curious what is happening.
Manager Current Gui Collection. 1 items...
Profile:A => Gui: 1771144857776 SelfGui: 1771144857776
 ...

// Now make two windows B & C.
// Each gets a Gui.
Main-Profile:A => Gui: 1771144857776 SelfGui: 1771144857776
Profile:B => Gui: 1771284442080 SelfGui: 1771284442080
Profile:C => Gui: 1771284442112 SelfGui: 1771284442112

Manager Current Gui Collection. 3 items...
 Profile:A => Gui: 1771144857776 SelfGui: 1771144857776
 Profile:B => Gui: 1771284442080 SelfGui: 1771284442080
 Profile:C => Gui: 1771284442112 SelfGui: 1771284442112
 ...

// Stacking the Windows creates a new Window and messes with the Gui's.
Profile:B => Gui: 1771284442080 SelfGui: _
Profile:C => Gui: 1771284442080 SelfGui: _
Profile: Generated => Gui: 1771284442080 SelfGui: 1771284442080

Manager Current Gui Collection. 4 items...
 Profile:A => Gui: 1771144857776 SelfGui: 1771144857776
 Profile:B => Gui: 1771284442080 SelfGui: _
 Profile:C => Gui: 1771284442080 SelfGui: _
 Profile:Generated => Gui: 1771284442080 SelfGui: 1771284442080
 ...

// Wouldn't this make more sense?
> Profile:Generated => Gui: 1771284463542 SelfGui: 1771284463542 // New Gui
> Profile:B => Gui: 1771284463542 SelfGui: 1771284442080
> Profile:C => Gui: 1771284463542 SelfGui: 1771284442112
// The create-time Gui should stay with the window. Right?

// Next, I want to set the main window to the generated/stacked group.
// I can't though. Is it because it isn't a Window? (IsWindow = false) 
// How do I promote it to a Window?

Switching Main to Generated
Generated is Window?: False
Main: none

Spoiler
using System;
using System.Diagnostics;
using Unigine;
using static Unigine.EngineWindow.FLAGS;
using win = Unigine.EngineWindow;
using wins = Unigine.WindowManager;

static class EC {

    [STAThread]
    static void Main(string[] args) {
        Engine.InitParameters ip = new() { window_title = "A" };
        Engine.Init(ip, args);
        // Initial State
        Gui(wins.GetWindow(0));
        MainGui();
        ManagerGuis();

        // Staging Phase
        // Q1: Where is second window?
        Engine.Iterate();
        ManagerGuis(); // Shows/Displays 2 Windows - wins.NumWindows = 2
        Gui(wins.GetWindow(0));
        //Gui(wins.GetWindow(1)); throws

        // Build Phase
        var a_ = new win("B", 200, 200, (int)(SHOWN));
        var b_ = new win("C", 200, 200, (int)(SHOWN));
        ln("Made Windows");
        MainGui();
        Gui(a_);
        Gui(b_);
        ManagerGuis();

        // Stacking
        ln("Stacked Windows");
        var c_ = wins.GetWindow(1);
        var d_ = wins.GetWindow(2);
        var e_ = wins.Stack(c_, d_);
        e_.Title = "Generated";
        e_.Size = new(800, 600);
        e_.MoveToCenter();

        // Q2: Why do Windows lose Gui on stacking?
        MainGui();
        Gui(c_);
        Gui(d_);
        Gui(e_);
        ManagerGuis();

        // Switching Windows
        ln($"Switching Main to Generated");
        win og = wins.MainWindow; og.Main = false; og.Hide();
        e_.Main = true;
        e_.Arrange();
        e_.Expand();
        e_.Show();

        ln($"Generated is Window?: {e_.IsWindow}");
        ln($"Main: {wins.MainWindow?.Title ?? "none"}");
        //Q3: How can I set the main window from a group?;


        Engine.Main();
        Engine.Shutdown();
        }

    /* **********   Locals   ********** */

    static void ln(string s) => Debug.WriteLine(s);
    static string Fmt(Gui? g) => g?.GetPtr().ToString() ?? "_";
    static string Profile(win w) => $"Profile:{w.Title} => Gui: {Fmt(w.Gui)} SelfGui: {Fmt(w.SelfGui)}";

    static void Gui(win w) => Debug.WriteLine(Profile(w));
    static void MainGui() => Debug.WriteLine($"Main-{Profile(wins.MainWindow)}");

    static void ManagerGuis() {
        Debug.WriteLine($"\nManager Current Gui Collection. {wins.NumWindows} items...");
        for (int i = 0; i < wins.NumWindows; i++) {
            Debug.WriteLine(' ' + Profile(wins.GetWindow(i)));
            }
        Debug.WriteLine(" ...\n");
        }
    }

 

 

Link to comment

Hello.

According to these log messages, this is the behavior from 2.16.0.1.

During initialization, two windows were created: the loading screen, which captured only the system window pointer, and the main application window. The loading screen was deleted via deleteLater(), so it only disappeared from the WindowManager in swap() when iterating the engine. This creation solved the problem with input focus on the main window.

When created, each window captured the system pointer and its GUI from the pool in the WindowManager. This is necessary for placement on the desktop and for rendering engine widgets inside a window.

Nested windows and nested groups don't need to use the system window and GUI, so they were put back into the pool. The parent group with its resources is responsible for interacting with them and rendering them. For a group, its contents are perceived as just a collection of engine widgets.

The main flag is basically responsible for rendering the engine from the main camera to the window. The group, on the other hand, can only render tab decorations and nested window decorations. Rendering from cameras happens only in windows. Therefore, the main flag cannot be assigned to a group.

The planned refactoring will split the EngineWindow into several separate objects, because it has accumulated too much different functionality. There will be a division like this:

  • EngineWindowBase - abstract class with basic window functionality
  • EngineWindowViewport - class for rendering from assigned camera
  • EngineWindowGroup - class for creating different types of groups based on EngineWindowBase

This will allow to separate the functionality into appropriate classes, and also improve the work with callbacks.

In 2.16.1 the log looks like this:

Profile:A => Gui: 2828044705920 SelfGui: 2828044705920
Main-Profile:A => Gui: 2828044705920 SelfGui: 2828044705920

Manager Current Gui Collection. 1 items...
 Profile:A => Gui: 2828044705920 SelfGui: 2828044705920
 ...


Manager Current Gui Collection. 1 items...
 Profile:A => Gui: 2828044705920 SelfGui: 2828044705920
 ...

Profile:A => Gui: 2828044705920 SelfGui: 2828044705920
Made Windows
Main-Profile:A => Gui: 2828044705920 SelfGui: 2828044705920
Profile:B => Gui: 2826123212208 SelfGui: 2826123212208
Profile:C => Gui: 2826123212240 SelfGui: 2826123212240

Manager Current Gui Collection. 3 items...
 Profile:A => Gui: 2828044705920 SelfGui: 2828044705920
 Profile:B => Gui: 2826123212208 SelfGui: 2826123212208
 Profile:C => Gui: 2826123212240 SelfGui: 2826123212240
 ...

Stacked Windows
Main-Profile:A => Gui: 2828044705920 SelfGui: 2828044705920
Profile:B => Gui: 2826123212784 SelfGui: 2826123212208
Profile:C => Gui: 2826123212784 SelfGui: 2826123212240
Profile:Generated => Gui: 2826123212784 SelfGui: 2826123212784

Manager Current Gui Collection. 4 items...
 Profile:A => Gui: 2828044705920 SelfGui: 2828044705920
 Profile:B => Gui: 2826123212784 SelfGui: 2826123212208
 Profile:C => Gui: 2826123212784 SelfGui: 2826123212240
 Profile:Generated => Gui: 2826123212784 SelfGui: 2826123212784
 ...

Switching Main to Generated
Generated is Window?: False
Main: none

Small improvements have already been made to window behavior.

Why do you need to work with gui? In fact, windows and widgets hide the work directly with this class. They themselves are added and removed from different gui instances. Now I see using the GUI directly only for some custom rendering.

  • Like 1
  • Thanks 1
Link to comment

Thanks @karpych11. That was really helpful - should be in the docs.
I realized I misspoke about Main. What I was thinking was "Main Gui" - basically a "CurrentGui" or the one that shows up as Profile:A.

I like the 2.16.1 results. "MainGUI" would be like changing from:

Main-Profile:A => Gui: 2828044705920 SelfGui: 2828044705920
Profile:B => Gui: 2826123212784 SelfGui: 2826123212208
Profile:C => Gui: 2826123212784 SelfGui: 2826123212240
Main-Profile:A => Gui: 2828044705920 SelfGui: 2828044705920
Profile:B => Gui: 3874657483719 SelfGui: 2826123212208
Profile:C => Gui: 3874657483719 SelfGui: 2826123212240

- setting top-parent/child containments.

I'm not really sure why I'm working with GUI :). Still learning about it.
I'm using Unigine a little differently, I think. Basically, I'm making an OS UI 3D - Replacing the Windows Desktop with Unigine. My "Grand Scheme" is Unigine in ROM on devices. (Not really planning on going that far though) 

Roughly, I thought GUI was the lowest-level and could be associated with an EngineWindow.
That window could be (indirectly) associated with a System Window/Process. 
I have Unigine as a hub and let other processes drive the sim.
I might have a "File System" EngineWindow associated with an OS filesystem process. I would give it a Window and "fixed" Gui.
These OS Modules are capable of modifying or producing Gui's. Module drivers would alter or produce and swap whole Guis in Windows.

I'm kind of taking a Unigine on the Side approach - it's part of a larger system and I'm digging around to see how I might hook in.

Link to comment
×
×
  • Create New...