Jump to content

Ultra Engine testing


Josh
 Share

Recommended Posts

Ok, then how would someone make a loading bar or spinner when the map is loading? I recall this being asked around a lot during the Leadwerks days. Would I put the spinner on the separate thread instead since that just needs to rotate/change images?

Something else to consider is you probably want background map loading when VR gets implemented. Maybe official level streaming support can come later, idk.

I'm more worried about my skinned meshes not reloading and some of my prefabs still have their UVs messed up when it comes to scene loading at the moment than a silly spinny wheel.

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

The renderer actually will keep going while the map is loading, even if it is blocking the main thread. In VR this means you can still look around at whatever is currently in the world, and everything works fine. You can use a shader the uses the current time to rotate one of those never-ending load indicators because it does not require any new information to come from the blocked main thread. I have thought about a LoadScene callback you could use to relay the loading progress from the main thread to the rendering thread, but I am not sure yet how that would work. Calling World::Render() in the middle of a callback would cause the scene to appear piece-by-piece. Maybe that would work if you were using render layers to control what the camera sees, or loading the scene into a separate world from the one that is being rendered. I'm not sure yet.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

I guess I'll have experiment with it more outside debug mode as the application cames to a screeching hault when loading big maps. In reale it's 10x faster.

 

8 minutes ago, Josh said:

You can use a shader the uses the current time to rotate one of those never-ending load indicators because it does not require any new information to come from the blocked main thread.

Hopefully this will be easier to do in the future. Kind of shy to learn shaders with them being massive this time around.

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

just a small proof of concept i made:

image.thumb.png.f93a5978fa29042a0c4124bd015e9780.png

The top line  ShaderValidator::ShaderCompiler::Compile(); is the interessting part.

This method parses all json shaderfamilies and extracts the required shader files and tries to locate the correct source and target. then it takes all of the found shaders and recompiles them to Spirv-binary files in code before any shader is loaded.

  • Upvote 1
  • Windows 10 Pro 64-Bit-Version
  • NVIDIA Geforce 1080 TI
Link to comment
Share on other sites

Update

  • Made a lot of members protected in the WIdget class that should not be public
  • Fixed FileType not detecting package files

@reepblueYour example is now working correctly, but I just noticed that when loading your provided scene from a ZIP file is was quite a lot slower than when I extracted the material files to the project folder.

  • Like 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

9 minutes ago, Josh said:

@reepblueYour example is now working correctly, but I just noticed that when loading your provided scene from a ZIP file is was quite a lot slower than when I extracted the material files to the project folder

Thanks,

Think the speed has something to do how the zip is compressed? I used 7z with the -a flag to make the zip. I recently found ZipLib which is a modern C++ zip library that can be used to package games. I only got to compiling it as one static library last night.

I also noticed that the package only works if the extension is.zip. in Cyclone, I have my packages as .pak but I understand that this can cause conflicts with package plugins.

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

That was my first thought, but the decompression speed is fine. Ultra has a "feature" that tries to detect files that may be locked by another process, like when a paint program saves an image:

		//Load disk files
#ifdef _WIN32
		FILE* file = _wfopen(rpath.c_str(), L"rb");
#else
		std::string ss = rpath.ToUTF8String();
		FILE* file = fopen(ss.c_str(), "rb");
#endif
		//Locked files (file is being written to by another process or thread)
		if (file == NULL and FileType(rpath) == 1)
		{
			int duration = 250;
			for (int n = 0; n < 5; ++n)
			{
				Sleep(duration);
				file = _wfopen(rpath.c_str(), L"rb");
				if (file != NULL) break;
				duration *= 2;
			}
		}

This was being triggered by every file loaded from the package because FileType was always returning 1, indicating that a file existed on the hard drive. And of course the file could not be loaded this way, so it was adding 1.25 second delay for each file.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Update

  • Fixed zip file slow loading speed
  • Zip packages are now detected by examining the file header instead of checking the file extension, so you can name them anything you want and they will still work
  • Like 1
  • Thanks 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

18 hours ago, reepblue said:

Also, @SpiderPig said something about the fog being broken and here's a picture of it. Load any lvl# map of Cyclone to notice no fog in the void. I got this artifact randomly and took a screen of it.

image.thumb.png.5c731be95ada313cb2a88a0ba7e7acec.png

Does this only happen when fog is enabled, or all the time?

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

6 hours ago, Josh said:

It's working perfectly. Notice the MOUSELEAVE event is even being emitted when you hover over the child. This is exactly what it is supposed to do. :)

Don't think in terms of hierarchies, think in terms of "which widget is directly under the mouse cursor?".

Oh I understand now.  So if I wanted to send the MOUSE_ENTER and MOUSE_MOVE events to the parents I simply need to call the call-back on the parent too?  Pretty much exactly what @Dreikblack said but in my case like this:

bool EventCallback(const Event& event, shared_ptr<Object> extra) {
  //Do Stuff
  
  auto parent = event.source->As<Widget>()->Getparent();
  if(parent != nullptr) {
  	event.source = parent;
  	EventCallback(event, extra);
  }
}

 

This example no longer works with Widget::Initialize being inaccessible.

https://www.ultraengine.com/learn/CustomWidgets?lang=cpp

Link to comment
Share on other sites

Is the child always in the way, and doesn't get used for anything? Is it just decorative? If that is the case, you can call child->SetInteractive(false) and it will be ignored by events. Any mouse events will occur on the parent, and the child will be considered just visual.

This is how I made the icon and text labels appear on the project buttons in the client app.

  • Thanks 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

3 minutes ago, Josh said:

Is the child always in the way, and doesn't get used for anything? Is it just decorative? If that is the case, you can call child->SetInteractive(false) and it will be ignored by events. Any mouse events will occur on the parent, and the child will be considered just visual.

This is how I made the icon and text labels appear on the project buttons in the client app.

Perfect!  That'll do it.  Thankyou.

  • Like 1
Link to comment
Share on other sites

11 minutes ago, SpiderPig said:

This example no longer works with Widget::Initialize being inaccessible.

https://www.ultraengine.com/learn/CustomWidgets?lang=cpp

Thank you. I updated the example here:
https://github.com/UltraEngine/Documentation/blob/master/CPP/CustomWidgets.md

It will take 24 hours for the documentation cache to refresh, so just copy it from Github.

  • Like 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

15 minutes ago, Josh said:

Does this only happen when fog is enabled, or all the time?

I noticed this for the first time last night, but none of the maps don't seem to have fog enabled. 

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

I'd like to use a custom widget for a button that uses textures, one for the normal state and another for the hover.  I don't know if I should do it like this though, the textures don't show.  In one project the normal state shows but the hover state doesn't, here neither show up.

#include "UltraEngine.h"

using namespace UltraEngine;

//Declare new style constants
enum CustomWidgetStyle
{
    CUSTOMWIDGET_DEFAULT = 0
};

//Declare new widget class
class CustomWidget : public Widget
{
    //Custom members
    bool hover;
    shared_ptr<Texture> t1, t2;

protected:

    virtual bool Initialize(const WString& text, const int x, const int y, const int width, const int height, shared_ptr<Widget> parent, const int style)
    {
        t1 = LoadTexture("pinkgrid.dds");
        t2 = LoadTexture("bluegrid.dds");
        return Widget::Initialize(text, x, y, width, height, parent, style);
    }

    //Called when the mouse moves if this widget has the focus
    virtual void MouseMove(const int x, const int y) {}

    //Called when the mouse cursor enters the widget bounds
    virtual void MouseEnter(const int x, const int y)
    {
        hover = true;
        Redraw();
    }

    //Called when the mouse cursor leaves the widget bounds
    virtual void MouseLeave(const int x, const int y)
    {
        hover = false;
        Redraw();
    }

    //Called when the mouse button is pressed
    virtual void MouseDown(const MouseButton button, const int x, const int y)
    {
        if (button == MOUSE_LEFT) EmitEvent(EVENT_WIDGETACTION, Self());
    }

    //Called when the mouse button is released
    virtual void MouseUp(const MouseButton button, const int x, const int y) {}

    //Called when another widget becomes selected
    virtual void LoseFocus() {}

    //Called when mouse double-click occurs
    virtual void DoubleClick(const MouseButton button, const int x, const int y) {}

    //Called when mouse triple-click occurs
    virtual void TripleClick(const MouseButton button, const int x, const int y) {}

    //Called when widget is selected
    virtual void GainFocus() {}

    //Called when key is pressed
    virtual void KeyDown(const KeyCode key) {}

    //Called when key is released
    virtual void KeyUp(const KeyCode key) {}

    //Called for each keydown event
    virtual void KeyChar(const int keychar) {}

    //Called when mouse wheel turns and mouse is hovered over this widget
    virtual void MouseWheel(const int delta, const int x, const int y) {}

    //Called each time the widget is redrawn
    virtual void Draw(const int x, const int y, const int width, const int height)
    {
        blocks.clear();

        //Background rectangle
        int b = AddBlock(iVec2(0), this->size, Vec4(1));
        blocks[b].texture = (hover ? t1 : t2);

        //Foreground text
        AddBlock(text, iVec2(0), this->size, Vec4(1), TEXT_CENTER | TEXT_MIDDLE);
    }
public:

    //Constructor
    CustomWidget() : hover(false)
    {}

    friend shared_ptr<Widget> CreateCustomWidget(const WString&, const int, const int, const int, const int, shared_ptr<Widget>, const CustomWidgetStyle);
};

//Create function
shared_ptr<Widget> CreateCustomWidget(const WString& text, const int x, const int y, const int width, const int height, shared_ptr<Widget> parent, const CustomWidgetStyle style)
{
    auto widget = std::make_shared<CustomWidget>();
    widget->Initialize(text, x, y, width, height, parent, style);
    return widget;
}

int main(int argc, const char* argv[])
{
    auto displays = GetDisplays();
    auto window = CreateWindow("Ultra Engine", 0, 0, 800, 600, displays[0]);
    auto framebuffer = CreateFramebuffer(window);
    auto world = CreateWorld();

    auto camera = CreateCamera(world);
    camera->Move(0, 0, -3);

    auto box = CreateBox(world);

    auto default_font = LoadFont("Fonts\\arial.ttf");
    auto ui = CreateInterface(world, default_font, framebuffer->size);
    ui->SetRenderLayers(2);
    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(2);
    ui_camera->SetClearMode(CLEAR_DEPTH);

    //Create widget
    auto widget = CreateCustomWidget("Custom", 20, 20, 120, 36, ui->root, CUSTOMWIDGET_DEFAULT);
  
    auto panel = CreatePanel(100, 100, 100, 100, ui->root);
    panel->SetColor(1, 0, 0);

    while (true)
    {
        while (PeekEvent()) {
            auto ev = WaitEvent();
            switch (ev.id)
            {
            case EVENT_WIDGETACTION:
                Print("Widget action: " + String(ev.data));
                break;
            case EVENT_WINDOWCLOSE:
                return 0;
                break;
            }
        }

        world->Update();
        world->Render(framebuffer);
    }
    return 0;
}

 

Images.zip

Link to comment
Share on other sites

10 hours ago, Josh said:

Widgets don't have a persistent order. Widget blocks are assigned an order any time anything changes. The number of widget blocks, and whether they are hidden or shown, can change from one action to the next.

What's really needed here is a widget block that can display a line. I don't want to add this until there is time to test on Quartz, GDI, and XRender, because I don't want to start adding features to the 3D GUI that are not supported by a GUI created on a window.

Yeah I agree.  Having said that though, I would still like to know at what depth the widget is at.  In my case I would ping the depth every loop and set my sprites accordingly anyway, so it doesn't matter if it changes.  At least it would be a fix until you're ready to work on widget blocks supporting lines.

Link to comment
Share on other sites

11 minutes ago, SpiderPig said:

I'd like to use a custom widget for a button that uses textures, one for the normal state and another for the hover.  I don't know if I should do it like this though, the textures don't show.  In one project the normal state shows but the hover state doesn't, here neither show up.

Ah, you have discovered why I keep talking about consistency. I was trying to figure out why none of the sprite creation code was getting called, and finally realized you created the interface on a window. So naturally, a Vulkan texture would not appear. :D

auto ui = CreateInterface(window);

 

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Essentially a repost of the problem I posted earlier but with an additional problem.  The panel on the right has a border drawn on the pixmap itself but it is not visible on the panel.  The panels here are sized 64x64 and the textures are 128x128.  I might be making the wrong assumption that the widgets texture coords are 0 to 1 respectively regards of their size?

There's also the alpha issue here too.

PixmapIssues.png.4d9e9dbb62016765d76367b1e0de383e.png

 

#include "UltraEngine.h"
#include "ComponentSystem.h"

using namespace UltraEngine;

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, 0, -3);

    auto font = LoadFont("Fonts\\arial.ttf");
    auto ui = CreateInterface(world, font, framebuffer->size);
    ui->SetRenderLayers(2);
    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(2);
    ui_camera->SetClearMode(CLEAR_DEPTH);

    auto light = CreateBoxLight(world);
    light->SetRotation(35, 45, 0);
    light->SetRange(-10, 10);

    auto box = CreateBox(world);
    box->SetColor(0, 0, 1);

    auto actor = CreateActor(box);
    auto component = actor->AddComponent<Mover>();
    component->rotation.y = 45;

    auto widget = CreatePanel(600, 350, 64, 64, ui->root, PANEL_BORDER);
    widget->SetColor(1.0f, 1.0f, 1.0f, 0.25f);
    widget->SetPixmap(LoadPixmap("Background.dds"));

    auto w2 = CreatePanel(670, 350, 64, 64, ui->root);
    w2->SetColor(1.0f, 1.0f, 1.0f, 0.25f);
    w2->SetPixmap(LoadPixmap("NewBackground.dds"));

    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {
        world->Update();
        world->Render(framebuffer);
    }
    return 0;
}

 

Background.zip

Link to comment
Share on other sites

@reepblue I'm not sure what I am looking for. Everything looks okay if I use this code to load a map:

#include "UltraEngine.h"
#include "ComponentSystem.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, 1280, 720, 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->SetPosition(0, 0, -4);
    camera->SetClearColor(0,0,1);

    auto actor = CreateActor(camera);
    actor->AddComponent<CameraControls>();

    auto scene = LoadScene(world, "maps/lvl6.map");

    auto box = CreateBox(world);

    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {
        world->Update();
        world->Render(framebuffer);
    }
    return 0;
}

 

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

I notice the signs have a strange error in their cubemap reflections. If I recall correctly, this is caused by texture assignment in a custom shader...there's a texture being used for a normal map that isn't a normal map, something like that.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

12 hours ago, SpiderPig said:

I'd like to use a custom widget for a button that uses textures, one for the normal state and another for the hover.  I don't know if I should do it like this though, the textures don't show.  In one project the normal state shows but the hover state doesn't, here neither show up.

You just need to send events to the interface, since it is not created on a window, and it will work fine:

        while (PeekEvent()) {
            auto ev = WaitEvent();
            switch (ev.id)
            {
            case EVENT_WIDGETACTION:
                Print("Widget action: " + String(ev.data));
                break;
            case EVENT_WINDOWCLOSE:
                return 0;
                break;            
            }
            ui->ProcessEvent(ev);
        }

You probably want to change the widget background color because right now your draw method creates white text on a white background.

  • Thanks 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

  • Josh locked this topic
Guest
This topic is now closed to further replies.
 Share

×
×
  • Create New...