Search the Community
Showing results for tags 'GUI'.
-
Lua Beginner's Guide - first map, Main Menu, Loading Screen and GUI
Dreikblack posted a blog entry in Ultra Tutorials
Prerequisites https://www.ultraengine.com/learn/luasetup?lang=lua Also Lua extension is quite useful for VS Code, if you don't mind Tencent. Map Create a simple map call start.ultra with a brush as floor and a Empty aka pivot with FPSPlayer component How to do it: Now you can press "F5" in the editor, or select "Game" then "run" to run your game to just made map: You can add skybox in Edit > World Settings (at top buttons in the Editor) by choosing skybox.dds from Materials\Environment\Default Main menu, loading screen and GUI Create a simple menu with couple brushes and camera and name this map menu.ultra Now open main.lua. For that open Project tab in top right corner, select root project folder and double click on Open the VSCode.bat file. If this fails make sure you have setup Visual Studio Code correctly https://www.ultraengine.com/learn/luasetup?lang=lua Select all i nfile and delete it from VS Code. Now paste there folllow code with just a Loading screen, almost without anything else and save: -- local before variable means it will be avaiable only in current scope (inside script, funtion, cycle or condition body) -- loading screen vars local loadingWorld = nil local loadingCamera = nil local loadingText = nil local loadingBackground = nil -- for using in main loop local currentWorld = nil local currentUi = nil local displays = GetDisplays() -- You can WINDOW_FULLSCREEN to styles to make game fullscreen, 3rd and 4th are resolution size window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[1], WINDOW_CENTER | WINDOW_TITLEBAR) -- Create a framebuffer, needed for rendering framebuffer = CreateFramebuffer(window) font = LoadFont("Fonts/arial.ttf"); loadingWorld = CreateWorld(); local centerX = framebuffer:GetSize().x * 0.5 local centerY = framebuffer:GetSize().y * 0.5 local labelHeight = framebuffer:GetSize().y * 0.2 loadingBackground = CreateSprite(loadingWorld, framebuffer.size.x, framebuffer.size.y) loadingBackground:SetColor(0.2, 0.2, 0.2); loadingBackground:SetRenderLayers(2); loadingText = CreateSprite(loadingWorld, font, "LOADING", labelHeight, TEXT_CENTER | TEXT_MIDDLE) loadingText:SetPosition(centerX, centerY + labelHeight * 0.5, 0) -- 0 layer - no render, 1 - default render, we will use 2 for UI and sprites loadingText:SetRenderLayers(2) -- Creating camera for sprites, which needs to be orthographic (2D) for UI and sprites if they used as UI loadingCamera = CreateCamera(loadingWorld, PROJECTION_ORTHOGRAPHIC); loadingCamera:SetPosition(centerX, centerY, 0); -- camera render layer should match with stuff that you want to be visible for this camera. RenderLayers is a bit mask, so you can combine few layers, but probably you don't need it in most cases loadingCamera:SetRenderLayers(2) currentWorld = loadingWorld -- simple minimum game loop while window:Closed() == false do -- Garbage collection step collectgarbage() -- getting all events from queue - input, UI etc. while (PeekEvent()) do local event = WaitEvent() -- You need to do it for UI in 3D scene if (currentUi) then currentUi:ProcessEvent(event) end end if (currentWorld) then -- Update game logic (positions, components etc.). By default 60 HZ and not depends on framerate if you have 60+ FPS currentWorld:Update() -- 2nd param is VSync (true by default), 3rd is fps limit. Can by changed dynamically. currentWorld:Render(framebuffer) end end Now if we start a game we will see this loading screen: And once we have a screen we can create a menu to load in. Create MainMenu.lua in Source folder. To do it in Visual Studio Code select "File" then select "New file". Type in "MainMenu.lua" and hit return. A dialog box will open asking where you want to save this file. It should open in the source folder by default but if it dosen't navigate to the source folder and hit return. Paste in the following content for this file and save: local function NewGameButtonCallback(Event, Extra) --this overload currently is not working --EmitEvent(EVENT_GAME_START, nil, 0, 0, 0, 0, 0, nil, "start.ultra") EmitEvent(EVENT_GAME_START) return true end local function ExitButtonCallback(Event, Extra) --to close application os.exit() return true end local function InitMainMenu(mainMenu) mainMenu.world = CreateWorld(); mainMenu.scene = LoadMap(mainMenu.world, "Maps/menu.ultra") --Create user interface local frameSize = framebuffer:GetSize(); mainMenu.ui = CreateInterface(mainMenu.world, font, frameSize) mainMenu.ui:SetRenderLayers(2); --to make backgrount transparent mainMenu.ui.background:SetColor(0.0, 0.0, 0.0, 0.0) --Create camera for GUI mainMenu.uiCamera = CreateCamera(mainMenu.world, PROJECTION_ORTHOGRAPHIC) mainMenu.uiCamera:SetPosition(frameSize.x * 0.5, frameSize.y * 0.5, 0); mainMenu.uiCamera:SetRenderLayers(2); --for correct rendering above 3D scene mainMenu.uiCamera:SetClearMode(CLEAR_DEPTH); --Menu buttons local newGameButton = CreateButton("New game", frameSize.x / 2 - 100, 125, 200, 50, mainMenu.ui.background); ListenEvent(EVENT_WIDGETACTION, newGameButton, NewGameButtonCallback); local exitButton = CreateButton("Exit", frameSize.x / 2 - 100, 200, 200, 50, mainMenu.ui.background); ListenEvent(EVENT_WIDGETACTION, exitButton, ExitButtonCallback); end --functions should be declared after another function that this fucntion uses function CreateMainMenu() local mainMenu = {} InitMainMenu(mainMenu) return mainMenu end Let's get back to main.lua. We need to import main menu script and custom event ids to top: import "Source/MainMenu.lua" --custom events ids EVENT_GAME_START = 1001 EVENT_MAIN_MENU = 1002 Now add after "local currentUi = nil" menu var and callback fuctions for events: framebuffer = nil local menu = nil local function StartGameEventCallback(Event, Extra) --nothing just for now return true; end --function should be declared after vars that this function uses local function MainMenuEventCallback(Event, Extra) menu = CreateMainMenu(); --switching current render and update targets for loop currentWorld = menu.world; currentUi = menu.ui; return true; end Put this above main loop: --to show Loading screen before Main Menu loadingWorld:Render(framebuffer); --ListenEvent are needed to do something in callback function when specific even from specfic source (or not, if 2nd param is nil) emitted ListenEvent(EVENT_GAME_START, nil, StartGameEventCallback); ListenEvent(EVENT_MAIN_MENU, nil, MainMenuEventCallback); --let's try it out! EmitEvent(EVENT_MAIN_MENU) Just in case if something one wrong, current main.lua main.lua We need to modify FPSPlayer component just a little bit. Via Editor you can find it by selecting "Project" ( Top right of the editor screen), select "Source", select "Components", select "Player". Double click "FPSPlayer.lua". Add to its top to other vars a new one (24th line to be precisely) FPSPlayer.doResetMousePosition = true And new condition for mouse position reset in FPSPlayer.lua in Update() at 286 line or find thine line with Ctrl-F and past to search field "window:SetMousePosition(cx, cy)" if doResetMousePosition then window:SetMousePosition(cx, cy) end One big thing left - a game to play. Add Game.lua to project at Source folder: local function GameMenuButtonCallback(Event, Extra) if (KEY_ESCAPE == Event.data and Extra) then local game = Extra local isHidden = game.menuPanel:GetHidden() game.menuPanel:SetHidden(not isHidden) if isHidden then window:SetCursor(CURSOR_DEFAULT) else window:SetCursor(CURSOR_NONE) end if (game.player ~= nil) then --to stop cursor reset to center when menu on game.player.doResetMousePosition = not isHidden end end return false end local function MainMenuButtonCallback(Event, Extra) EmitEvent(EVENT_MAIN_MENU) return true end local function ExitButtonCallback(Event, Extra) os.exit() return true end local function InitGame(game, mapPath) game.world = CreateWorld(); game.scene = LoadScene(game.world, mapPath) for k, entity in pairs(game.scene.entities) do local foundPlayer = entity:GetComponent("FPSPlayer") if (foundPlayer ~= nil) then game.player = foundPlayer; break; end end --Create user interface for game menu local frameSize = framebuffer:GetSize() game.ui = CreateInterface(game.world, font, frameSize) game.ui:SetRenderLayers(2) game.ui.background:SetColor(0.0, 0.0, 0.0, 0.0) game.uiCamera = CreateCamera(game.world, PROJECTION_ORTHOGRAPHIC) game.uiCamera:SetPosition(frameSize.x * 0.5, frameSize.y * 0.5, 0) game.uiCamera:SetRenderLayers(2); game.uiCamera:SetClearMode(CLEAR_DEPTH); --widgets are stays without extra pointers because parent widet, game.ui.background in this case, keep them --to remove widget you should do widget:SetParent(nil) game.menuPanel = CreatePanel(frameSize.x / 2 - 150, frameSize.y / 2 - 125 / 2, 300, 250, game.ui.background) local menuButton = CreateButton("Main menu", 50, 50, 200, 50, game.menuPanel); ListenEvent(EVENT_WIDGETACTION, menuButton, MainMenuButtonCallback); local exitButton = CreateButton("Exit", 50, 150, 200, 50, game.menuPanel); ListenEvent(EVENT_WIDGETACTION, exitButton, ExitButtonCallback); --we don't need game menu on screen while playing game.menuPanel:SetHidden(true); --and we will need it once hitting Esc button ListenEvent(EVENT_KEYUP, window, GameMenuButtonCallback, game); end --functions should be declared after another function that this fucntion uses function CreateGame(mapPath) local game = {} InitGame(game, mapPath) return game end Add new Game include and global var to main.lua: import "Source/Game.lua" local game = nil Update function callbacks at 24 line: local function StartGameEventCallback(Event, Extra) --destroying a main menu menu = nil --to show loading screen loadingWorld:Render(framebuffer) if Event.text ~= nil and Event.text ~= "" then --in lua .. used for string concatenation game = CreateGame("Maps/" .. Event.text); else game = CreateGame("Maps/start.ultra"); end --switching current render and update targets for loop currentWorld = game.world currentUi = game.ui return true; end --function should be declared after vars that this function uses local function MainMenuEventCallback(Event, Extra) --destroying a game instance if one existed game = nil --to show loading screen loadingWorld:Render(framebuffer) menu = CreateMainMenu() --switching current render and update targets for loop currentWorld = menu.world; currentUi = menu.ui; return true; end And in the end we have a game with own menu: All created and modified classes: LuaMenuGameLoad.zip Repository: https://github.com/Dreikblack/LuaTutorialProject/tree/menu-loading-screen-and-gui -
Normal look On my 2nd screen. Normal on 3rd one tho. Also UI mouse input works like if no offset happen #include "UltraEngine.h" using namespace UltraEngine; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; shared_ptr<World> world; shared_ptr<Interface> ui; shared_ptr<Camera> uiCamera; shared_ptr<Widget> btn; shared_ptr<Widget> btn2; static bool EventCallback(const Event& e, shared_ptr<Object> extra) { Print("Callback"); return true; } void initGui() { auto default_font = LoadFont("Fonts\\arial.ttf"); ui = CreateInterface(world, default_font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(0.2f, 0.1f, 0.1f, 1.0f); uiCamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); btn = CreateButton("Btn", 20, 20, 100, 100, ui->root); btn2 = CreateButton("Btn", 20, 150, 100, 100, ui->root); } int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window window = CreateWindow("Ultra Engine", 0, 0, 300, 300, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); //Create a world world = CreateWorld(); //Create a framebuffer framebuffer = CreateFramebuffer(window); //Create a camera auto camera = CreateCamera(world); camera->SetClearColor(0, 0, 0); initGui(); ListenEvent(EVENT_DATA, NULL, EventCallback, btn); auto color = Vec4(0.5, 0, 1, 0.5f); btn->SetColor(color); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { while (PeekEvent()) { const Event ev = WaitEvent(); ui->ProcessEvent(ev); } world->Update(); world->Render(framebuffer); } return 0; }
-
Before first render only first button had new color which looks correct After applying same half-transparent color to both buttons in real time. #include "UltraEngine.h" using namespace UltraEngine; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; shared_ptr<World> world; shared_ptr<Interface> ui; shared_ptr<Camera> uiCamera; shared_ptr<Widget> btn; shared_ptr<Widget> btn2; static bool EventCallback(const Event& e, shared_ptr<Object> extra) { Print("Callback"); return true; } void initGui() { auto default_font = LoadFont("Fonts\\arial.ttf"); ui = CreateInterface(world, default_font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(1.0f, 0.0f, 0.0f, 1.0f); uiCamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); btn = CreateButton("Btn", 20, 20, 100, 100, ui->root); btn2 = CreateButton("Btn", 20, 150, 100, 100, ui->root); } int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window window = CreateWindow("Ultra Engine", 0, 0, 300, 300, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); //Create a world world = CreateWorld(); //Create a framebuffer framebuffer = CreateFramebuffer(window); //Create a camera auto camera = CreateCamera(world); camera->SetClearColor(0, 0, 0); initGui(); ListenEvent(EVENT_DATA, NULL, EventCallback, btn); auto color = Vec4(0.5, 0, 1, 0.5f); btn->SetColor(color); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { if (window->KeyDown(KEY_SPACE)) { btn->SetColor(color); btn2->SetColor(color); } world->Update(); world->Render(framebuffer); } return 0; }
-
#include "UltraEngine.h" using namespace UltraEngine; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; shared_ptr<World> menuWold; shared_ptr<Interface> ui; shared_ptr<Camera> uiCamera; shared_ptr<Widget> panel; shared_ptr<Icon> icon; bool isFirst = true; void initGui() { auto default_font = LoadFont("Fonts\\arial.ttf"); ui = CreateInterface(menuWold, default_font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); uiCamera = CreateCamera(menuWold, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); panel = CreatePanel(10, 50, 64, 64, ui->root, PANEL_DEFAULT); icon = LoadIcon("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Icons/help.svg"); icon->SetColor(0.5, 0.5, 1.0); panel->SetIcon(icon); panel->Redraw(); } int main(int argc, const char* argv[]) { auto displays = GetDisplays(); window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_DEFAULT); menuWold = CreateWorld(); menuWold->RecordStats(); framebuffer = CreateFramebuffer(window); auto light = CreateBoxLight(menuWold); auto camera = CreateCamera(menuWold); camera->SetClearColor(0.125); initGui(); while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { if (window->KeyHit(KEY_SPACE)) { isFirst = !isFirst; if (isFirst) { panel->icon->SetColor(0.5, 0.5, 0.5); panel->SetIcon(panel->icon); panel->Redraw(); } else { panel->icon->SetColor(1.0, 1.0, 0.5); panel->SetIcon(panel->icon); panel->Redraw(); } } menuWold->Update(); menuWold->Render(framebuffer); } return 0; }
-
Style should make UI looks brown (to check if it's loaded correctly) Also file name is looks wrong if it's not Latin symbolsData.zip #include "UltraEngine.h" using namespace UltraEngine; int main(int argc, const char* argv[]) { auto package = LoadPackage("Data.zip"); if (package == nullptr) { Notify("No Package Found"); } package->FileType(""); auto plugin = LoadPlugin("Plugin\\FITextureLoader"); if (!plugin) Notify("No plugin Found"); else Notify("Plugin Found"); auto displays = GetDisplays(); auto window = CreateWindow("Ultra Engine", 0, 0, 500, 500, displays[0], WINDOW_DEFAULT); auto framebuffer = CreateFramebuffer(window); auto world = CreateWorld(); auto font = LoadFont("Fonts\\arial.ttf"); auto ui = CreateInterface(world, font, framebuffer->GetSize()); ui->SetRenderLayers(2); auto uiCamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); ui->LoadColorScheme("Style.json"); auto btn = CreateButton("TEST", 10, 10, 100, 100, ui->root); auto dir = LoadDir("Ru"); for (WString localFile : dir) { btn->SetText(localFile); Print(localFile); } //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { world->Update(); world->Render(framebuffer); } return 0; }
-
Maybe it's only with Cyrillic not sure #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 label1 = CreateLabel("Test", 20, 20, 120, 30, ui->root); auto label2 = CreateLabel("Тест", 20, 50, 120, 30, ui->root, LABEL_BORDER | LABEL_CENTER | LABEL_MIDDLE); while (window->Closed() == false) { WaitEvent(); } return 0; }
-
Press space to add text for left button. Right button have a several lines initially but looks as should be. #include "UltraEngine.h" using namespace UltraEngine; int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create window auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0]); //Create framebuffer auto framebuffer = CreateFramebuffer(window); //Create world auto world = CreateWorld(); //Create main camera auto camera = CreateCamera(world); camera->SetPosition(0, 0, -3); //Load a font auto font = LoadFont("Fonts/arial.ttf"); //Create user interface with a semi-transparent background auto ui = CreateInterface(world, font, framebuffer->size); ui->background->SetColor(0, 0, 0, 0.5); //Create widget iVec2 sz = ui->background->ClientSize(); auto button = CreateButton("Button", 100, 200, 150, 30, ui->background); auto button2 = CreateButton("Button2", 500, 200, 150, 30, ui->background); for (int i = 0; i < 5; i++) { button2->AddText("\ntest"); } //Create camera auto orthocamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); orthocamera->SetClearMode(CLEAR_DEPTH); orthocamera->SetPosition(float(framebuffer->size.x) * 0.5f, float(framebuffer->size.y) * 0.5f, 0); //UI will only appear in orthographic camera orthocamera->SetRenderLayers(2); ui->SetRenderLayers(2); while (true) { if (window->KeyHit(KEY_SPACE)) { button->AddText("\ntest"); } while (PeekEvent()) { const Event ev = WaitEvent(); switch (ev.id) { case EVENT_WINDOWCLOSE: if (ev.source == window) { return 0; } break; default: ui->ProcessEvent(ev); break; } } world->Update(); world->Render(framebuffer); } return 0; }
-
Also GetFont() method would be nice to have for Interface #include "UltraEngine.h" using namespace UltraEngine; int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create window auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0]); //Create framebuffer auto framebuffer = CreateFramebuffer(window); //Create world auto world = CreateWorld(); //Create main camera auto camera = CreateCamera(world); camera->SetPosition(0, 0, -3); auto font = LoadFont("Fonts/arial.ttf"); //Create user interface with a semi-transparent background auto ui = CreateInterface(world, font, framebuffer->size); ui->background->SetColor(0, 0, 0, 0.5); //Create widget iVec2 sz = ui->background->ClientSize(); auto button = CreateButton("Button", sz.x / 2 - 75, sz.y / 2 - 15, 150, 30, ui->background); //Create camera auto orthocamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); orthocamera->SetClearMode(CLEAR_DEPTH); orthocamera->SetPosition(float(framebuffer->size.x) * 0.5f, float(framebuffer->size.y) * 0.5f, 0); //UI will only appear in orthographic camera orthocamera->SetRenderLayers(2); ui->SetRenderLayers(2); if (!button->GetFont()) Notify("Font is null"); else { Notify("Font is not null"); } while (true) { world->Update(); world->Render(framebuffer); } return 0; }
-
Label text breaks if font and text was changed in real time
Dreikblack posted a topic in Bug Reports
#include "UltraEngine.h" using namespace UltraEngine; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; shared_ptr<World> world; shared_ptr<Interface> ui; shared_ptr<Camera> uiCamera; shared_ptr<Widget> label; static bool EventCallback(const Event& e, shared_ptr<Object> extra) { Print("Callback"); return true; } void initGui() { auto default_font = LoadFont("Fonts\\arial.ttf"); ui = CreateInterface(world, default_font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 1.0f); uiCamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); label = CreateLabel("Btn", 20, 20, 100, 100, ui->root); } int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window window = CreateWindow("Ultra Engine", 0, 0, 300, 300, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); //Create a world world = CreateWorld(); //Create a framebuffer framebuffer = CreateFramebuffer(window); //Create a camera auto camera = CreateCamera(world); camera->SetClearColor(0, 0, 0); initGui(); ListenEvent(EVENT_DATA, NULL, EventCallback, label); auto color = Vec4(0.5, 0, 1, 0.5f); label->SetColor(color); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { if (window->KeyDown(KEY_SPACE)) { label->SetText("New Text"); float fonstScale = 14.0 / (float)13; label->SetFontScale(0.9); } world->Update(); world->Render(framebuffer); } return 0; } -
If i drag or create window at 2nd screen ui is looks broken, button can be pressed tho. Also if i try to create full window at non main display it's still appears on main one. Editor UI works fine on all displays. Main screen: Second screen: Third screen: #include "UltraEngine.h" using namespace UltraEngine; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; shared_ptr<World> menuWold; shared_ptr<Interface> ui; shared_ptr<Camera> uiCamera; shared_ptr<Widget> btn; shared_ptr<Widget> btn2; bool fullscreen = false; int displayId = 0; void initGui() { auto default_font = LoadFont("Fonts\\arial.ttf"); ui = CreateInterface(menuWold, default_font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); uiCamera = CreateCamera(menuWold, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); btn = CreateButton("Change display", (float)framebuffer->GetSize().x / 2, framebuffer->GetSize().y / 2, 200, 200, ui->root); btn->SetFontScale(2.0f); btn2 = CreateButton("Fullscreen", (float)framebuffer->GetSize().x / 2, framebuffer->GetSize().y / 2 - 100, 120, 30, ui->root, BUTTON_CHECKBOX); if (fullscreen) btn2->SetState(WIDGETSTATE_SELECTED); } void changeDisplay() { auto displays = GetDisplays(); displayId = ++displayId; if (displayId == displays.size()) { displayId = 0; } if (!fullscreen) { window = CreateWindow("Ultra Engine", 0, 0, 1000, 1000, GetDisplays()[displayId], WINDOW_DEFAULT); } else { window = CreateWindow("Ultra Engine", 0, 0, displays[displayId]->GetSize().width, displays[displayId]->GetSize().height, displays[displayId], WINDOW_DEFAULT | WINDOW_FULLSCREEN); } framebuffer = CreateFramebuffer(window); initGui(); } int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window window = CreateWindow("Ultra Engine", 0, 0, 1000, 1000, displays[0], WINDOW_DEFAULT); //Create a world menuWold = CreateWorld(); //Create a framebuffer framebuffer = CreateFramebuffer(window); //Create light auto light = CreateBoxLight(menuWold); light->SetRange(-10, 10); light->SetRotation(15, 15, 0); light->SetColor(2); //Create camera auto camera = CreateCamera(menuWold); camera->SetClearColor(0.125); camera->SetPosition(0, 0, -3); camera->SetFov(70); //Create scenery auto box = CreateBox(menuWold); initGui(); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { while (PeekEvent()) { const Event ev = WaitEvent(); if (ev.source == btn && ev.id == EVENT_WIDGETACTION) { changeDisplay(); } if (ev.source == btn2 && ev.id == EVENT_WIDGETACTION) { fullscreen = !fullscreen; } ui->ProcessEvent(ev); } menuWold->Update(); menuWold->Render(framebuffer); } return 0; }
-
In 2D seems to be still working: But in 3D: #include "UltraEngine.h" using namespace UltraEngine; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; shared_ptr<World> world; shared_ptr<Interface> ui; shared_ptr<Camera> uiCamera; shared_ptr<Widget> panel1; shared_ptr<Widget> panel2; shared_ptr<Widget> panel3; void initGui() { auto default_font = LoadFont("Fonts\\arial.ttf"); ui = CreateInterface(world, default_font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); uiCamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); panel1 = CreatePanel(20, 20, 100, 100, ui->root); panel1->SetColor(1, 0, 0, 1, WIDGETCOLOR_BACKGROUND); panel2 = CreatePanel(50, 50, 100, 100, panel1); panel2->SetColor(0, 1, 0, 1, WIDGETCOLOR_BACKGROUND); panel3 = CreatePanel(25, 25, 100, 100, panel2); panel3->SetColor(0, 0, 1, 1, WIDGETCOLOR_BACKGROUND); } int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window window = CreateWindow("Ultra Engine", 0, 0, 300, 300, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); //Create a world world = CreateWorld(); world->SetAmbientLight(0); //Create a framebuffer framebuffer = CreateFramebuffer(window); //Create a camera auto camera = CreateCamera(world); camera->SetClearColor(0, 0, 0); initGui(); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { world->Update(); world->Render(framebuffer); } return 0; }
-
#include "UltraEngine.h" using namespace UltraEngine; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; shared_ptr<World> menuWold; shared_ptr<Interface> ui; shared_ptr<Camera> uiCamera; shared_ptr<Widget> panel; shared_ptr<Icon> icon1; shared_ptr<Icon> icon2; bool isFirst = true; void initGui() { auto default_font = LoadFont("Fonts\\arial.ttf"); ui = CreateInterface(menuWold, default_font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); uiCamera = CreateCamera(menuWold, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); panel = CreatePanel(10, 50, 64, 64, ui->root, PANEL_DEFAULT); icon1 = LoadIcon("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Icons/help.svg"); icon2 = LoadIcon("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Icons/new.svg"); panel->SetIcon(icon1); } int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window window = CreateWindow("Ultra Engine", 0, 0, 200, 200, displays[0], WINDOW_DEFAULT); //Create a world menuWold = CreateWorld(); //Create a framebuffer framebuffer = CreateFramebuffer(window); //Create light auto light = CreateBoxLight(menuWold); light->SetRange(-10, 10); light->SetRotation(15, 15, 0); light->SetColor(2); //Create camera auto camera = CreateCamera(menuWold); camera->SetClearColor(0.125); camera->SetPosition(0, 0, -3); camera->SetFov(70); initGui(); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { isFirst = !isFirst; if (isFirst) { panel->SetIcon(icon1); } else { panel->SetIcon(icon2); } menuWold->Update(); menuWold->Render(framebuffer); } return 0; }
-
After resizing icon of yellow armor becomes a blue one. Red also becomes blue. Green stays green. Used to be fine several months ago. #include "UltraEngine.h" #include "ComponentSystem.h" using namespace UltraEngine; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; shared_ptr<World> world; shared_ptr<Interface> ui; shared_ptr<Camera> uiCamera; shared_ptr<Widget> panel; shared_ptr<Widget> panel2; bool isFirst = true; void initGui() { auto default_font = LoadFont("Fonts\\arial.ttf"); ui = CreateInterface(world, default_font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); uiCamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); panel = CreatePanel(10, 10, 50, 50, ui->root, PANEL_DEFAULT); panel2 = CreatePanel(10, 70, 100, 100, ui->root, PANEL_DEFAULT); auto pixmap = LoadPixmap("/gfx/items.wad/armor2");//yellow armor panel->SetPixmap(pixmap); auto pixmap2 = pixmap->Resize(pixmap->size.x * 1.5f, pixmap->size.y * 1.5f);//blue now O_o panel2->SetPixmap(pixmap2); } int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window window = CreateWindow("Ultra Engine", 0, 0, 300, 300, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); //Create a world world = CreateWorld(); world->SetAmbientLight(0); //Create a framebuffer framebuffer = CreateFramebuffer(window); //Load FreeImage plugin auto plg = LoadPlugin("Plugins/FITextureLoader"); auto quakeLoaderPlugin = LoadPlugin("Plugins/QuakeLoader"); //Load model WString path = AppDir(); auto pak = LoadPackage(path + "/PAK0.PAK"); ChangeDir(path); //Create a camera auto camera = CreateCamera(world); camera->SetClearColor(0, 0, 0); camera->Move(0, 0, -0.3); camera->SetRange(0.01, 100); camera->SetFov(70); initGui(); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { world->Update(); world->Render(framebuffer); } return 0; }
-
I don't know if it was changed intentionally somehow but several months ago blocks[0].radius used to make corners rounded #include "UltraEngine.h" using namespace UltraEngine; class CustomWidget : public Panel { CustomWidget::CustomWidget() { cornerradius = 8; blocks.resize(1); } protected: virtual bool Initialize(const int x, const int y, const int width, const int height, shared_ptr<Widget> parent) { return Widget::Initialize(text, x, y, width, height, parent, style); } void Draw(const int x, const int y, const int width, const int height) { blocks[0].color = color[WIDGETCOLOR_BACKGROUND]; blocks[0].wireframe = false; blocks[0].position = iVec2(0); blocks[0].size = size; blocks[0].hidden = false; blocks[0].radius = cornerradius; } public: static shared_ptr<CustomWidget> create(const int x, const int y, const int width, const int height, shared_ptr<Widget> parent) { struct Struct : public CustomWidget { }; auto instance = std::make_shared<Struct>(); instance->Initialize(x, y, width, height, parent); instance->SetColor(0.5, 0.5, 0.5, 1, WIDGETCOLOR_BACKGROUND); return instance; } }; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; shared_ptr<World> menuWold; shared_ptr<Interface> ui; shared_ptr<Camera> uiCamera; shared_ptr<CustomWidget> customWidget; void initGui() { auto default_font = LoadFont("Fonts\\arial.ttf"); ui = CreateInterface(menuWold, default_font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); uiCamera = CreateCamera(menuWold, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); customWidget = CustomWidget::create(10, 50, 200, 50, ui->root); } int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window window = CreateWindow("Ultra Engine", 0, 0, 300, 300, displays[0], WINDOW_DEFAULT); //Create a world menuWold = CreateWorld(); //Create a framebuffer framebuffer = CreateFramebuffer(window); //Create camera auto camera = CreateCamera(menuWold); camera->SetClearColor(0.125); camera->SetPosition(0, 0, -3); camera->SetFov(70); initGui(); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { menuWold->Update(); menuWold->Render(framebuffer); } return 0; }
-
It happens after recreating window and UI on second screen, dragging app window and even if initially windows was created on 2nd display. Depending on window resolution it looks differently on second screen - invisible or partly visible. First screen: Second: #include "UltraEngine.h" using namespace UltraEngine; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; shared_ptr<World> menuWold; shared_ptr<Interface> ui; shared_ptr<Camera> uiCamera; shared_ptr<Widget> btn; shared_ptr<Widget> btn2; bool fullscreen = false; int displayId = 0; void initGui() { auto default_font = LoadFont("Fonts\\arial.ttf"); ui = CreateInterface(menuWold, default_font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); uiCamera = CreateCamera(menuWold, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); btn = CreateButton("Change display", (float)framebuffer->GetSize().x / 2, framebuffer->GetSize().y / 2, 200, 200, ui->root); btn->SetFontScale(2.0f); btn2 = CreateButton("Fullscreen", (float)framebuffer->GetSize().x / 2, framebuffer->GetSize().y / 2 + 250, 120, 30, ui->root, BUTTON_CHECKBOX); } void changeDisplay() { displayId = displayId == 0 ? 1 : 0; if (!fullscreen) { window = CreateWindow("Ultra Engine", 0, 0, 1000, 1000, GetDisplays()[displayId], WINDOW_DEFAULT); } else { window = CreateWindow("Ultra Engine", 0, 0, 1000, 1000, GetDisplays()[displayId], WINDOW_DEFAULT | WINDOW_FULLSCREEN); } framebuffer = CreateFramebuffer(window); initGui(); } int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window window = CreateWindow("Ultra Engine", 0, 0, 1000, 1000, displays[0], WINDOW_DEFAULT); //Create a world menuWold = CreateWorld(); //Create a framebuffer framebuffer = CreateFramebuffer(window); //Create light auto light = CreateBoxLight(menuWold); light->SetRange(-10, 10); light->SetRotation(15, 15, 0); light->SetColor(2); //Create camera auto camera = CreateCamera(menuWold); camera->SetClearColor(0.125); camera->SetPosition(0, 0, -3); camera->SetFov(70); //Create scenery auto box = CreateBox(menuWold); initGui(); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { while (PeekEvent()) { const Event ev = WaitEvent(); if (ev.source == btn && ev.id == EVENT_WIDGETACTION) { changeDisplay(); } if (ev.source == btn2 && ev.id == EVENT_WIDGETACTION) { fullscreen = !fullscreen; } ui->ProcessEvent(ev); } menuWold->Update(); menuWold->Render(framebuffer); } return 0; }
-
I made this example in an effort to get things to crash but have noted a few other issues in the process. Please excuses the size the example. No mouse events for tabber or button (disable the panel creating in the loop to see this) Press Space a few times - Red panel clipping exceeds parents size by 1 pixel in both x & y Sprite remains in renderlayer 0. Solved! Powers of 2 required. Only downside to not use the enum Tab page and button left border clipped off Drawing widgets stops at the 2,000 mark? Excessive I know but is this some sort of limit or bug? #include "UltraEngine.h" #include "ComponentSystem.h" using namespace UltraEngine; bool EventCallback(const Event& event, shared_ptr<Object> extra) { switch (event.id) { case EVENT_MOUSEENTER: Print("MOUSE_ENTER"); break; case EVENT_MOUSELEAVE: Print("MOUSE_LEAVE"); break; case EVENT_MOUSEDOWN: Print("MOUSE_DOWN"); break; case EVENT_MOUSEMOVE: //Print("MOUSE_MOVE"); break; case EVENT_MOUSEUP: Print("MOUSE_UP"); break; case EVENT_MOUSEWHEEL: Print("MOUSE_WHEEL"); break; } return true; } int main(int argc, const char* argv[]) { auto displays = GetDisplays(); auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); auto world = CreateWorld(); auto framebuffer = CreateFramebuffer(window); auto camera = CreateCamera(world); camera->SetClearColor(0.125); camera->SetFov(70); camera->SetPosition(0, 2, -3); auto default_font = LoadFont("Fonts\\arial.ttf"); auto ui = CreateInterface(world, default_font, framebuffer->size); ui->SetRenderLayers(1); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); auto ui_camera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); ui_camera->SetPosition((float)framebuffer->size.x * 0.5f, (float)framebuffer->size.y * 0.5f, 0); ui_camera->SetRenderLayers(1); ui_camera->SetClearMode(CLEAR_DEPTH); auto w1 = CreatePanel(0, 0, 1, 1, ui->root); ListenEvent(EVENT_NONE, w1, EventCallback); auto w2 = CreatePanel(0, 0, 1, 1, w1); ListenEvent(EVENT_NONE, w2, EventCallback); w2->SetColor(1, 0, 0); auto w3 = CreateTabber(10, 10, 1, 1, ui->root); w3->SetShape(25, 25, 256, 256); w3->AddItem("Page1"); w3->AddItem("Page2"); auto w4 = CreateButton("Test", 0, 0, 32, 32, w3); w4->SetShape(5, 5, 100, 50); auto terrain = CreateTerrain(world, 512, 512); terrain->SetMaterial(LoadMaterial("Data\\bluegrid.mat")); auto c = CreateCylinder(world); c->SetPhysicsMode(PHYSICS_PLAYER); vector<shared_ptr<Entity>> entities; Vec3 offset = Vec3(10.0f, 1.0f, 5.0f); float scale = 2.0f; for (int z = 0; z < 10; z++) { for (int x = 0; x < 10; x++) { auto e = CreateSphere(world); e->SetColor(Random(), Random(), Random()); e->SetPosition(Vec3((float)x * scale + Random() - 0.5f, 0.0f, (float)z * scale + Random() - 0.5f) + offset, true); e->SetMass(1.0f); entities.push_back(e); } } auto sprite = CreateSprite(world, default_font, "", 12); sprite->SetRenderLayers(1);//Still on layer 0? vector<shared_ptr<Widget>> widgets; widgets.push_back(ui->root); while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { if (window->KeyHit(KEY_SPACE)) { w1->SetShape(Random(0, 512), Random(0, 512), Random(64, 128), Random(64, 128)); w2->SetShape(Random(0, 10), Random(0, 10), Random(16, 128), Random(16, 32)); } auto w = CreatePanel(Random(0, 512), Random(0, 512), Random(64, 128), Random(64, 128), ui->root);// widgets[(int)Random(0.0f, (float)widgets.size() - 0.1f)]); w->SetColor(Random(), Random(), Random()); ListenEvent(EVENT_NONE, w, EventCallback); widgets.push_back(w); sprite->SetText(String(widgets.size())); while (PeekEvent()) { auto event = WaitEvent(); ui->ProcessEvent(event); } world->Update(); world->Render(framebuffer); } return 0; }
-
For some reason usual widgets don't change icon at all so had to create little custom widget with AddBlock(); #include "UltraEngine.h" using namespace UltraEngine; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; shared_ptr<World> menuWold; shared_ptr<Interface> ui; shared_ptr<Camera> uiCamera; shared_ptr<Widget> panel; shared_ptr<Widget> btn; bool isFirst = true; class TestWidget : public Widget { protected: virtual void Draw(const int x, const int y, const int width, const int height) { blocks.clear(); int blockId = AddBlock(pixmap, iVec2(0), Vec4(1)); } public: static shared_ptr<TestWidget> create(const int x, const int y, const int width, const int height, shared_ptr<Widget> parent, const int style = 0) { struct Struct : public TestWidget { }; auto instance = std::make_shared<Struct>(); instance->Initialize("", x, y, width, height, parent, style); return instance; } }; void initGui() { auto default_font = LoadFont("Fonts\\arial.ttf"); ui = CreateInterface(menuWold, default_font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); uiCamera = CreateCamera(menuWold, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); panel = TestWidget::create(10, 50, 64, 64, ui->root); auto icon = LoadIcon("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Icons/help.svg"); panel->SetIcon(icon); btn = CreateButton("Change an icon", 10, 10, 150, 20, ui->root); } int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window window = CreateWindow("Ultra Engine", 0, 0, 200, 200, displays[0], WINDOW_DEFAULT); //Create a world menuWold = CreateWorld(); //Create a framebuffer framebuffer = CreateFramebuffer(window); //Create light auto light = CreateBoxLight(menuWold); light->SetRange(-10, 10); light->SetRotation(15, 15, 0); light->SetColor(2); //Create camera auto camera = CreateCamera(menuWold); camera->SetClearColor(0.125); camera->SetPosition(0, 0, -3); camera->SetFov(70); initGui(); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { while (PeekEvent()) { const Event ev = WaitEvent(); if (ev.source == btn && ev.id == EVENT_WIDGETACTION) { isFirst = !isFirst; if (isFirst) { auto icon = LoadIcon("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Icons/help.svg"); //panel->SetPixmap(icon->Rasterize(1)); panel->SetIcon(icon); } else { auto icon2 = LoadIcon("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Icons/new.svg"); //panel->SetPixmap(icon2->Rasterize(1)); panel->SetIcon(icon2); } } ui->ProcessEvent(ev); } menuWold->Update(); menuWold->Render(framebuffer); } return 0; }
-
Initially i tried to reproduced bug when while changing an icon it was blinking with purple but in test example first icons stays. #include "UltraEngine.h" using namespace UltraEngine; shared_ptr<Window> window; shared_ptr<Framebuffer> framebuffer; shared_ptr<World> menuWold; shared_ptr<Interface> ui; shared_ptr<Camera> uiCamera; shared_ptr<Widget> panel; shared_ptr<Widget> btn; bool isFirst = true; void initGui() { auto default_font = LoadFont("Fonts\\arial.ttf"); ui = CreateInterface(menuWold, default_font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); uiCamera = CreateCamera(menuWold, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition((float)framebuffer->GetSize().x * 0.5f, (float)framebuffer->GetSize().y * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); panel = CreatePanel(10, 50, 64, 64, ui->root, PANEL_DEFAULT); auto icon = LoadIcon("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Icons/help.svg"); panel->SetIcon(icon); btn = CreateButton("Change an icon", 10, 10, 150, 20, ui->root); } int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window window = CreateWindow("Ultra Engine", 0, 0, 200, 200, displays[0], WINDOW_DEFAULT); //Create a world menuWold = CreateWorld(); //Create a framebuffer framebuffer = CreateFramebuffer(window); //Create light auto light = CreateBoxLight(menuWold); light->SetRange(-10, 10); light->SetRotation(15, 15, 0); light->SetColor(2); //Create camera auto camera = CreateCamera(menuWold); camera->SetClearColor(0.125); camera->SetPosition(0, 0, -3); camera->SetFov(70); initGui(); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { while (PeekEvent()) { const Event ev = WaitEvent(); if (ev.source == btn && ev.id == EVENT_WIDGETACTION) { isFirst = !isFirst; if (isFirst) { auto icon = LoadIcon("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Icons/help.svg"); panel->SetIcon(icon); } else { auto icon2 = LoadIcon("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Icons/new.svg"); panel->SetIcon(icon2); } } ui->ProcessEvent(ev); } menuWold->Update(); menuWold->Render(framebuffer); } return 0; }
-
I think block.SetPixmap work fine if a pixmap as member set in but with if it's another pixmap (to make few different icons for different blocks) i have an exception at Render(). An example: #include "UltraEngine.h" using namespace UltraEngine; class NewWidget : public Widget { protected: virtual void Draw(const int x, const int y, const int width, const int height) { for (int i = 0; i < 4; i++) { blocks[i].hidden = false; blocks[i].position = iVec2(i * 64, 0); blocks[i].size = iVec2(64, 64); blocks[i].filter = pixmapfilter; blocks[i].color = Vec4(1); auto px = LoadPixmap("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/dirt01.dds"); blocks[i].SetPixmap(px); } } public: static shared_ptr<NewWidget> create(const int x, const int y, const int width, const int height, shared_ptr<Widget> parent, const int style = 0) { struct Struct : public NewWidget { }; auto instance = std::make_shared<Struct>(); instance->Initialize("", x, y, width, height, parent, style); return instance; } NewWidget() { blocks.resize(4); } }; int main(int argc, const char* argv[]) { //Get the displays auto displays = GetDisplays(); //Create a window auto window = CreateWindow("Ultra Engine", 0, 0, 1920, 1080, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); //Create a framebuffer auto framebuffer = CreateFramebuffer(window); //Create a world auto world = CreateWorld(); //Create a camera auto camera = CreateCamera(world); camera->SetClearColor(0.6); camera->SetFov(90); camera->SetRotation(54.736f, 45, 0); camera->SetPosition(0, 4, 0); auto sz = framebuffer->GetSize(); // Load a font auto font = LoadFont("Fonts/arial.ttf"); // Create user interface auto ui = CreateInterface(world, font, framebuffer->GetSize()); ui->SetRenderLayers(2); ui->root->SetColor(0.0f, 0.0f, 0.0f, 0.0f); // Create ui camera auto uiCamera = CreateCamera(world, PROJECTION_ORTHOGRAPHIC); uiCamera->SetPosition(float(framebuffer->GetSize().x) * 0.5f, float(framebuffer->GetSize().y) * 0.5f, 0); uiCamera->SetRenderLayers(2); uiCamera->SetClearMode(CLEAR_DEPTH); auto widget = NewWidget::create(0, 0, 64 * 4, 64, ui->root, 0); //Create light auto light = CreateBoxLight(world); light->SetRange(-100, 100); light->SetArea(100, 100); light->SetRotation(35, 35, 0); light->SetColor(2); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { world->Update(); world->Render(framebuffer, false); } return 0; }
-
Hi, I finally managed to build a first release candidate for a SyntaxEditor-Widget. The Widget is using the famous Scintilla TextEditor-Component under the hood and wraps the control into a UAK-Widget. At this point i only provide binaries (includes and libraries) but i am currently preparing to release the source as well. The source itself is semi-autogenerated with a manual created body and a tool which generates the main part of the Scintilla-Component based of so called iFace files maintained by the Scintilla author (these files contains the definitions of each enum or function you can use with Scintilla). Downloads: Demo (Small sample): Demo.zip Libraries and Headers:SyntaxEditor_libinc.zip To use the new widget you need to copy the content of the zip into your project and add the "include" directory to "Additional Include Directories" and add the the path to the Library to "Additional Library Directories" (for Release and Debug configurations). Finally you need to add the needed lib files to "Additional Dependecies": Imm32.lib SyntaxWidget.lib Lexilla.lib Scintilla.lib here is screenshot of the small demo app: and the code: #include "UltraEngine.h" #include "SyntaxWidget.h" #include "ScintillaLexer.hpp" using namespace UltraEngine; int main(int argc, const char* argv[]) { #ifdef _WIN64 auto plugin = LoadPlugin("Plugins/FITextureLoader.*"); #else auto plugin = LoadPlugin("Plugins (x86)/FITextureLoader.*"); #endif if (plugin == NULL) { Print("Failed to load FreeImage plugin."); return 1; } //Get the displays auto displays = GetDisplays(); //Create a window auto window = CreateWindow("Ultra Engine", 0, 0, 800, 600, displays[0], WINDOW_TITLEBAR | WINDOW_RESIZABLE | WINDOW_CENTER); //Create User Interface auto ui = CreateInterface(window); //Create widget auto sz = ui->root->GetSize(); auto toggleVisibility = CreateButton("Visible", 10, 10, 80, 20, ui->root, ButtonStyle::BUTTON_TOGGLE); toggleVisibility->SetState(WidgetState::WIDGETSTATE_SELECTED); auto container = CreatePanel(5, 40, sz.x - 10, sz.y - 45, ui->root, PanelStyle::PANEL_BORDER); sz = container->ClientSize(); container->SetLayout(1, 1, 1, 1); auto syntaxEditor = CreateSyntaxEditor(5, 5, sz.x - 10, sz.y - 10, container); syntaxEditor->SetLayout(1, 1, 1, 1); syntaxEditor->SetFoldFlags(FoldFlag::LineAfterContracted | FoldFlag::LineBeforeContracted); // 16 Draw line below if not expanded //auto lualexer = CreateLexer("lua"); // syntaxEditor->SetILexer(lualexer); auto lexer = CreateLuaLexer(syntaxEditor); syntaxEditor->SetKeyWords(0, "and break do else elseif end for function if in local nil not or repeat return then until while"); syntaxEditor->SetKeyWords(1, "print require"); syntaxEditor->SetProperty("fold", "1"); syntaxEditor->SetProperty("fold.compact", "0"); syntaxEditor->SetAutomaticFold(AutomaticFold::Change | AutomaticFold::Click | AutomaticFold::Show); syntaxEditor->SetMarginSensitiveN(2, 1); auto luasource = R"V0G0N(require("INC_Class.lua") --========================== = cAnimal = setclass("Animal") function cAnimal.methods:init(action, cutename) self.superaction = action self.supercutename = cutename end --========================== cTiger = setclass("Tiger", cAnimal) function cTiger.methods:init(cutename) self : init_super("HUNT (Tiger)", "Zoo Animal (Tiger)") self.action = "ROAR FOR ME!!" self.cutename = cutename function test() end end --========================== Tiger1 = cAnimal:new("HUNT", "Zoo Animal") Tiger2 = cTiger : new("Mr Grumpy") Tiger3 = cTiger : new("Mr Hungry") print("CLASSNAME FOR TIGER1 = ", Tiger1:classname()) print("CLASSNAME FOR TIGER2 = ", Tiger2:classname()) print("CLASSNAME FOR TIGER3 = ", Tiger3:classname()) print("===============") print("SUPER ACTION", Tiger1.superaction) print("SUPER CUTENAME", Tiger1.supercutename) print("ACTION ", Tiger1.action) print("CUTENAME", Tiger1.cutename) print("===============") print("SUPER ACTION", Tiger2.superaction) print("SUPER CUTENAME", Tiger2.supercutename) print("ACTION ", Tiger2.action) print("CUTENAME", Tiger2.cutename) print("===============") print("SUPER ACTION", Tiger3.superaction) print("SUPER CUTENAME", Tiger3.supercutename) print("ACTION ", Tiger3.action) print("CUTENAME", Tiger3.cutename))V0G0N"; String s = luasource; syntaxEditor->SetText(s.c_str()); syntaxEditor->StyleSetBack(STYLE_DEFAULT, RGB(syntaxEditor->color[WIDGETCOLOR_BACKGROUND].r * 255, syntaxEditor->color[WIDGETCOLOR_BACKGROUND].g * 255, syntaxEditor->color[WIDGETCOLOR_BACKGROUND].b * 255)); syntaxEditor->StyleSetFore(STYLE_DEFAULT, RGB(syntaxEditor->color[WIDGETCOLOR_FOREGROUND].r * 255, syntaxEditor->color[WIDGETCOLOR_FOREGROUND].g * 255, syntaxEditor->color[WIDGETCOLOR_FOREGROUND].b * 255)); syntaxEditor->StyleSetFont(STYLE_DEFAULT, "Consolas"); syntaxEditor->StyleSetSize(STYLE_DEFAULT, 11); syntaxEditor->StyleClearAll(); syntaxEditor->SetCaretFore(RGB(syntaxEditor->color[WIDGETCOLOR_FOREGROUND].r * 255, syntaxEditor->color[WIDGETCOLOR_FOREGROUND].g * 255, syntaxEditor->color[WIDGETCOLOR_FOREGROUND].b * 255)); syntaxEditor->SetFoldMarginHiColour(true, RGB(syntaxEditor->color[WIDGETCOLOR_HIGHLIGHT].r * 255, syntaxEditor->color[WIDGETCOLOR_HIGHLIGHT].g * 255, syntaxEditor->color[WIDGETCOLOR_HIGHLIGHT].b * 255)); syntaxEditor->SetFoldMarginColour(true, RGB(syntaxEditor->color[WIDGETCOLOR_HIGHLIGHT].r * 255, syntaxEditor->color[WIDGETCOLOR_HIGHLIGHT].g * 255, syntaxEditor->color[WIDGETCOLOR_HIGHLIGHT].b * 255)); auto textWidth = syntaxEditor->TextWidth(STYLE_LINENUMBER, "_99999"); syntaxEditor->SetMargins(5); syntaxEditor->SetMarginTypeN(0, MarginType::Number); syntaxEditor->SetMarginWidthN(0, textWidth); syntaxEditor->SetMarginTypeN(2, MarginType::Symbol); syntaxEditor->SetMarginMaskN(2, SC_MASK_FOLDERS); syntaxEditor->SetMarginWidthN(2, 16); syntaxEditor->SetMarginLeft(2); syntaxEditor->SetMarginRight(2); syntaxEditor->MarkerDefine(SC_MARKNUM_FOLDER, MarkerSymbol::BoxPlus); syntaxEditor->MarkerDefine(SC_MARKNUM_FOLDEROPEN, MarkerSymbol::BoxMinus); syntaxEditor->MarkerDefine(SC_MARKNUM_FOLDEREND, MarkerSymbol::BoxPlus); syntaxEditor->MarkerDefine(SC_MARKNUM_FOLDERMIDTAIL, MarkerSymbol::TCorner); syntaxEditor->MarkerDefine(SC_MARKNUM_FOLDEROPENMID, MarkerSymbol::BoxMinusConnected); syntaxEditor->MarkerDefine(SC_MARKNUM_FOLDERSUB, MarkerSymbol::VLine); syntaxEditor->MarkerDefine(SC_MARKNUM_FOLDERTAIL, MarkerSymbol::LCornerCurve); for (int i = 25; i <= 31; i++) { syntaxEditor->MarkerSetFore(i, RGB(syntaxEditor->color[WIDGETCOLOR_BACKGROUND].r * 255, syntaxEditor->color[WIDGETCOLOR_BACKGROUND].g * 255, syntaxEditor->color[WIDGETCOLOR_BACKGROUND].b * 255)); syntaxEditor->MarkerSetBack(i, RGB(215, 221, 232)); } syntaxEditor->StyleSetFore(LuaLexer::WORD, RGB(150, 190, 177)); syntaxEditor->StyleSetFore(LuaLexer::WORD2, RGB(220, 220, 170)); syntaxEditor->StyleSetFore(LuaLexer::COMMENT, RGB(87, 160, 61)); syntaxEditor->StyleSetFore(LuaLexer::COMMENTLINE, RGB(87, 160, 61)); syntaxEditor->StyleSetFore(LuaLexer::COMMENTDOC, RGB(87, 160, 61)); syntaxEditor->StyleSetFore(LuaLexer::CHARACTER, RGB(87, 160, 61)); syntaxEditor->StyleSetFore(LuaLexer::STRING, RGB(214, 151, 108)); syntaxEditor->StyleSetBack(STYLE_LINENUMBER, RGB(syntaxEditor->color[WIDGETCOLOR_BACKGROUND].r * 255, syntaxEditor->color[WIDGETCOLOR_BACKGROUND].g * 255, syntaxEditor->color[WIDGETCOLOR_BACKGROUND].b * 255)); syntaxEditor->StyleSetFore(STYLE_LINENUMBER, RGB(43, 145, 175)); syntaxEditor->SetElementColour(Element::ListBack, RGB(syntaxEditor->color[WIDGETCOLOR_BACKGROUND].r * 255, syntaxEditor->color[WIDGETCOLOR_BACKGROUND].g * 255, syntaxEditor->color[WIDGETCOLOR_BACKGROUND].b * 255)); syntaxEditor->SetElementColour(Element::List, RGB(syntaxEditor->color[WIDGETCOLOR_FOREGROUND].r * 255, syntaxEditor->color[WIDGETCOLOR_FOREGROUND].g * 255, syntaxEditor->color[WIDGETCOLOR_FOREGROUND].b * 255)); syntaxEditor->SetElementColour(Element::ListSelected, RGB(syntaxEditor->color[WIDGETCOLOR_SELECTEDTEXT].r * 255, syntaxEditor->color[WIDGETCOLOR_SELECTEDTEXT].g * 255, syntaxEditor->color[WIDGETCOLOR_SELECTEDTEXT].b * 255)); syntaxEditor->SetElementColour(Element::ListSelectedBack, RGB(syntaxEditor->color[WIDGETCOLOR_SELECTION].r * 255, syntaxEditor->color[WIDGETCOLOR_SELECTION].g * 255, syntaxEditor->color[WIDGETCOLOR_SELECTION].b * 255)); auto pixmap = LoadPixmap("Resources/class.png")->Resize(16, 16); syntaxEditor->RGBAImageSetWidth(pixmap->size.x); syntaxEditor->RGBAImageSetHeight(pixmap->size.y); syntaxEditor->RegisterRGBAImage(1, pixmap->pixels->Data()); while (true) { const Event ev = WaitEvent(); if (ev.id == SyntaxEditor::EVENT_CHARADDED) { auto notification = static_cast<TextEditorNotification*>(ev.extra.get()); if (notification->ch == '.' && !syntaxEditor->AutoCActive()) { syntaxEditor->AutoCShow(0, "Entity?1 Window?1 Hello World"); } } switch (ev.id) { case EVENT_WIDGETACTION: if (ev.source == toggleVisibility) { if (toggleVisibility->GetState() == WidgetState::WIDGETSTATE_SELECTED) { toggleVisibility->SetText("Visible"); syntaxEditor->Show(); } else { toggleVisibility->SetText("Hidden"); syntaxEditor->Hide(); } } break; case EVENT_WIDGETSELECT: break; case EVENT_QUIT: case EVENT_WINDOWCLOSE: return 0; break; default: break; } } return 0; } ToDo: Publish the source add helper to apply UAK based theming move some Scintilla-Types to UAK-Types (e.g.: Colour to iVec4) I hope you enjoy the release and i look forward for any suggestions and feedback is very welcome.
- 2 comments
-
- 4
-
- ultraappkit
- uak
-
(and 6 more)
Tagged with:
-
One month ago I began work to investigate what it would take to bring Ultra App Kit, the foundation for our new generation of game development tools, to Linux. Today I am happy to share my progress with you and discuss some of the things I have learned. Developed by MIT in the year 1984, X11 is an interesting beast that is easy to start with, but can become quite difficult once you get into the details. (Wayland support is of course an obvious step in the not-too-distant future but I have to work with what exists here now today and Ubuntu 20.04 still uses X by default.) The single hardest part had to do with calls to XSetInputFocus on windows that had not yet been mapped. X has a weird asynchronous design, yet XSetInputFocus does not seem to get added to the command queue and instead depends on the mapping (visible) state of a window right now. That means that is you create or show a window and then immediately activate it, an error will occur that looks something like this: Error of failed request: BadMatch (invalid parameter attributes) Major opcode of failed request: 42 (X_SetInputFocus) Serial number of failed request: 12 Current serial number in output stream: 12 The way around this is to call XMapWindow and then wait on the event queue until a MapNotify event for that window occurs, adding all other events into a list that can be evaluated on the next call to WaitEvent(). The time elapsed is checked inside the loop in case something weird happens and the desired event is never received: void Window::Show() { if (!Hidden()) return; XMapWindow(display->GetHandle(),xwindow); XMoveResizeWindow(display->GetHandle(), GetHandle(),m_position.x,m_position.y,size.x,size.y); XFlush(display->GetHandle()); XSync(display->GetHandle(),false); auto engine = GameEngine::Get(); XEvent ev = {}; auto start = Millisecs(); while (xhidestate) { XNextEvent(display->GetHandle(),&ev); if (ev.type == MapNotify and ev.xany.window == GetHandle()) { xhidestate = false; return; } if (engine) engine->storedxevents.push_back(ev); Sleep(1); if (Millisecs() - start > 5000) { Warn("MapNotify is taking a long time to be received. This may cause window errors."); return; } } } POSIX timers are strange creatures that seem to follow rules all their own. A timer callback gets triggered during any call to sleep() when a timer tick has occurred, but a mutex lock inside the callback will freeze the program. I ended up using the much simpler timerfd interface. Double-buffering, good text rendering, and alpha blending are all different extensions built on top of the base X11 system. Getting all of this to work together took a lot of trial and error. However, I think you will agree based on the screenshots below that this work has been worthwhile. Multi-select draggable treeview with insertion between nodes Multi-line text display with optional word wrapping Hierarchical menu system with real popup windows For the final leg of development I have set up a small Kickstarter campaign. If you haven't gotten Ultra App Kit yet this is a good opportunity to grab it before the Linux build is released. Ultra App Kit can also be purchase in our store or on Steam.
-
Built to power a new generation of game development tools, Ultra App Kit provides an easy-to-use C++ programming SDK for creating desktop GUI applications. Unlike other alternatives like Dear ImGui, the Ultra App Kit GUI renders in retained mode rather than immediate mode, and is specifically designed for desktop GUI applications. This makes applications snappy and responsive when resizing or refreshing a window. DPI scaling is baked into the design for resolution-independent graphics on any screen. The GUI can be combined with an embedded OpenGL viewport, or combined with a 3D game engine to make custom editors and game development tools. Check out the video tutorials and read the documentation to learn more. Ultra App Kit can be purchased in our store. API Design C++ shared pointers everywhere Extensible widgets system Extensive documentation with examples for each command UI Features Resolution independent for any DPI scale Load SVG vector images Set widget icons Change mouse cursor Custom color schemes stored in JSON files Supported Widgets Label Button (push, checkbox, radio, and toggle styles) ProgressBar TextField TextArea ComboBox ListBox Slider (scrollbar, trackbar, and stepper styles) Draggable multi-select TreeView Create your own custom widgets Additional Features File I/O File system watcher Memory allocation and management Image loading, saving, processing Package system for loading files from compressed / encrypted archives Plugin system Thread management String manipulation (split, search, conversion, etc.) Message boxes and file / folder requester
-
This will create a "spinner" widget like in 3ds max. You can use SetRange() to control the min and max values. Download: Spinner.h Example: #include "UltraEngine.h" #include "Spinner.h" using namespace UltraEngine; int main(int argc, const char* argv[]) { //Get displays auto displays = GetDisplays(); //Create window auto mainwindow = CreateWindow("Spinner", 0, 0, 800, 600, displays[0]); //Create user interface auto ui = CreateInterface(mainwindow); iVec2 sz = ui->root->ClientSize(); //Create spinners auto ispinner = CreateSpinner(20, 20, 100, 30, ui->root, SPINNER_INTEGER); auto fspinner = CreateSpinner(20, 60, 100, 30, ui->root, SPINNER_FLOAT); auto nspinner = CreateSpinner(20, 100, 100, 30, ui->root, SPINNER_FLOAT | SPINNER_NORMALIZE); //Show the window mainwindow->Show(); mainwindow->Activate(); //Easier to work with: ui->SetScale(2); while (true) { const Event event = WaitEvent(); switch (event.id) { case EVENT_WIDGETACTION: if (event.source == ispinner) Print(event.data); if (event.source == fspinner or event.source == nspinner) { Print(event.source->As<Widget>()->GetProgress()); } break; case EVENT_WINDOWCLOSE: if (event.source == mainwindow) return 0; break; } } return 0; }