-
Posts
2,600 -
Joined
-
Last visited
Content Type
Blogs
Forums
Store
Gallery
Videos
Downloads
Everything posted by reepblue
-
Hey, just an idea, but why not have the game files be in their own directory? Right now, everything looks cluttered. IDK, maybe to something like this? The only change to the project files would be to change the output directory, For the editor, I would have it look for a path string within the Ultra.json file so the editor can set its root folder correctly. Bin might be a bad name, maybe "Game" would be better...
-
With Cyclone, I was getting complaints about how people with non US-EN keyboards couldn't bind some of their keys. While my input system supported rebinding of actions, it couldn't read things like arrow keys on those keyboards. Could UltraEngine magically convert the input to use unicode for us like SDL2 does? This way KEY_E is ALWAYS the E key no matter what keyboard we're using.
-
Also, if you set the environment maps to null, there's a split second where the frame buffer will turn purple.
-
I also really like that other creators can load each other's maps for investigation. Reminds me back when I used to use vmex to decompile cool community maps to learn how they made custom elements and such!
-
@JoshI was able to beat it! Here's a few tips. 1) There's a file called [uid]_CycloneMod.json. If you were to copy that file, modify it as below and resave it as [uid]_bastardplatforms.json, the map will be accessible from the menu! { "author": "Josh", "maps": { "TemplateAddon": { "filepath": "Maps/bastardplatforms.map" } }, "name": "BastardPlatforms" } This uses the SAME system as the chapter selection. You can also have a custom image for your addon. Here's an example with one of the chapter scripts showcasing images and multiple maps. { "name": "Crash Courses 00-08", "author": "Reep Softworks", "maps": { "Crash Course 00 + 01": { "id": 0, "filepath": "Maps/lvl0.map", "imagepath": "Materials/GUI/Chapters/chaptericon_lvl0.tex", }, "Crash Course 02 + 03": { "id": 1, "filepath": "Maps/lvl1.map", "imagepath": "Materials/GUI/Chapters/chaptericon_lvl1.tex" }, "Crash Course 04 + 05": { "id": 2, "filepath": "Maps/lvl2.map", "imagepath": "Materials/GUI/Chapters/chaptericon_lvl2.tex" }, "Crash Course 06 + 07": { "id": 3, "filepath": "Maps/lvl3.map", "imagepath": "Materials/GUI/Chapters/chaptericon_lvl3.tex" }, "Crash Course 08": { "id": 4, "filepath": "Maps/lvl4.map", "imagepath": "Materials/GUI/Chapters/chaptericon_lvl4.tex" } } } It's best practice not to use spaces with map names. This is so your map can be loaded with the map command within developer console. But spaces should work with chapter scripts. I also combined everything to get around the censor, ð 2) If you add flash chambers to your map, the player will respawn when they die instead of a hard reload. I made an example map showcasing these - but for some reason didn't include it. You can refer to example_lvl7.map for the time being. Also with an exit flash chamber, the map will automatically fade out and kick the player back to the menu if there's no more maps in the queue. 3) I didn't need the slope to get onto the first platform. 4) Make sure you add your bumpers. Any tool brush with the collision set to projected will do the trick! 5) This answers your question. Make a new script and attach it to the brush you want this effect. function Script:Start() self.entity:SetCollisionType(19) -- COLLISIONTYPE_CLEANSER self.entity:SetKeyValue("force_cyclone_placement", "1") end I might write a few guides on my Steam page this weekend. Right now, I just wanted to see what curiosity alone would bring.
-
There probably is, but I'll need to check my code base to make sure. I'll be sure to try your map when I get home. ð
-
Got window switching to work without disrupting the world render. The black screens are due to OBS and does not actually happen. Right now, I'm just using WINDOW_CENTER as the style. //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void GraphicsWindow::Build(const GameWindowParams& info) { if (m_pWindow != NULL) { //m_pWindow->Close(); m_pFramebuffer = NULL; m_pWindow = NULL; m_pDisplay = NULL; } auto displays = UltraEngine::GetDisplays(); m_pDisplay = displays[info.displayindex]; UltraEngine::WString title = Foundation::GetAppName(); if (title.empty()) title = "Ultra Engine"; m_pWindow = UltraEngine::CreateWindow(Foundation::GetAppName(), 0, 0, info.size.x * static_cast<int>(m_pDisplay->scale), info.size.y * static_cast<int>(m_pDisplay->scale), m_pDisplay, info.style); m_pFramebuffer = UltraEngine::CreateFramebuffer(m_pWindow); ListenEvent(UltraEngine::EVENT_WINDOWCLOSE, m_pWindow, EventCallbackStopGameWindow, Self()); m_hParams = { info.displayindex, info.size, info.style }; }
-
I couldn't seem to use Load material function at all. I tried loading a material formatted like one from the old SDK and it didn't work.
-
The legacy plugin doesn't seem to work. (Texture index out of range.) auto ball = CreateSphere(m_pWorld, 0.5, 32); auto mat = LoadMaterial("Materials/Developer/defaultmeshface.mat"); if (mat) ball->SetMaterial(mat); NVM, seems to happen when I load json materials too...
-
As a teenager, I've spent thousands of hours with the Source SDK. It was really cool how Valve gave people the real tools to develop and create maps and mods. Overtime I got to see and take apart games to see how they actually work. Overtime, the indie engine market took over, and making Source mods is now just a terrible experience. Hammer crashes more frequently and the SDK branch of the engine has old bugs that were never patched. I want the excitement I had of making maps and cool features to be part of Cyclone as a package. Leadwerks has a very intuitive interface, and with a Lua Sandbox, many possibilities open up. As of the last update shipped today, anyone with a license of Leadwerks Game Engine has the ability to create custom maps and scripts and share them with others. This is the first step to see if anyone would be interested if they had the tools in their holster. There's now a batch file called "create_mod_env.bat" which will create a Leadwerks project within the game directory by default. You can edit the batch file to define a different path if you wish. You'll also receive a few example maps showing the logic of the game. Import the project in Leadwerks, and you should be good to go! When you're ready to share, zip up the map and chapter script and tell people to install it in a folder called "Addons" within the game's directory. While this is only the first draft of this, I'm interested to see where it will end up. I hope you all find it interesting and motivating.
-
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; }
-
Yeah, if a dynamic cast to a BSPTree returns null, that would mean that the pick hit an actual model, or something else.
-
I do this because within Leadwerks, I can count on the geometry being simple and static. Reflection on this, I'm now thinking that I could have probably get away with using material flags if I had that option. I used the roughness value in my game to check if the surface could hold a cyclone or not. I've never got to counting polys or checking the face size as everything I tried was really slow. Again, this was the very first check I implemented, and it stopped 80% of unwanted successful placements. Real production code example. //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- const bool CanCycloneBePlaced(Entity* pEntity) { if (pEntity == NULL) return false; // Quick force placement, ignores all other rules! if (String::Int(pEntity->GetKeyValue("force_cyclone_placement")) != 0) return true; if (pEntity->GetClass() == Object::ModelClass) { // Only allow placement on Models if it's collapsed CSG. auto cast = static_cast<Model*>(pEntity); if (cast->collapsedfrombrushes == false) return false; } return true; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- const bool CanPlaceCycloneOnSurface(Leadwerks::Surface* pSurface) { if (pSurface == nullptr) return false; auto material = pSurface->GetMaterial(); if (material == nullptr) return false; if (material->GetBlendMode() != Blend::Solid) return false; if (IsReflectiveSurface(material)) return false; return true; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- const bool CanPlaceCycloneOnFace(Leadwerks::Face* pFace) { if (pFace == NULL) return false; if (pFace->surface != NULL) { if (!CanPlaceCycloneOnSurface(pFace->surface)) return false; } return true; } const bool CanPlace(PickInfo pPickInfo) { if (pPickInfo.entity == NULL) return false; // Bail early if it's a platform. if (IsPlatform(pPickInfo.entity, pPickInfo.normal) && pPickInfo.entity->GetMass() == 0) { return true; } if (pPickInfo.entity->GetClass() == Object::ModelClass) { if (pPickInfo.surface == NULL) return false; if (!CanPlaceCycloneOnSurface(pPickInfo.surface)) return false; if (!CanCycloneBePlaced(pPickInfo.entity)) return false; } else if (pPickInfo.entity->GetClass() == Object::BrushClass) { if (!CanPlaceCycloneOnFace(pPickInfo.face)) return false; } // Do the volume test last as it's another aabb check. return !IsPointInNoCycloneVolume(pPickInfo.position); }
-
@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.
-
The very first check my pick system did was check if the surface was a static brush or a model. This was mostly done as I wanted a quick condition to prevent players putting cyclones on models Also in Leadwerks, you had to obtain the material differently based if it was a collapsed brush, uncollapsed brush, or a loaded model. Just having a way to sort what's a model and what is world geometry is pretty much what I need and that bool members worked well for me.
-
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.
-
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.
-
Part of it was due to the engine API with the biggest thing to get use to is defining what world to place the entities in. I'm trying to recreate the system I've engineered for Cyclone. Pretty much I want a window to be created and show a black screen. Upon hitting ~ on the keyboard, a console window should popup allowing control via input. I want to be able to type map <mapname> and the application will load the map file with all actors spawned and ready to go. I do this within a Stage class which pretty much had everything I needed to render a scene on the screen such as the frame buffer, and world. It also managed Stage Actors which were derived from Leadwerks' Actor class. With Ultra, things get a tricky as the engine can now handle multiple worlds at once. I see this being really handy for VR as there should always be an active world and you should never see the SteamVR Home loading screen when in-game. I also want to support changing window modes while the game is running as I got feedback on that not being possible with the old engine without causing a lot of issues. There's now Scene classes instead of the contents of the maple being automatically dumped into the current world pointer. Right now I have multiple creation functions within my new Stage class that loads entities in the Stage's world and adds it to it's own vector container. Now thinking about it, I probably should just have a Scene class as a member of stage and just use that for my entity manager. My creation wrapper functions will just call the AddEntity call instead. This way, no matter if the entity is loaded from file or created from the actor, it'll all be within the scene class which is part of my Stage Class. Regarding actors, I currently created Stage Actors in the Ultra Engine implementation. The stage just updates and passes the polled event to all of it's registered actors. This actually was really helpful drawing the panels to the screen, but I'm asking myself if I should continue to use it for gameplay objects. The new component system seems to be more modular and the editor would be able to read its values in real time thanks to everything being hpps. But because of that, and the need to use a preprocessor app, I may add support for how Actors were handled in Leadwerks. I prefer to use the hierarchy nature of C++ over a component system, hit I come from using Quakeworld tech, so I'm not the majority. I recall Ultra Engine being able to read Lua scripts in older builds. If that's included, I'll try that out. But right now I'm just interested in creating the basics of a game; which is just a glorified map loader with command support. Sadly, weekends don't last that long. I had my Visual Studio updated as well, and I still got sent to memory.h and xutility.h a lot telling me there were over 100 errors and warnings. I was also forcing myself to start using templates for things while not fully understanding how they work, so that probably didn't help ether.
-
I've spent the weekend with this. I gotta say, Ultra Engine is very verbose, and I really had to think about what I was doing. I've created App classes that do all the setting handling and Window creation alongside a Stage class much like I did with Cyclone. I wrote a lot of function wrappers, so entities are created to the stage world and registered to a vector list, so they don't go out of scope. What will be really nice is that I'll not need to recreate the camera every time the map loads. ðĪŠ Not too sure how loading a scene is going to be since I see it as its own container of entities. I might have a scene member and push new entities to its "entities" vector. Things I've in-countered: Scroll bar is still broken. Still can't make sense of how the component system works. I had better luck copying and pasting the preprocessor to my game folder but it still wasn't working correctly. I'm under the impression it's still a work in progress. Right now, I guess I'm sticking with my StageActor class. Parent UI windows don't like to be parented to windows with an active frame buffer. Showing a complex array of panels for the first time takes a bit, even on Release. I can't seem to create anything besides panels, labels and sliders within the frame buffer. That's why I only have 2 panels and a label up above, the rest is commented out. Not a big fan of having the compiler freak out and report 120 errors for minor syntax errors. It's more of a chore to find out what's wrong compared to working with Leadwerks. I would like a UpdateMatrix hook for the entities. I would like access to the material's json class member so I don't have to reload anything. I would still like access to Model::collapsedfrombrushes Noticing this grey ugly dot on the reflection of the cube. Hope this was helpful.
-
Oh yeah, I think that's broken. I wouldn't count on it being fixed unfortunately. TBH, I wouldn't worry about it. I wanted to do a lot of things for my game, but I ended up not pursuing it because I couldn't figure it out. Don't let a minor detail get in the way of things.
-
Make a panel like you did for your menu box and update its position with the mouse position ether every frame or in your event queue.
-
The GUI gets drawn ON TOP of all post rendering calls within the context layer. This was actually really convenient when I was trying to figure out what should be a HUD element and should be a UI element. You should draw all HUD icons and text to PostRender functions as it'll always get drawn below the UI. For your mouse issue, I guess you can try creating a panel and poll the mouse position from the event stack and apply it to the panel.
-
Looks like the last update broke the scroll bar for text areas, it was working last night. I would post a screenshot but the site is not letting me again.
-
Wow, that looks incredible in Leadwerks and I can't wait to see it in Ultra. Hopefully your environment class can be part of the engine itself some day. Future on everything is really exciting and I'm glad to be part of it. ð
-
Fyi, The project updated is broken with my project. The app crashes upon clicking on the hazard icon. I just recopy everything but my source and project. I'm not sure adding another library to my project it made it upset or not.