klepto2 Posted August 24, 2022 Share Posted August 24, 2022 I know, but for the scattering i might need a bit more According to some papers i will split up the data into PushConstants and uniform buffers, where the push constants will contain the repeatedly changing data and the uniform buffer maybe the more static once. UniformBuffer was just the beginning, i will try to integrate as much buffer types as possible, this will give a lot more freedom. Windows 10 Pro 64-Bit-Version NVIDIA Geforce 1080 TI Link to comment Share on other sites More sharing options...
Josh Posted August 24, 2022 Author Share Posted August 24, 2022 Do you feel like this approach is more modular than what you did with Leadwerks? Does this allow more possibilities? My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
klepto2 Posted August 24, 2022 Share Posted August 24, 2022 Yes, to get the ComputeShaders (mainly for fft or the atmospheric scattering) was very tricky to implement in leadwerks, some missing things like native 3d textures. UltraEngine already has eveything we need, and the latest additions to hook into it the rendering pipeline and get easy access to some underlying types makes it much easier. On the other hand, you need to think a bit different than as in Leadwrks Engine. eg: Textures etc. are really only initialised once they are rendered. But thats nice, just needs a different thinking and makes it ultra fast. Windows 10 Pro 64-Bit-Version NVIDIA Geforce 1080 TI Link to comment Share on other sites More sharing options...
reepblue Posted August 24, 2022 Share Posted August 24, 2022 1 hour ago, Josh said: Another update: Initializes using Vulkan 1.3 TextArea now working in 3D graphics CreateInterface() overload added a font parameter Nice, I don't expect that you got to fixing buttons, but if this also fixes text areas, I should be able to get a working developer console now. Cyclone - Ultra Game System - Component Preprocessor - Tex2TGA - Darkness Awaits Template (Leadwerks) If you like my work, consider supporting me on Patreon! Link to comment Share on other sites More sharing options...
Josh Posted August 24, 2022 Author Share Posted August 24, 2022 @reepblue Looks like the text alignment has some problems but buttons are functional. 1 My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
reepblue Posted August 24, 2022 Share Posted August 24, 2022 I'm sure you'll figure it out. More interested in functionality right now. Also, for hiding UI elements, should I be hiding the interface or the camera? I was hiding the camera to make the menu stop drawing which is probably why it's slow to update first time around. Cyclone - Ultra Game System - Component Preprocessor - Tex2TGA - Darkness Awaits Template (Leadwerks) If you like my work, consider supporting me on Patreon! Link to comment Share on other sites More sharing options...
Josh Posted August 24, 2022 Author Share Posted August 24, 2022 I would hide the camera, unless there are other 2D elements you want to draw. I think the UI might be responding to a bunch of piled up window paint events and is re-creating a lot of sprites at startup but I'm not sure yet. 1 My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted August 24, 2022 Author Share Posted August 24, 2022 Update is up: Fixed text alignment for buttons and other widgets Faster startup time 1 My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted August 24, 2022 Share Posted August 24, 2022 Just updated and all the contents of the Include directory were gone - not sure about other directories. This could be because I deleted tar.exe and am using the older default for W10? There were also two updates available, one right after the other. After uninstalling then reinstalling there is no Include folder now. Link to comment Share on other sites More sharing options...
Yue Posted August 24, 2022 Share Posted August 24, 2022 I thought I could try it. Link to comment Share on other sites More sharing options...
reepblue Posted August 26, 2022 Share Posted August 26, 2022 @Josh Recompiled my app, this is what I get now. The elements don't seem to be updating ether, but that may be on me. Cyclone - Ultra Game System - Component Preprocessor - Tex2TGA - Darkness Awaits Template (Leadwerks) If you like my work, consider supporting me on Patreon! Link to comment Share on other sites More sharing options...
Josh Posted August 26, 2022 Author Share Posted August 26, 2022 Not a big problem, it's just the clipping planes are not working. My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted August 26, 2022 Author Share Posted August 26, 2022 Test program shows a problem with the slider: #include "UltraEngine.h" using namespace UltraEngine; int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window auto window = CreateWindow("Ultra Engine", 0, 0, 800, 600, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); //Create a world auto world = CreateWorld(); //Create a framebuffer auto framebuffer = CreateFramebuffer(window); //Create a camera auto camera = CreateCamera(world); camera->SetClearColor(0.125); camera->SetRotation(45, 0, 0); camera->Move(0, 0, -10); camera->SetFOV(70); auto uicam = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); uicam->SetRenderLayers(RENDERLAYER_1); uicam->SetPosition(framebuffer->size.x / 2, framebuffer->size.y / 2); auto ui = CreateInterface(world, LoadFont("Fonts/arial.ttf"), framebuffer->size); ui->SetRenderLayers(RENDERLAYER_1); auto sz = ui->root->ClientSize(); auto textarea = CreateTextArea(10, 10, sz.x - 20, sz.y - 20, ui->root, TEXTAREA_WORDWRAP); WString s; for (int n = 0; n < 300; ++n) { s += String(n) + "\n"; } textarea->SetLayout(1, 1, 1, 1); //ui->SetScale(displays[0]->scale); textarea->SetText(s); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { while (PeekEvent()) { ui->ProcessEvent(WaitEvent()); } world->Update(); world->Render(framebuffer); } return 0; } My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted August 26, 2022 Author Share Posted August 26, 2022 Same problem in a simpler example: #include "UltraEngine.h" using namespace UltraEngine; int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window auto window = CreateWindow("Ultra Engine", 0, 0, 800, 600, displays[0]); //Create User Interface auto ui = CreateInterface(window); //Create widget auto sz = ui->root->ClientSize(); auto slider = CreateSlider(10, 10, 200, 30, ui->root, SLIDER_SCROLLBAR); while (true) { const Event ev = WaitEvent(); switch (ev.id) { case EVENT_WIDGETACTION: Print("Widget action: " + String(ev.data)); break; case EVENT_WINDOWCLOSE: return 0; break; } } return 0; } My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted August 26, 2022 Author Share Posted August 26, 2022 New update: GUI is now 100% working correctly in Vulkan, as far as I know Fixed terrain paint example Sprites are now using the PBR shader family by default. If you want to use the unlit shader family, you need to create a material and assign the shader family to it. My list of things to do: Directional light shadows GI for dynamic objects Motion blur VR integration 2 My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted August 26, 2022 Share Posted August 26, 2022 I've tried a few things but it's still not downloading everything with the default version of tar.exe. Here is some specific info about my OS. What version are you guys running? Link to comment Share on other sites More sharing options...
SpiderPig Posted August 26, 2022 Share Posted August 26, 2022 @Josh Clicking "Cancel" on the download process crashes the App. Link to comment Share on other sites More sharing options...
Josh Posted August 27, 2022 Author Share Posted August 27, 2022 If you click the "run install scripts manually" options in the settings you can run the bat file yourself and see any info it prints out. My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted August 27, 2022 Author Share Posted August 27, 2022 Client is updated to fix the cancel download button bug. My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
reepblue Posted August 27, 2022 Share Posted August 27, 2022 Still getting the clipping issue in the 3D render but the first draw call seems to be better. FYI, unless I'm not doing this correctly, adding in a 3D viewport seems to slow everything down. Also, I can't seem to resize the viewport after the window size has been changed. #include "UltraEngine.h" #include "ComponentSystem.h" using namespace UltraEngine; const int TOOLBARHEIGHT = 48; const int STATUSBARHEIGHT = 32; const int SIDEPANELWIDTH = 300; const int CONSOLEHEIGHT = 120; int main(int argc, const char* argv[]) { //Get displays auto displays = GetDisplays(); //Create window auto mainwindow = CreateWindow("Ultra App Kit", 0, 0, 1024, 768, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR | WINDOW_RESIZABLE); mainwindow->SetMinSize(800, 600); //Create user interface auto ui = CreateInterface(mainwindow); iVec2 sz = ui->root->ClientSize(); //------------------------------------------------------- // Create main menu //------------------------------------------------------- auto mainmenu = CreateMenu("", ui->root); //File menu auto menu_file = CreateMenu("File", mainmenu); CreateMenu("New", menu_file); CreateMenu("", menu_file); auto menu_open = CreateMenu("Open", menu_file); auto menu_save = CreateMenu("Save", menu_file); auto menu_saveas = CreateMenu("Save as...", menu_file); CreateMenu("", menu_file); auto menu_recentfiles = CreateMenu("Recent files", menu_file); array<shared_ptr<Widget>, 10> menu_recentfile; for (int n = 0; n < menu_recentfile.size(); ++n) { menu_recentfile[n] = CreateMenu("Recent file " + String(n + 1), menu_recentfiles); } CreateMenu("", menu_file); auto menu_exit = CreateMenu("Exit", menu_file); //Edit menu auto menu_edit = CreateMenu("Edit", mainmenu); CreateMenu("Undo", menu_edit); CreateMenu("Redo", menu_edit); CreateMenu("", menu_edit); CreateMenu("Cut", menu_edit); CreateMenu("Copy", menu_edit); CreateMenu("Past", menu_edit); CreateMenu("", menu_edit); CreateMenu("Select all", menu_edit); CreateMenu("Select none", menu_edit); CreateMenu("Invert selection", menu_edit); //View menu auto menu_view = CreateMenu("View", mainmenu); auto menu_perspective = CreateMenu("Perspective", menu_view); auto menu_top = CreateMenu("XZ - Top", menu_view); auto menu_side = CreateMenu("XZ - Side", menu_view); auto menu_front = CreateMenu("XY - Front", menu_view); menu_perspective->SetState(true); //Tools menu auto menu_tools = CreateMenu("Tools", mainmenu); auto menu_options = CreateMenu("Options", menu_tools); //Help menu auto menu_help = CreateMenu("Help", mainmenu); auto menu_helpcontents = CreateMenu("Help Contents", menu_help); auto menu_about = CreateMenu("About", menu_help); //------------------------------------------------------- // Create toolbar //------------------------------------------------------- auto toolbar = CreatePanel(0, mainmenu->size.y, sz.x, TOOLBARHEIGHT, ui->root); toolbar->SetLayout(1, 1, 1, 0); int x = 4, y = 4; auto toolbarbutton_open = CreateButton("", x, y, TOOLBARHEIGHT - 8, TOOLBARHEIGHT - 8, toolbar, BUTTON_TOOLBAR); toolbarbutton_open->SetFontScale(2); toolbarbutton_open->SetIcon(LoadIcon("https://raw.githubusercontent.com/Leadwerks/Documentation/private/Assets/Icons/open.svg")); x += TOOLBARHEIGHT; auto toolbarbutton_save = CreateButton("", x, y, TOOLBARHEIGHT - 8, TOOLBARHEIGHT - 8, toolbar, BUTTON_TOOLBAR); toolbarbutton_save->SetFontScale(2); toolbarbutton_save->SetIcon(LoadIcon("https://raw.githubusercontent.com/Leadwerks/Documentation/private/Assets/Icons/save.svg")); x += TOOLBARHEIGHT; auto toolbarbutton_options = CreateButton("", x, y, TOOLBARHEIGHT - 8, TOOLBARHEIGHT - 8, toolbar, BUTTON_TOOLBAR); toolbarbutton_options->SetFontScale(2); toolbarbutton_options->SetIcon(LoadIcon("https://raw.githubusercontent.com/Leadwerks/Documentation/private/Assets/Icons/settings.svg")); x += TOOLBARHEIGHT; auto toolbarbutton_help = CreateButton("", x, y, TOOLBARHEIGHT - 8, TOOLBARHEIGHT - 8, toolbar, BUTTON_TOOLBAR); toolbarbutton_help->SetIcon(LoadIcon("https://raw.githubusercontent.com/Leadwerks/Documentation/private/Assets/Icons/help.svg")); toolbarbutton_help->SetFontScale(2); //------------------------------------------------------- // Create status bar //------------------------------------------------------- auto statusbar = CreatePanel(0, sz.y - STATUSBARHEIGHT, sz.x, STATUSBARHEIGHT, ui->root); statusbar->SetLayout(1, 1, 0, 1); auto statusbarlabel_view = CreateLabel("Perspective", 4, 0, 300, statusbar->size.y, statusbar, LABEL_LEFT | LABEL_MIDDLE); //------------------------------------------------------- // Create main panel //------------------------------------------------------- auto mainpanel = CreatePanel(0, toolbar->position.y + toolbar->size.y, sz.x, sz.y - toolbar->size.y - toolbar->position.y - statusbar->size.y, ui->root); mainpanel->SetLayout(1, 1, 1, 1); sz = mainpanel->ClientSize(); //Create console auto console = CreateTextArea(4, mainpanel->size.y - CONSOLEHEIGHT, mainpanel->size.x - SIDEPANELWIDTH - 8, CONSOLEHEIGHT - 28 - 4, mainpanel); console->SetLayout(1, 1, 0, 1); auto widget_input = CreateTextField(4, mainpanel->size.y - 28, mainpanel->size.x - SIDEPANELWIDTH - 8, 28, mainpanel, TEXTFIELD_ENTERKEYACTIONEVENT); widget_input->SetLayout(1, 1, 0, 1); //Main viewport auto mainviewport = CreatePanel(4, 4, mainpanel->size.x - SIDEPANELWIDTH - 8, mainpanel->size.y - 8 - CONSOLEHEIGHT, mainpanel, PANEL_BORDER); mainviewport->SetLayout(1, 1, 1, 1); mainviewport->SetColor(0, 0, 0); auto viewport = CreateWindow("", mainviewport->GetPosition(true).x, mainviewport->GetPosition(true).y, mainviewport->GetSize().x, mainviewport->GetSize().y, mainwindow, WINDOW_CHILD | WINDOW_CLIENTCOORDS); //Create a world auto world = CreateWorld(); //Create a framebuffer auto framebuffer = CreateFramebuffer(viewport); //Create a camera auto camera = CreateCamera(world); camera->SetClearColor(0.125); camera->SetFOV(70); camera->SetPosition(0, 0, -3); //Create a light auto light = CreateLight(world, LIGHT_DIRECTIONAL); light->SetRotation(35, 45, 0); //Create a box auto box = CreateBox(world); //------------------------------------------------------- // Create side panel //------------------------------------------------------- auto sidepanel = CreatePanel(sz.x - SIDEPANELWIDTH, 0, SIDEPANELWIDTH, sz.y, mainpanel); sidepanel->SetLayout(0, 1, 1, 1); auto tabber = CreateTabber(0, 0, SIDEPANELWIDTH, sz.y, sidepanel); tabber->SetLayout(1, 1, 1, 1); tabber->AddItem("Objects", true); tabber->AddItem("Scene"); //Object panel sz = tabber->ClientSize(); auto objectpanel = CreatePanel(0, 0, sz.x, sz.y, tabber); objectpanel->SetLayout(1, 1, 1, 1); //tabber->items[0].extra = objectpanel; //Scene panel auto scenepanel = CreatePanel(0, 0, sz.x, sz.y, tabber); scenepanel->SetHidden(true); scenepanel->SetLayout(1, 1, 1, 1); //tabber->items[1].extra = scenepanel; x = 8; y = 12; CreateLabel("Category:", x, y, 200, 30, objectpanel); y += 24; auto objectcategorybox = CreateComboBox(x, y, sz.x - x * 2, 30, objectpanel); objectcategorybox->SetLayout(1, 1, 1, 0); objectcategorybox->AddItem("Primitives", true); objectcategorybox->AddItem("Extended primitives"); objectcategorybox->AddItem("Cameras"); objectcategorybox->AddItem("Lights"); objectcategorybox->AddItem("Splines"); y += 44; CreateLabel("Object:", x, y, 200, 30, objectpanel); y += 24; auto objectbox = CreateComboBox(x, y, sz.x - x * 2, 30, objectpanel); objectbox->SetLayout(1, 1, 1, 0); objectbox->AddItem("Box", true); objectbox->AddItem("Wedge"); objectbox->AddItem("Cylinder"); objectbox->AddItem("Sphere"); y += 44; x = 80; CreateButton("Create", x, y, sz.x - 2 * x, 28, objectpanel); x = 8; y = 12; auto scenebrowser = CreateTreeView(x, y, sz.x - 2 * x, 400 - y, scenepanel); scenebrowser->SetLayout(1, 1, 1, 1); auto node = scenebrowser->root->AddNode("Scene"); node->Expand(); node->AddNode("Box 1"); node->AddNode("Box 2"); node->AddNode("Box 3"); y += scenebrowser->size.y + x; auto propertiespanel = CreatePanel(x, y, sz.x, sz.y - y, scenepanel); propertiespanel->SetLayout(1, 1, 0, 1); y = 8; CreateLabel("Name:", x, y + 4, 60, 30, propertiespanel); auto widget_name = CreateTextField(x * 2 + 60, y, sz.x - 4 * x - 60, 30, propertiespanel); widget_name->SetText("Box 1"); y += 40; CreateLabel("Value:", x, y + 4, 60, 30, propertiespanel); CreateSlider(x * 2 + 60, y, sz.x - 4 * x - 60, 30, propertiespanel, SLIDER_HORIZONTAL | SLIDER_TRACKBAR); y += 40; //------------------------------------------------------- // Options window //------------------------------------------------------- auto optionswindow = CreateWindow("Options", 0, 0, 400, 500, mainwindow, WINDOW_HIDDEN | WINDOW_TITLEBAR | WINDOW_CENTER); auto optionsui = CreateInterface(optionswindow); sz = optionsui->root->ClientSize(); auto button_option1 = CreateButton("Option 1", 12, 12, 300, 30, optionsui->root, BUTTON_CHECKBOX); button_option1->SetState(WIDGETSTATE_SELECTED); auto button_option2 = CreateButton("Option 2", 12, 12 + 32, 300, 30, optionsui->root, BUTTON_RADIO); button_option2->SetState(WIDGETSTATE_SELECTED); auto button_option3 = CreateButton("Option 3", 12, 12 + 32 * 2, 300, 30, optionsui->root, BUTTON_RADIO); auto button_applyoptions = CreateButton("OK", sz.x - 2 * (8 + 80), sz.y - 8 - 30, 80, 30, optionsui->root, BUTTON_OK); auto button_closeoptions = CreateButton("Cancel", sz.x - 8 - 80, sz.y - 8 - 30, 80, 30, optionsui->root, BUTTON_CANCEL); //------------------------------------------------------- // Main loop //------------------------------------------------------- while (true) { const Event event = WaitEvent(); switch (event.id) { case EVENT_WINDOWSIZE: if (event.source == mainwindow) { // If the window resize event is captured auto window = event.source->As<UltraEngine::Window>(); // Get the new size of the applications window UltraEngine::iVec2 sz = mainwindow->ClientSize(); // Set the position and size of the viewport window //viewport->SetShape(mainviewport->GetPosition(true).x, mainviewport->GetPosition(true).y, mainviewport->GetSize().x, mainviewport->GetSize().y); } break; case EVENT_WIDGETACTION: if (event.source == menu_exit) { EmitEvent(EVENT_WINDOWCLOSE, mainwindow); } else if (event.source == menu_open) { RequestFile("Open File"); } else if (event.source == menu_save or event.source == menu_saveas) { RequestFile("Save File", "", "All Files", 0, true); } else if (event.source == menu_helpcontents) { RunFile("https://www.ultraengine.com/learn"); } else if (event.source == menu_about) { Notify("Ultra App Kit"); } else if (event.source == menu_perspective or event.source == menu_top or event.source == menu_side or event.source == menu_front) { menu_perspective->SetState(WIDGETSTATE_UNSELECTED); menu_top->SetState(WIDGETSTATE_UNSELECTED); menu_side->SetState(WIDGETSTATE_UNSELECTED); menu_front->SetState(WIDGETSTATE_UNSELECTED); auto menuitem = event.source->As<Widget>(); menuitem->SetState(WIDGETSTATE_SELECTED); statusbarlabel_view->SetText(menuitem->text); } else if (event.source == toolbarbutton_open) { EmitEvent(EVENT_WIDGETACTION, menu_open); } else if (event.source == toolbarbutton_save) { EmitEvent(EVENT_WIDGETACTION, menu_save); } else if (event.source == toolbarbutton_options) { EmitEvent(EVENT_WIDGETACTION, menu_options); } else if (event.source == toolbarbutton_help) { EmitEvent(EVENT_WIDGETACTION, menu_helpcontents); } else if (event.source == widget_input) { if (!widget_input->text.empty()) { console->AddText("\n" + widget_input->text); widget_input->SetText(""); } widget_input->Activate(); } else if (event.source == menu_options) { optionswindow->SetHidden(false); optionswindow->Activate(); mainwindow->Disable(); } else if (event.source == button_applyoptions or event.source == button_closeoptions) { EmitEvent(EVENT_WINDOWCLOSE, optionswindow); } break; case EVENT_WIDGETSELECT: if (event.source == tabber) { for (int n = 0; n < tabber->items.size(); ++n) { if (n == event.data) { objectpanel->SetHidden(true); scenepanel->SetHidden(false); } else { objectpanel->SetHidden(false); scenepanel->SetHidden(true); } } } break; case EVENT_WINDOWCLOSE: if (event.source == mainwindow) { if (Confirm("Are you sure you want to quit?")) { return 0; } } else if (event.source == optionswindow) { mainwindow->Enable(); mainwindow->Activate(); optionswindow->SetHidden(true); } case EVENT_PRINT: console->AddText(event.text + "\n"); break; } world->Update(); world->Render(framebuffer); } return 0; } Cyclone - Ultra Game System - Component Preprocessor - Tex2TGA - Darkness Awaits Template (Leadwerks) If you like my work, consider supporting me on Patreon! Link to comment Share on other sites More sharing options...
Josh Posted August 27, 2022 Author Share Posted August 27, 2022 2 hours ago, reepblue said: Still getting the clipping issue in the 3D render but the first draw call seems to be better. Update your project to get the new shaders. 2 hours ago, reepblue said: FYI, unless I'm not doing this correctly, adding in a 3D viewport seems to slow everything down. Also, I can't seem to resize the viewport after the window size has been changed. Okay, a few things...first, your application seems to be a real-time app, but you probably want an event-driven application that only renders when the window is painted. If that is the case, read on, otherwise my solution would be slightly different. So the code below changes the event look to stop until an event occurs, and only render when a WINDOWPAINT event occurs. In either case, for viewports to be resizable, you cannot have multithreaded rendering enabled. To turn this off call ASyncRender(false) before the engine is initialized. This will run all the rendering and culling code on the same thread as the logic thread, in order, the same way Leadwerks works. So it's much slower like this (but also more responsive because there's less latency.) The reason this is required is because you can't have the window resizing on one thread while Vulkan is rendering to it on another. No way this can be allowed to happen, and the code to use a mutex to prevent that would be extremely complicated and probably cancel out the benefits of multithreading. This is probably why you don't see a lot of resizable game windows anymore. The code below is how our editor is structured, and it does have a resizable viewport. A Vulkan validation error is occuring the second time the viewport is resized, but it's probably a fairly minor issue that will be easy for me to fix. In order for a window to be resizable at all, it must have the WINDOW_RESIZABLE flag. You cannot resize a window that does not have this flag. You also cannot create a framebuffer on a resizable window if ASyncRender(false) has not been called, for the reason explained above (Vulkan trying to render to a framebuffer as another thread is resizing it). #include "UltraEngine.h" using namespace UltraEngine; const int TOOLBARHEIGHT = 48; const int STATUSBARHEIGHT = 32; const int SIDEPANELWIDTH = 300; const int CONSOLEHEIGHT = 120; int main(int argc, const char* argv[]) { ASyncRender(false); //Get displays auto displays = GetDisplays(); //Create window auto mainwindow = CreateWindow("Ultra App Kit", 0, 0, 1024, 768, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR | WINDOW_RESIZABLE); mainwindow->SetMinSize(800, 600); //Create user interface auto ui = CreateInterface(mainwindow); iVec2 sz = ui->root->ClientSize(); //------------------------------------------------------- // Create main menu //------------------------------------------------------- auto mainmenu = CreateMenu("", ui->root); //File menu auto menu_file = CreateMenu("File", mainmenu); CreateMenu("New", menu_file); CreateMenu("", menu_file); auto menu_open = CreateMenu("Open", menu_file); auto menu_save = CreateMenu("Save", menu_file); auto menu_saveas = CreateMenu("Save as...", menu_file); CreateMenu("", menu_file); auto menu_recentfiles = CreateMenu("Recent files", menu_file); std::array<shared_ptr<Widget>, 10> menu_recentfile; for (int n = 0; n < menu_recentfile.size(); ++n) { menu_recentfile[n] = CreateMenu("Recent file " + String(n + 1), menu_recentfiles); } CreateMenu("", menu_file); auto menu_exit = CreateMenu("Exit", menu_file); //Edit menu auto menu_edit = CreateMenu("Edit", mainmenu); CreateMenu("Undo", menu_edit); CreateMenu("Redo", menu_edit); CreateMenu("", menu_edit); CreateMenu("Cut", menu_edit); CreateMenu("Copy", menu_edit); CreateMenu("Past", menu_edit); CreateMenu("", menu_edit); CreateMenu("Select all", menu_edit); CreateMenu("Select none", menu_edit); CreateMenu("Invert selection", menu_edit); //View menu auto menu_view = CreateMenu("View", mainmenu); auto menu_perspective = CreateMenu("Perspective", menu_view); auto menu_top = CreateMenu("XZ - Top", menu_view); auto menu_side = CreateMenu("XZ - Side", menu_view); auto menu_front = CreateMenu("XY - Front", menu_view); menu_perspective->SetState(true); //Tools menu auto menu_tools = CreateMenu("Tools", mainmenu); auto menu_options = CreateMenu("Options", menu_tools); //Help menu auto menu_help = CreateMenu("Help", mainmenu); auto menu_helpcontents = CreateMenu("Help Contents", menu_help); auto menu_about = CreateMenu("About", menu_help); //------------------------------------------------------- // Create toolbar //------------------------------------------------------- auto toolbar = CreatePanel(0, mainmenu->size.y, sz.x, TOOLBARHEIGHT, ui->root); toolbar->SetLayout(1, 1, 1, 0); int x = 4, y = 4; auto toolbarbutton_open = CreateButton("", x, y, TOOLBARHEIGHT - 8, TOOLBARHEIGHT - 8, toolbar, BUTTON_TOOLBAR); toolbarbutton_open->SetFontScale(2); toolbarbutton_open->SetIcon(LoadIcon("https://raw.githubusercontent.com/Leadwerks/Documentation/private/Assets/Icons/open.svg")); x += TOOLBARHEIGHT; auto toolbarbutton_save = CreateButton("", x, y, TOOLBARHEIGHT - 8, TOOLBARHEIGHT - 8, toolbar, BUTTON_TOOLBAR); toolbarbutton_save->SetFontScale(2); toolbarbutton_save->SetIcon(LoadIcon("https://raw.githubusercontent.com/Leadwerks/Documentation/private/Assets/Icons/save.svg")); x += TOOLBARHEIGHT; auto toolbarbutton_options = CreateButton("", x, y, TOOLBARHEIGHT - 8, TOOLBARHEIGHT - 8, toolbar, BUTTON_TOOLBAR); toolbarbutton_options->SetFontScale(2); toolbarbutton_options->SetIcon(LoadIcon("https://raw.githubusercontent.com/Leadwerks/Documentation/private/Assets/Icons/settings.svg")); x += TOOLBARHEIGHT; auto toolbarbutton_help = CreateButton("", x, y, TOOLBARHEIGHT - 8, TOOLBARHEIGHT - 8, toolbar, BUTTON_TOOLBAR); toolbarbutton_help->SetIcon(LoadIcon("https://raw.githubusercontent.com/Leadwerks/Documentation/private/Assets/Icons/help.svg")); toolbarbutton_help->SetFontScale(2); //------------------------------------------------------- // Create status bar //------------------------------------------------------- auto statusbar = CreatePanel(0, sz.y - STATUSBARHEIGHT, sz.x, STATUSBARHEIGHT, ui->root); statusbar->SetLayout(1, 1, 0, 1); auto statusbarlabel_view = CreateLabel("Perspective", 4, 0, 300, statusbar->size.y, statusbar, LABEL_LEFT | LABEL_MIDDLE); //------------------------------------------------------- // Create main panel //------------------------------------------------------- auto mainpanel = CreatePanel(0, toolbar->position.y + toolbar->size.y, sz.x, sz.y - toolbar->size.y - toolbar->position.y - statusbar->size.y, ui->root); mainpanel->SetLayout(1, 1, 1, 1); sz = mainpanel->ClientSize(); //Create console auto console = CreateTextArea(4, mainpanel->size.y - CONSOLEHEIGHT, mainpanel->size.x - SIDEPANELWIDTH - 8, CONSOLEHEIGHT - 28 - 4, mainpanel); console->SetLayout(1, 1, 0, 1); auto widget_input = CreateTextField(4, mainpanel->size.y - 28, mainpanel->size.x - SIDEPANELWIDTH - 8, 28, mainpanel, TEXTFIELD_ENTERKEYACTIONEVENT); widget_input->SetLayout(1, 1, 0, 1); //Main viewport auto mainviewport = CreatePanel(4, 4, mainpanel->size.x - SIDEPANELWIDTH - 8, mainpanel->size.y - 8 - CONSOLEHEIGHT, mainpanel, PANEL_BORDER); mainviewport->SetLayout(1, 1, 1, 1); mainviewport->SetColor(0, 0, 0); auto viewport = CreateWindow("", mainviewport->GetPosition(true).x, mainviewport->GetPosition(true).y, mainviewport->GetSize().x, mainviewport->GetSize().y, mainwindow, WINDOW_CHILD | WINDOW_CLIENTCOORDS | WINDOW_RESIZABLE); //Create a world auto world = CreateWorld(); //Create a framebuffer auto framebuffer = CreateFramebuffer(viewport); //Create a camera auto camera = CreateCamera(world); camera->SetClearColor(0.125); camera->SetFOV(70); camera->SetPosition(0, 0, -3); //Create a light auto light = CreateLight(world, LIGHT_DIRECTIONAL); light->SetRotation(35, 45, 0); //Create a box auto box = CreateBox(world); //------------------------------------------------------- // Create side panel //------------------------------------------------------- auto sidepanel = CreatePanel(sz.x - SIDEPANELWIDTH, 0, SIDEPANELWIDTH, sz.y, mainpanel); sidepanel->SetLayout(0, 1, 1, 1); auto tabber = CreateTabber(0, 0, SIDEPANELWIDTH, sz.y, sidepanel); tabber->SetLayout(1, 1, 1, 1); tabber->AddItem("Objects", true); tabber->AddItem("Scene"); //Object panel sz = tabber->ClientSize(); auto objectpanel = CreatePanel(0, 0, sz.x, sz.y, tabber); objectpanel->SetLayout(1, 1, 1, 1); //tabber->items[0].extra = objectpanel; //Scene panel auto scenepanel = CreatePanel(0, 0, sz.x, sz.y, tabber); scenepanel->SetHidden(true); scenepanel->SetLayout(1, 1, 1, 1); //tabber->items[1].extra = scenepanel; x = 8; y = 12; CreateLabel("Category:", x, y, 200, 30, objectpanel); y += 24; auto objectcategorybox = CreateComboBox(x, y, sz.x - x * 2, 30, objectpanel); objectcategorybox->SetLayout(1, 1, 1, 0); objectcategorybox->AddItem("Primitives", true); objectcategorybox->AddItem("Extended primitives"); objectcategorybox->AddItem("Cameras"); objectcategorybox->AddItem("Lights"); objectcategorybox->AddItem("Splines"); y += 44; CreateLabel("Object:", x, y, 200, 30, objectpanel); y += 24; auto objectbox = CreateComboBox(x, y, sz.x - x * 2, 30, objectpanel); objectbox->SetLayout(1, 1, 1, 0); objectbox->AddItem("Box", true); objectbox->AddItem("Wedge"); objectbox->AddItem("Cylinder"); objectbox->AddItem("Sphere"); y += 44; x = 80; CreateButton("Create", x, y, sz.x - 2 * x, 28, objectpanel); x = 8; y = 12; auto scenebrowser = CreateTreeView(x, y, sz.x - 2 * x, 400 - y, scenepanel); scenebrowser->SetLayout(1, 1, 1, 1); auto node = scenebrowser->root->AddNode("Scene"); node->Expand(); node->AddNode("Box 1"); node->AddNode("Box 2"); node->AddNode("Box 3"); y += scenebrowser->size.y + x; auto propertiespanel = CreatePanel(x, y, sz.x, sz.y - y, scenepanel); propertiespanel->SetLayout(1, 1, 0, 1); y = 8; CreateLabel("Name:", x, y + 4, 60, 30, propertiespanel); auto widget_name = CreateTextField(x * 2 + 60, y, sz.x - 4 * x - 60, 30, propertiespanel); widget_name->SetText("Box 1"); y += 40; CreateLabel("Value:", x, y + 4, 60, 30, propertiespanel); CreateSlider(x * 2 + 60, y, sz.x - 4 * x - 60, 30, propertiespanel, SLIDER_HORIZONTAL | SLIDER_TRACKBAR); y += 40; //------------------------------------------------------- // Options window //------------------------------------------------------- auto optionswindow = CreateWindow("Options", 0, 0, 400, 500, mainwindow, WINDOW_HIDDEN | WINDOW_TITLEBAR | WINDOW_CENTER); auto optionsui = CreateInterface(optionswindow); sz = optionsui->root->ClientSize(); auto button_option1 = CreateButton("Option 1", 12, 12, 300, 30, optionsui->root, BUTTON_CHECKBOX); button_option1->SetState(WIDGETSTATE_SELECTED); auto button_option2 = CreateButton("Option 2", 12, 12 + 32, 300, 30, optionsui->root, BUTTON_RADIO); button_option2->SetState(WIDGETSTATE_SELECTED); auto button_option3 = CreateButton("Option 3", 12, 12 + 32 * 2, 300, 30, optionsui->root, BUTTON_RADIO); auto button_applyoptions = CreateButton("OK", sz.x - 2 * (8 + 80), sz.y - 8 - 30, 80, 30, optionsui->root, BUTTON_OK); auto button_closeoptions = CreateButton("Cancel", sz.x - 8 - 80, sz.y - 8 - 30, 80, 30, optionsui->root, BUTTON_CANCEL); //------------------------------------------------------- // Main loop //------------------------------------------------------- while (true) { const Event event = WaitEvent(); switch (event.id) { case EVENT_WINDOWSIZE: if (event.source == mainwindow) { // If the window resize event is captured auto window = event.source->As<UltraEngine::Window>(); // Get the new size of the applications window UltraEngine::iVec2 sz = mainwindow->ClientSize(); // Set the position and size of the viewport window viewport->SetShape(mainviewport->GetPosition(true).x, mainviewport->GetPosition(true).y, mainviewport->GetSize().x, mainviewport->GetSize().y); } break; case EVENT_WIDGETACTION: if (event.source == menu_exit) { EmitEvent(EVENT_WINDOWCLOSE, mainwindow); } else if (event.source == menu_open) { RequestFile("Open File"); } else if (event.source == menu_save or event.source == menu_saveas) { RequestFile("Save File", "", "All Files", 0, true); } else if (event.source == menu_helpcontents) { RunFile("https://www.ultraengine.com/learn"); } else if (event.source == menu_about) { Notify("Ultra App Kit"); } else if (event.source == menu_perspective or event.source == menu_top or event.source == menu_side or event.source == menu_front) { menu_perspective->SetState(WIDGETSTATE_UNSELECTED); menu_top->SetState(WIDGETSTATE_UNSELECTED); menu_side->SetState(WIDGETSTATE_UNSELECTED); menu_front->SetState(WIDGETSTATE_UNSELECTED); auto menuitem = event.source->As<Widget>(); menuitem->SetState(WIDGETSTATE_SELECTED); statusbarlabel_view->SetText(menuitem->text); } else if (event.source == toolbarbutton_open) { EmitEvent(EVENT_WIDGETACTION, menu_open); } else if (event.source == toolbarbutton_save) { EmitEvent(EVENT_WIDGETACTION, menu_save); } else if (event.source == toolbarbutton_options) { EmitEvent(EVENT_WIDGETACTION, menu_options); } else if (event.source == toolbarbutton_help) { EmitEvent(EVENT_WIDGETACTION, menu_helpcontents); } else if (event.source == widget_input) { if (!widget_input->text.empty()) { console->AddText("\n" + widget_input->text); widget_input->SetText(""); } widget_input->Activate(); } else if (event.source == menu_options) { optionswindow->SetHidden(false); optionswindow->Activate(); mainwindow->Disable(); } else if (event.source == button_applyoptions or event.source == button_closeoptions) { EmitEvent(EVENT_WINDOWCLOSE, optionswindow); } break; case EVENT_WIDGETSELECT: if (event.source == tabber) { for (int n = 0; n < tabber->items.size(); ++n) { if (n == event.data) { objectpanel->SetHidden(true); scenepanel->SetHidden(false); } else { objectpanel->SetHidden(false); scenepanel->SetHidden(true); } } } break; case EVENT_WINDOWCLOSE: if (event.source == mainwindow) { if (Confirm("Are you sure you want to quit?")) { return 0; } } else if (event.source == optionswindow) { mainwindow->Enable(); mainwindow->Activate(); optionswindow->SetHidden(true); } break; case EVENT_WINDOWPAINT: if (event.source == viewport) world->Render(framebuffer); break; } } return 0; } My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted August 27, 2022 Author Share Posted August 27, 2022 Now if you wanted to make a real-time application with a resizable viewport, we just wrap the event loop up in a while statement, remove the WINDOWPAINT event handling, and add the world Update() and Render() to the end. This would be appropriate for something like a particle editor that is continuously rendering. However, since this is using ASyncRender(false) the renderer will be much slower than multithreaded rendering (probably about the same speed as Leadwerks). I still get a validation error upon resizing the window, but it's probably easy to fix that. This will also make the GUI not as snappy as it normally would be, because we are intermittently spending a lot of time performing some fairly heavy computational tasks, and the world Update method also pauses the thread if it is running faster than 60 hz. #include "UltraEngine.h" using namespace UltraEngine; const int TOOLBARHEIGHT = 48; const int STATUSBARHEIGHT = 32; const int SIDEPANELWIDTH = 300; const int CONSOLEHEIGHT = 120; int main(int argc, const char* argv[]) { ASyncRender(false); //Get displays auto displays = GetDisplays(); //Create window auto mainwindow = CreateWindow("Ultra App Kit", 0, 0, 1024, 768, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR | WINDOW_RESIZABLE); mainwindow->SetMinSize(800, 600); //Create user interface auto ui = CreateInterface(mainwindow); iVec2 sz = ui->root->ClientSize(); //------------------------------------------------------- // Create main menu //------------------------------------------------------- auto mainmenu = CreateMenu("", ui->root); //File menu auto menu_file = CreateMenu("File", mainmenu); CreateMenu("New", menu_file); CreateMenu("", menu_file); auto menu_open = CreateMenu("Open", menu_file); auto menu_save = CreateMenu("Save", menu_file); auto menu_saveas = CreateMenu("Save as...", menu_file); CreateMenu("", menu_file); auto menu_recentfiles = CreateMenu("Recent files", menu_file); std::array<shared_ptr<Widget>, 10> menu_recentfile; for (int n = 0; n < menu_recentfile.size(); ++n) { menu_recentfile[n] = CreateMenu("Recent file " + String(n + 1), menu_recentfiles); } CreateMenu("", menu_file); auto menu_exit = CreateMenu("Exit", menu_file); //Edit menu auto menu_edit = CreateMenu("Edit", mainmenu); CreateMenu("Undo", menu_edit); CreateMenu("Redo", menu_edit); CreateMenu("", menu_edit); CreateMenu("Cut", menu_edit); CreateMenu("Copy", menu_edit); CreateMenu("Past", menu_edit); CreateMenu("", menu_edit); CreateMenu("Select all", menu_edit); CreateMenu("Select none", menu_edit); CreateMenu("Invert selection", menu_edit); //View menu auto menu_view = CreateMenu("View", mainmenu); auto menu_perspective = CreateMenu("Perspective", menu_view); auto menu_top = CreateMenu("XZ - Top", menu_view); auto menu_side = CreateMenu("XZ - Side", menu_view); auto menu_front = CreateMenu("XY - Front", menu_view); menu_perspective->SetState(true); //Tools menu auto menu_tools = CreateMenu("Tools", mainmenu); auto menu_options = CreateMenu("Options", menu_tools); //Help menu auto menu_help = CreateMenu("Help", mainmenu); auto menu_helpcontents = CreateMenu("Help Contents", menu_help); auto menu_about = CreateMenu("About", menu_help); //------------------------------------------------------- // Create toolbar //------------------------------------------------------- auto toolbar = CreatePanel(0, mainmenu->size.y, sz.x, TOOLBARHEIGHT, ui->root); toolbar->SetLayout(1, 1, 1, 0); int x = 4, y = 4; auto toolbarbutton_open = CreateButton("", x, y, TOOLBARHEIGHT - 8, TOOLBARHEIGHT - 8, toolbar, BUTTON_TOOLBAR); toolbarbutton_open->SetFontScale(2); toolbarbutton_open->SetIcon(LoadIcon("https://raw.githubusercontent.com/Leadwerks/Documentation/private/Assets/Icons/open.svg")); x += TOOLBARHEIGHT; auto toolbarbutton_save = CreateButton("", x, y, TOOLBARHEIGHT - 8, TOOLBARHEIGHT - 8, toolbar, BUTTON_TOOLBAR); toolbarbutton_save->SetFontScale(2); toolbarbutton_save->SetIcon(LoadIcon("https://raw.githubusercontent.com/Leadwerks/Documentation/private/Assets/Icons/save.svg")); x += TOOLBARHEIGHT; auto toolbarbutton_options = CreateButton("", x, y, TOOLBARHEIGHT - 8, TOOLBARHEIGHT - 8, toolbar, BUTTON_TOOLBAR); toolbarbutton_options->SetFontScale(2); toolbarbutton_options->SetIcon(LoadIcon("https://raw.githubusercontent.com/Leadwerks/Documentation/private/Assets/Icons/settings.svg")); x += TOOLBARHEIGHT; auto toolbarbutton_help = CreateButton("", x, y, TOOLBARHEIGHT - 8, TOOLBARHEIGHT - 8, toolbar, BUTTON_TOOLBAR); toolbarbutton_help->SetIcon(LoadIcon("https://raw.githubusercontent.com/Leadwerks/Documentation/private/Assets/Icons/help.svg")); toolbarbutton_help->SetFontScale(2); //------------------------------------------------------- // Create status bar //------------------------------------------------------- auto statusbar = CreatePanel(0, sz.y - STATUSBARHEIGHT, sz.x, STATUSBARHEIGHT, ui->root); statusbar->SetLayout(1, 1, 0, 1); auto statusbarlabel_view = CreateLabel("Perspective", 4, 0, 300, statusbar->size.y, statusbar, LABEL_LEFT | LABEL_MIDDLE); //------------------------------------------------------- // Create main panel //------------------------------------------------------- auto mainpanel = CreatePanel(0, toolbar->position.y + toolbar->size.y, sz.x, sz.y - toolbar->size.y - toolbar->position.y - statusbar->size.y, ui->root); mainpanel->SetLayout(1, 1, 1, 1); sz = mainpanel->ClientSize(); //Create console auto console = CreateTextArea(4, mainpanel->size.y - CONSOLEHEIGHT, mainpanel->size.x - SIDEPANELWIDTH - 8, CONSOLEHEIGHT - 28 - 4, mainpanel); console->SetLayout(1, 1, 0, 1); auto widget_input = CreateTextField(4, mainpanel->size.y - 28, mainpanel->size.x - SIDEPANELWIDTH - 8, 28, mainpanel, TEXTFIELD_ENTERKEYACTIONEVENT); widget_input->SetLayout(1, 1, 0, 1); //Main viewport auto mainviewport = CreatePanel(4, 4, mainpanel->size.x - SIDEPANELWIDTH - 8, mainpanel->size.y - 8 - CONSOLEHEIGHT, mainpanel, PANEL_BORDER); mainviewport->SetLayout(1, 1, 1, 1); mainviewport->SetColor(0, 0, 0); auto viewport = CreateWindow("", mainviewport->GetPosition(true).x, mainviewport->GetPosition(true).y, mainviewport->GetSize().x, mainviewport->GetSize().y, mainwindow, WINDOW_CHILD | WINDOW_CLIENTCOORDS | WINDOW_RESIZABLE); //Create a world auto world = CreateWorld(); //Create a framebuffer auto framebuffer = CreateFramebuffer(viewport); //Create a camera auto camera = CreateCamera(world); camera->SetClearColor(0.125); camera->SetFOV(70); camera->SetPosition(0, 0, -3); //Create a light auto light = CreateLight(world, LIGHT_DIRECTIONAL); light->SetRotation(35, 45, 0); //Create a box auto box = CreateBox(world); //------------------------------------------------------- // Create side panel //------------------------------------------------------- auto sidepanel = CreatePanel(sz.x - SIDEPANELWIDTH, 0, SIDEPANELWIDTH, sz.y, mainpanel); sidepanel->SetLayout(0, 1, 1, 1); auto tabber = CreateTabber(0, 0, SIDEPANELWIDTH, sz.y, sidepanel); tabber->SetLayout(1, 1, 1, 1); tabber->AddItem("Objects", true); tabber->AddItem("Scene"); //Object panel sz = tabber->ClientSize(); auto objectpanel = CreatePanel(0, 0, sz.x, sz.y, tabber); objectpanel->SetLayout(1, 1, 1, 1); //tabber->items[0].extra = objectpanel; //Scene panel auto scenepanel = CreatePanel(0, 0, sz.x, sz.y, tabber); scenepanel->SetHidden(true); scenepanel->SetLayout(1, 1, 1, 1); //tabber->items[1].extra = scenepanel; x = 8; y = 12; CreateLabel("Category:", x, y, 200, 30, objectpanel); y += 24; auto objectcategorybox = CreateComboBox(x, y, sz.x - x * 2, 30, objectpanel); objectcategorybox->SetLayout(1, 1, 1, 0); objectcategorybox->AddItem("Primitives", true); objectcategorybox->AddItem("Extended primitives"); objectcategorybox->AddItem("Cameras"); objectcategorybox->AddItem("Lights"); objectcategorybox->AddItem("Splines"); y += 44; CreateLabel("Object:", x, y, 200, 30, objectpanel); y += 24; auto objectbox = CreateComboBox(x, y, sz.x - x * 2, 30, objectpanel); objectbox->SetLayout(1, 1, 1, 0); objectbox->AddItem("Box", true); objectbox->AddItem("Wedge"); objectbox->AddItem("Cylinder"); objectbox->AddItem("Sphere"); y += 44; x = 80; CreateButton("Create", x, y, sz.x - 2 * x, 28, objectpanel); x = 8; y = 12; auto scenebrowser = CreateTreeView(x, y, sz.x - 2 * x, 400 - y, scenepanel); scenebrowser->SetLayout(1, 1, 1, 1); auto node = scenebrowser->root->AddNode("Scene"); node->Expand(); node->AddNode("Box 1"); node->AddNode("Box 2"); node->AddNode("Box 3"); y += scenebrowser->size.y + x; auto propertiespanel = CreatePanel(x, y, sz.x, sz.y - y, scenepanel); propertiespanel->SetLayout(1, 1, 0, 1); y = 8; CreateLabel("Name:", x, y + 4, 60, 30, propertiespanel); auto widget_name = CreateTextField(x * 2 + 60, y, sz.x - 4 * x - 60, 30, propertiespanel); widget_name->SetText("Box 1"); y += 40; CreateLabel("Value:", x, y + 4, 60, 30, propertiespanel); CreateSlider(x * 2 + 60, y, sz.x - 4 * x - 60, 30, propertiespanel, SLIDER_HORIZONTAL | SLIDER_TRACKBAR); y += 40; //------------------------------------------------------- // Options window //------------------------------------------------------- auto optionswindow = CreateWindow("Options", 0, 0, 400, 500, mainwindow, WINDOW_HIDDEN | WINDOW_TITLEBAR | WINDOW_CENTER); auto optionsui = CreateInterface(optionswindow); sz = optionsui->root->ClientSize(); auto button_option1 = CreateButton("Option 1", 12, 12, 300, 30, optionsui->root, BUTTON_CHECKBOX); button_option1->SetState(WIDGETSTATE_SELECTED); auto button_option2 = CreateButton("Option 2", 12, 12 + 32, 300, 30, optionsui->root, BUTTON_RADIO); button_option2->SetState(WIDGETSTATE_SELECTED); auto button_option3 = CreateButton("Option 3", 12, 12 + 32 * 2, 300, 30, optionsui->root, BUTTON_RADIO); auto button_applyoptions = CreateButton("OK", sz.x - 2 * (8 + 80), sz.y - 8 - 30, 80, 30, optionsui->root, BUTTON_OK); auto button_closeoptions = CreateButton("Cancel", sz.x - 8 - 80, sz.y - 8 - 30, 80, 30, optionsui->root, BUTTON_CANCEL); //------------------------------------------------------- // Main loop //------------------------------------------------------- while (true) { while (PeekEvent()) { const Event event = WaitEvent(); switch (event.id) { case EVENT_WINDOWSIZE: if (event.source == mainwindow) { // If the window resize event is captured auto window = event.source->As<UltraEngine::Window>(); // Get the new size of the applications window UltraEngine::iVec2 sz = mainwindow->ClientSize(); // Set the position and size of the viewport window viewport->SetShape(mainviewport->GetPosition(true).x, mainviewport->GetPosition(true).y, mainviewport->GetSize().x, mainviewport->GetSize().y); } break; case EVENT_WIDGETACTION: if (event.source == menu_exit) { EmitEvent(EVENT_WINDOWCLOSE, mainwindow); } else if (event.source == menu_open) { RequestFile("Open File"); } else if (event.source == menu_save or event.source == menu_saveas) { RequestFile("Save File", "", "All Files", 0, true); } else if (event.source == menu_helpcontents) { RunFile("https://www.ultraengine.com/learn"); } else if (event.source == menu_about) { Notify("Ultra App Kit"); } else if (event.source == menu_perspective or event.source == menu_top or event.source == menu_side or event.source == menu_front) { menu_perspective->SetState(WIDGETSTATE_UNSELECTED); menu_top->SetState(WIDGETSTATE_UNSELECTED); menu_side->SetState(WIDGETSTATE_UNSELECTED); menu_front->SetState(WIDGETSTATE_UNSELECTED); auto menuitem = event.source->As<Widget>(); menuitem->SetState(WIDGETSTATE_SELECTED); statusbarlabel_view->SetText(menuitem->text); } else if (event.source == toolbarbutton_open) { EmitEvent(EVENT_WIDGETACTION, menu_open); } else if (event.source == toolbarbutton_save) { EmitEvent(EVENT_WIDGETACTION, menu_save); } else if (event.source == toolbarbutton_options) { EmitEvent(EVENT_WIDGETACTION, menu_options); } else if (event.source == toolbarbutton_help) { EmitEvent(EVENT_WIDGETACTION, menu_helpcontents); } else if (event.source == widget_input) { if (!widget_input->text.empty()) { console->AddText("\n" + widget_input->text); widget_input->SetText(""); } widget_input->Activate(); } else if (event.source == menu_options) { optionswindow->SetHidden(false); optionswindow->Activate(); mainwindow->Disable(); } else if (event.source == button_applyoptions or event.source == button_closeoptions) { EmitEvent(EVENT_WINDOWCLOSE, optionswindow); } break; case EVENT_WIDGETSELECT: if (event.source == tabber) { for (int n = 0; n < tabber->items.size(); ++n) { if (n == event.data) { objectpanel->SetHidden(true); scenepanel->SetHidden(false); } else { objectpanel->SetHidden(false); scenepanel->SetHidden(true); } } } break; case EVENT_WINDOWCLOSE: if (event.source == mainwindow) { if (Confirm("Are you sure you want to quit?")) { return 0; } } else if (event.source == optionswindow) { mainwindow->Enable(); mainwindow->Activate(); optionswindow->SetHidden(true); } } } box->Turn(0, 1, 0); world->Update(); world->Render(framebuffer); } return 0; } My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted August 27, 2022 Author Share Posted August 27, 2022 That may seem confusing at first, but it's a pretty straightforward way to handle some very complicated issues. It took quite a few iterations to figure all this stuff out but the solution I've got gives you a lot of power to do whatever you want with minimal fuss. And it turns out that slower speed with lower latency is actually ideal for a GUI app, because you are more concerned with responsiveness than the speed at which it can render over and over. My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
SpiderPig Posted August 27, 2022 Share Posted August 27, 2022 16 hours ago, Josh said: If you click the "run install scripts manually" options in the settings you can run the bat file yourself and see any info it prints out. Downloaded client9. Installed fine manually, automatically however still had missing files in the Library folder in the client app directory. No errors in manually or automatic install. Perhaps now that tar.exe and it's two dll's are gone its working ok? Running patch.bat as admin after an auto install put the .lib files into the Library folder. Both debug and release build fine even though both show these errors. The errors are across a few files. Release runs fine but debug still has the error; Validation Error: [ VUID-VkDeviceCreateInfo-pNext-pNext ] Object 0: VK_NULL_HANDLE, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x901f59ec | vkCreateDevice: pCreateInfo->pNext chain includes a structure with unknown VkStructureType (1000314007); Allowed structures are [VkDeviceDiagnosticsConfigCreateInfoNV, VkDeviceGroupDeviceCreateInfo, VkDeviceMemoryOverallocationCreateInfoAMD, VkDevicePrivateDataCreateInfoEXT, VkPhysicalDevice16BitStorageFeatures, VkPhysicalDevice4444FormatsFeaturesEXT, VkPhysicalDevice8BitStorageFeatures, VkPhysicalDeviceASTCDecodeFeaturesEXT, VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT, VkPhysicalDeviceBufferDeviceAddressFeatures, VkPhysicalDeviceBufferDeviceAddressFeaturesEXT, VkPhysicalDeviceCoherentMemoryFeaturesAMD, VkPhysicalDeviceComputeShaderDerivativesFeaturesNV, VkPhysicalDeviceConditionalRenderingFeaturesEXT, VkPhysicalDeviceCooperativeMatrixFeaturesNV, VkPhysicalDeviceCornerSampledImageFeaturesNV, VkPhysicalDeviceCoverageReductionModeFeaturesNV, VkPhysicalDeviceCustomBorderColorFeaturesEXT, VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV, VkPhysicalDeviceDepthClipEnableFeaturesEXT, VkPhysicalDeviceDescriptorIndexingFeatures, VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV, VkPhysicalDeviceDiagnosticsConfigFeaturesNV, VkPhysicalDeviceExclusiveScissorFeaturesNV, VkPhysicalDeviceExtendedDynamicStateFeaturesEXT, VkPhysicalDeviceFeatures2, VkPhysicalDeviceFragmentDensityMap2FeaturesEXT, VkPhysicalDeviceFragmentDensityMapFeaturesEXT, VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV, VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT, VkPhysicalDeviceHostQueryResetFeatures, VkPhysicalDeviceImageRobustnessFeaturesEXT, VkPhysicalDeviceImagelessFramebufferFeatures, VkPhysicalDeviceIndexTypeUint8FeaturesEXT, VkPhysicalDeviceInlineUniformBlockFeaturesEXT, VkPhysicalDeviceLineRasterizationFeaturesEXT, VkPhysicalDeviceMemoryPriorityFeaturesEXT, VkPhysicalDeviceMeshShaderFeaturesNV, VkPhysicalDeviceMultiviewFeatures, VkPhysicalDevicePerformanceQueryFeaturesKHR, VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT, VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR, VkPhysicalDevicePortabilitySubsetFeaturesKHR, VkPhysicalDevicePrivateDataFeaturesEXT, VkPhysicalDeviceProtectedMemoryFeatures, VkPhysicalDeviceRayTracingFeaturesKHR, VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV, VkPhysicalDeviceRobustness2FeaturesEXT, VkPhysicalDeviceSamplerYcbcrConversionFeatures, VkPhysicalDeviceScalarBlockLayoutFeatures, VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures, VkPhysicalDeviceShaderAtomicFloatFeaturesEXT, VkPhysicalDeviceShaderAtomicInt64Features, VkPhysicalDeviceShaderClockFeaturesKHR, VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT, VkPhysicalDeviceShaderDrawParametersFeatures, VkPhysicalDeviceShaderFloat16Int8Features, VkPhysicalDeviceShaderImageFootprintFeaturesNV, VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL, VkPhysicalDeviceShaderSMBuiltinsFeaturesNV, VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures, VkPhysicalDeviceShadingRateImageFeaturesNV, VkPhysicalDeviceSubgroupSizeControlFeaturesEXT, VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT, VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT, VkPhysicalDeviceTimelineSemaphoreFeatures, VkPhysicalDeviceTransformFeedbackFeaturesEXT, VkPhysicalDeviceUniformBufferStandardLayoutFeatures, VkPhysicalDeviceVariablePointersFeatures, VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT, VkPhysicalDeviceVulkan11Features, VkPhysicalDeviceVulkan12Features, VkPhysicalDeviceVulkanMemoryModelFeatures, VkPhysicalDeviceYcbcrImageArraysFeaturesEXT]. This error is based on the Valid Usage documentation for version 154 of the Vulkan header. It is possible that you are using a struct from a private extension or an extension that was added to a later version of the Vulkan header, in which case the use of pCreateInfo->pNext is undefined and may not work correctly with validation enabled The Vulkan spec states: Each pNext member of any structure (including this one) in the pNext chain must be either NULL or a pointer to a valid instance of VkDeviceDiagnosticsConfigCreateInfoNV, VkDeviceGroupDeviceCreateInfo, VkDeviceMemoryOverallocationCreateInfoAMD, VkDevicePrivateDataCreateInfoEXT, VkPhysicalDevice16BitStorageFeatures, VkPhysicalDevice4444FormatsFeaturesEXT, VkPhysicalDevice8BitStorageFeatures, VkPhysicalDeviceASTCDecodeFeaturesEXT, VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT, VkPhysicalDeviceBufferDeviceAddressFeatures, VkPhysicalDeviceBufferDeviceAddressFeaturesEXT, VkPhysicalDeviceCoherentMemoryFeaturesAMD, VkPhysicalDeviceComputeShaderDerivativesFeaturesNV, VkPhysicalDeviceConditionalRenderingFeaturesEXT, VkPhysicalDeviceCooperativeMatrixFeaturesNV, VkPhysicalDeviceCornerSampledImageFeaturesNV, VkPhysicalDeviceCoverageReductionModeFeaturesNV, VkPhysicalDeviceCustomBorderColorFeaturesEXT, VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV, VkPhysicalDeviceDepthClipEnableFeaturesEXT, VkPhysicalDeviceDescriptorIndexingFeatures, VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV, VkPhysicalDeviceDiagnosticsConfigFeaturesNV, VkPhysicalDeviceExclusiveScissorFeaturesNV, VkPhysicalDeviceExtendedDynamicStateFeaturesEXT, VkPhysicalDeviceFeatures2, VkPhysicalDeviceFragmentDensityMap2FeaturesEXT, VkPhysicalDeviceFragmentDensityMapFeaturesEXT, VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV, VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT, VkPhysicalDeviceHostQueryResetFeatures, VkPhysicalDeviceImageRobustnessFeaturesEXT, VkPhysicalDeviceImagelessFramebufferFeatures, VkPhysicalDeviceIndexTypeUint8FeaturesEXT, VkPhysicalDeviceInlineUniformBlockFeaturesEXT, VkPhysicalDeviceLineRasterizationFeaturesEXT, VkPhysicalDeviceMemoryPriorityFeaturesEXT, VkPhysicalDeviceMeshShaderFeaturesNV, VkPhysicalDeviceMultiviewFeatures, VkPhysicalDevicePerformanceQueryFeaturesKHR, VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT, VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR, VkPhysicalDevicePortabilitySubsetFeaturesKHR, VkPhysicalDevicePrivateDataFeaturesEXT, VkPhysicalDeviceProtectedMemoryFeatures, VkPhysicalDeviceRayTracingFeaturesKHR, VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV, VkPhysicalDeviceRobustness2FeaturesEXT, VkPhysicalDeviceSamplerYcbcrConversionFeatures, VkPhysicalDeviceScalarBlockLayoutFeatures, VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures, VkPhysicalDeviceShaderAtomicFloatFeaturesEXT, VkPhysicalDeviceShaderAtomicInt64Features, VkPhysicalDeviceShaderClockFeaturesKHR, VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT, VkPhysicalDeviceShaderDrawParametersFeatures, VkPhysicalDeviceShaderFloat16Int8Features, VkPhysicalDeviceShaderImageFootprintFeaturesNV, VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL, VkPhysicalDeviceShaderSMBuiltinsFeaturesNV, VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures, VkPhysicalDeviceShadingRateImageFeaturesNV, VkPhysicalDeviceSubgroupSizeControlFeaturesEXT, VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT, VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT, VkPhysicalDeviceTimelineSemaphoreFeatures, VkPhysicalDeviceTransformFeedbackFeaturesEXT, VkPhysicalDeviceUniformBufferStandardLayoutFeatures, VkPhysicalDeviceVariablePointersFeatures, VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT, VkPhysicalDeviceVulkan11Features, VkPhysicalDeviceVulkan12Features, VkPhysicalDeviceVulkanMemoryModelFeatures, or VkPhysicalDeviceYcbcrImageArraysFeaturesEXT (https://vulkan.lunarg.com/doc/view/1.2.154.1/windows/1.2-extensions/vkspec.html#VUID-VkDeviceCreateInfo-pNext-pNext) Do I need to update Vulkan or something? How can I see what version I have installed? Importing a project created with client8 works well. I get a small error icon which I assumed means some files aren't up to date. Didn't know what to do so I clicked the icon and guessed that I press OK which seemed to work. Some more info displayed on this process would be a good idea. Upon opening the updated imported project it can't find UltraEngine.h. Perhaps the paths aren't updating to the new client app directory? Looking in the projects properties that seems to be the case. Link to comment Share on other sites More sharing options...
Josh Posted August 28, 2022 Author Share Posted August 28, 2022 The client app is updated again. It did not actually have any checks to make sure a file downloaded successfully. Now it will re-try the download if it fails a few times, and then stop with an error message if it can't get the file. 10 hours ago, SpiderPig said: Upon opening the updated imported project it can't find UltraEngine.h. Perhaps the paths aren't updating to the new client app directory? Looking in the projects properties that seems to be the case. The application does not currently attempt to modify imported projects but maybe I will add that. 10 hours ago, SpiderPig said: Do I need to update Vulkan or something? How can I see what version I have installed? You might need to update your graphics driver, but if it is initializing Vulkan 1.3 then that structure should be recognized. 1 My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Recommended Posts