Jump to content

MagnetarX10

Members
  • Posts

    10
  • Joined

  • Last visited

Everything posted by MagnetarX10

  1. @Josh Thanks for the help. Here is a version that combines the OpenGL example. This seems to be working fine. This is exactly what I need. #include "UltraEngine.h" #include <GL/GL.h> #pragma comment (lib, "opengl32.lib") using namespace UltraEngine; const int SidePanelWidth = 200; const int Indent = 8; //Custom event ID const EventId EVENT_VIEWPORTRENDER = EventId(101); void GLRender(shared_ptr<Window> viewport) { // Get and set the current size of the viewport iVec2 sz = viewport->ClientSize(); if (sz.x < 1 or sz.y < 1) return; glViewport(0, 0, sz.x, sz.y); // Set clear colour of viewport background glClearColor(0.15f, 0.15f, 0.15f, 1.0f); // Clear colour and depth buffers glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Render our triangle glBegin(GL_TRIANGLES); // Vertex 1 glColor3f(1, 0, 0); glVertex3f(0, 0.5, 0); // Vertex 2 glColor3f(0, 1, 0); glVertex3f(0.5, -0.5, 0); // Vertex 3 glColor3f(0, 0, 1); glVertex3f(-0.5, -0.5, 0); glEnd(); HWND hwnd = viewport->GetHandle(); auto hdc = GetDC(hwnd); SwapBuffers(hdc); ReleaseDC(hwnd, hdc); } // Callback function for resizing the viewport bool ResizeViewport(const Event& ev, shared_ptr<Object> extra) { // If the window resize event is captured auto window = ev.source->As<Window>(); // Get the new size of the applications window iVec2 sz = window->ClientSize(); auto viewport = extra->As<Window>(); // Set the position and size of the viewport window viewport->SetShape(SidePanelWidth, Indent, sz.x - SidePanelWidth - Indent, sz.y - Indent * 2); return true; } int main(int argc, const char* argv[]) { // Disable asynchronous rendering so window resizing will work with 3D graphics AsyncRender(false); // Get the available displays auto displays = GetDisplays(); // Create a window auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR | WINDOW_RESIZABLE); // Create user interface auto ui = CreateInterface(window); // Get the size of the user interface iVec2 sz = ui->background->ClientSize(); // Create a treeview widget auto treeview = CreateTreeView(Indent, Indent, SidePanelWidth - Indent * 2, sz.y - Indent * 2, ui->root); // Anchor left, top and bottom of treeview widget treeview->SetLayout(1, 0, 1, 1); // Add nodes to the treeview widget treeview->root->AddNode("Object 1"); treeview->root->AddNode("Object 2"); treeview->root->AddNode("Object 3"); // Create a viewport window auto viewport = CreateWindow("", SidePanelWidth, Indent, sz.x - SidePanelWidth - Indent, sz.y - Indent * 2, window, WINDOW_CHILD); // Adjust the size of the viewport when the applications window is resized (this will callback to our ResizeViewport() function) ListenEvent(EVENT_WINDOWSIZE, window, ResizeViewport, viewport); // Initialize an OpenGL context (get a hdc) HWND hwnd = (HWND)(viewport->GetHandle()); HDC hdc = GetDC(hwnd); // Specify the format of the default framebuffer PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, // Flags PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Framebuffer colour format (R, G, B, A) PFD_TYPE_RGBA, // Framebuffer colour depth (32 bit) 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Number of bits for depth-buffer 24, // Number of bits for stencil-buffer 8, // Number of render-targets in default framebuffer 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; // Select an appropriate pixel format that is supported by the hdc int format = ChoosePixelFormat(hdc, &pfd); if (SetPixelFormat(hdc, format, &pfd) == 0) { RuntimeError("SetPixelFormat() failed."); } // Create an OpenGL rendering context using our current hdc HGLRC glcontext = wglCreateContext(hdc); if (glcontext == NULL) { RuntimeError("wglCreateContext() failed."); } wglMakeCurrent(hdc, glcontext); // This varialble will be used for viewport refreshing bool dirty = false; // Main loop while (true) { // Wait for event const Event ev = WaitEvent(); // Evaluate event switch (ev.id) { case EVENT_WINDOWMOVE: if (not dirty) { dirty = true; EmitEvent(EVENT_VIEWPORTRENDER, viewport); } break; case EVENT_WINDOWSIZE: if (not dirty) { dirty = true; EmitEvent(EVENT_VIEWPORTRENDER, viewport); } break; //Close window when escape key is pressed case EVENT_KEYDOWN: if (ev.source == window and ev.data == KEY_ESCAPE) return 0; break; case EVENT_WINDOWCLOSE: if (ev.source == window) return 0; break; case EVENT_WINDOWPAINT: { if (not dirty) { // This prevents excessive paint events from building up, especially during window resizing // This event is added to the end of the event queue, so if a lot of paint events build up, it will // only cause a single render to be performed. dirty = true; EmitEvent(EVENT_VIEWPORTRENDER, viewport); } } break; case EVENT_VIEWPORTRENDER: GLRender(viewport); dirty = false; break; } } return 0; }
  2. I have the same issue with your EXE. Video link: https://drive.google.com/file/d/1VxprAr7jaH9Ne5sWD-Ecmea1TBPF3Rp4/view?usp=share_link Something about my system, I guess. I could have some weird version issue with drivers or libs. I have two monitors. One is a wide screen monitor. I have seen other issues in the past that were particular to a wide monitor, but this happens on both of my screens. Not sure if any of this information is useful, but here it is:
  3. I may have done this incorrectly, but I updated my Ultra Engine Client to 1.0.1. Then I created a new project. Then I copied and pasted the code from example 3 in Create Instance into main.cpp and rebuilt the project, but I am getting the same behavior as before. I tried it twice and restarted the Ultra Engine Client in case that is a requirement after an update.
  4. Here is a video. I think it is when I click outside of the Viewport region. I think I was doing this accidently initially and did not notice. My assumption is that the viewport is getting invalidated but it does not seem to be sent a render message. I added a little bit of code to track which render event was being sent so I could easily tell when a new render message we sent: case EVENT_VIEWPORTRENDER: world->Render(framebuffer); dirty = false; std::stringstream sstm; sstm << "Viewport render (count=" << ++renderCount << ")"; Print(sstm.str()); break;
  5. @Josh Thanks. On my machine (RTX3080, Windows 11 Pro, AMD CPU), every once in a while the viewport does not paint. I think it is writing a ViewPort Render, but the ViewPort is blank. Tends to happen when I am resizing or moving the window. I have not figure out exactly what causes it.
  6. @reepblue I looked at your code again. I am trying to figure out why it does not work the same as the ListenEvent() callback version I have. I assume that WaitEvent() returns an EVENT_WINDOWSIZE event on a different frequency than the ListenEvent() gets called. Your loop drops down to the Update() and Render() calls which seems like it should be functionally equivalent, but I see a dark window during the resize in your version. This means there is a difference. It has been a very long time since I did Windows programming but maybe the WaitEvent() triggers in the messages that signal a begin and end to the sizing rather than getting message for WM_SIZING which (I think) happens continuously as the user is resizing the window.
  7. @reepblue Thanks! This is very, very helpful. I had worked on this a bit and got it largely working based on @Josh's info. The nice thing about using the ListenEvent() callback is that the 3D Scene will remain visible while the Application Window is resized. I also called Update() to keep it rotating, but I am not sure if that is a bad idea. I added some buttons to change the rotation of the cube, but I do not understand is why it can take a few clicks to get the buttons to work. I assume there is a better way to get the button click or I need to select it based on mouse over? Also, it has been a while since I have programmed C++ ( over a decade), so I don't remember if there is a way to cast the "shared_ptr<Object> extra" parameter in the ListenEvent() callback to a struct or class of objects instead of the single pointer so I don't need to setup the panels and world objects as globals. #include "UltraEngine.h" #include "ComponentSystem.h" using namespace UltraEngine; const int WIN_WIDTH = 1000; const int WIN_HEIGHT = 1000; const int PANEL_WIDTH = 200; const int PADDING = 10; //global "cheats" to pass more data into the resize callback shared_ptr<Window> viewport; shared_ptr<World> world; shared_ptr<Framebuffer> framebuffer; shared_ptr<Widget> left_panel; shared_ptr<Widget> right_panel; //------------------------------------------------------- // Callback to handle dynamic resizing of the Viewport // and panels //------------------------------------------------------- bool ResizeViewport(const Event& ev, shared_ptr<Object> extra) { // If the window resize event is captured auto window = ev.source->As<Window>(); // Get the new size of the applications window iVec2 win_sz = window->ClientSize(); auto viewport = extra->As<Window>(); // Set the position and size of the viewport window AND the panels viewport->SetShape(PANEL_WIDTH + PADDING, PADDING, win_sz.x - (PANEL_WIDTH*2) - (PADDING * 2), win_sz.y - PADDING); if (left_panel != NULL) left_panel->SetShape(0, 0, PANEL_WIDTH, win_sz.y - PADDING); if (right_panel != NULL) right_panel->SetShape(win_sz.x - PANEL_WIDTH, 0, PANEL_WIDTH, win_sz.y - PADDING); //Render the Viewport to keep the 3D scene drawing during the resize world->Update(); world->Render(framebuffer); return true; } int main(int argc, const char* argv[]) { //Disable multithreaded rendering for RESIZABLE Windows AsyncRender(false); auto displays = GetDisplays(); auto window = CreateWindow("Ultra Engine Test", 0, 0, WIN_WIDTH, WIN_HEIGHT, displays[0], WINDOW_TITLEBAR | WINDOW_RESIZABLE); auto font = LoadFont("Fonts/Arial.ttf"); //------------------------------------------------------- // Create 2D User Interface //------------------------------------------------------- auto ui = CreateInterface(window); iVec2 win_sz = ui->root->ClientSize(); left_panel = CreatePanel(0, 0, PANEL_WIDTH, win_sz.y - PADDING, ui->root); left_panel->SetColor(0.20f, 0.20f, 0.20f, 1); left_panel->SetLayout(1, 1, 1, 1); right_panel = CreatePanel(win_sz.x - PANEL_WIDTH, 0, PANEL_WIDTH, win_sz.y - PADDING, ui->root); right_panel->SetColor(0.20f, 0.20f, 0.20f, 1); right_panel->SetLayout(1, 1, 1, 1); //Add Buttons iVec2 left_sz = left_panel->ClientSize(); iVec2 right_sz = right_panel->ClientSize(); auto rotate_left_btn = CreateButton("Rotate Left", left_sz.x / 2 - 75, left_sz.y / 2 - 15, 150, 30, left_panel); auto rotate_right_btn = CreateButton("Rotate Right", right_sz.x / 2 - 75, right_sz.y / 2 - 15, 150, 30, right_panel); //------------------------------------------------------- // Create 3D Viewport //------------------------------------------------------- viewport = CreateWindow("", PANEL_WIDTH + PADDING, PADDING, win_sz.x - (PANEL_WIDTH*2) - (PADDING*2), win_sz.y - PADDING, window, WINDOW_CHILD); framebuffer = CreateFramebuffer(viewport); world = CreateWorld(); // Adjust the size of the viewport when the applications window is resized (this will callback to the ResizeViewport() function) ListenEvent(EVENT_WINDOWSIZE, window, ResizeViewport, viewport); //------------------------------------------------------- // Setup 3D Scene //------------------------------------------------------- //Setup Camera auto camera_3D = CreateCamera(world); camera_3D->SetClearColor(0.125); camera_3D->SetFov(50); camera_3D->SetPosition(0, 0, -3); //Create a light auto light = CreateBoxLight(world); light->SetRotation(35, 45, 0); light->SetRange(-10, 10); //Create a box auto box = CreateBox(world); box->SetColor(0, 0, 1); //Entity component system auto actor = CreateActor(box); auto component = actor->AddComponent<Mover>(); //Rotate the Box component->rotation.y = 45; //------------------------------------------------------- // Main Loop //------------------------------------------------------- while (true) { while (PeekEvent()) { const Event ev = WaitEvent(); switch (ev.id) { case EVENT_WIDGETACTION: //Set the rotation based on the button click if (ev.source == rotate_right_btn) component->rotation.y = -45; else if (ev.source == rotate_left_btn) component->rotation.y = +45; break; case EVENT_WINDOWCLOSE: if (ev.source == window) return 0; break; default: ui->ProcessEvent(ev); break; } } world->Update(); world->Render(framebuffer); } return 0; }
  8. I am new to Ultra Engine and never used Leadworks and have only a little bit of 3D programming experience. I looked as some youtube examples and read what I think are the relevant portions of the programming reference, but I am not 100% sure what to do. I am trying to build something similar to the Editor interface I saw in the Gallery. I want a main window that has a left panel and a right panel with UI controls and a center panel that renders a 3D viewport. I have created the Window, FrameBuffer, World, and Interface Objects. I have a Left and Right Panel on the Interface. I setup 2 cameras, one for the 2D and one for the 3D Objects. I turned off the real-time rendering for the 2D camera. I am sure this is simple, I don't know how to setup the 3D world for only that middle space inside the main window. Currently, the 3D world draws over the 2D UI and I get a lot of flashing.
×
×
  • Create New...