Jump to content

reepblue

Developers
  • Posts

    2,500
  • Joined

  • Last visited

Posts posted by reepblue

  1. 12 minutes ago, Josh said:

    Currently there is no merging / collapsing of brushes when a map is loaded. It's not as important in Ultra as it was in Leadwerks, because draw calls don't slow Ultra down much. I plan to add a Map::Build() command, or add some load flag that controls whether brushes get collapsed. Once that is in, then the original brushes will be gone, so there won't be anything to reload from a game save file.

    Hmm, this does solve my problem of identifying what is level geometry and what is a decorative model. I can just use the As<Brush>() cast. I guess if brush collapsing returns, please put back the public "collapsedbrush" bool or something like you had in Leadwerks.

    I also want to mention that when I loaded my save file with Map::Load(), I noticed my materials lost their normal maps. These kinds of things are hard to write examples for as it requires a lot of code and assets to showcase the problem. Maybe it's a side effect from the same problem here.

  2. Found a new bug with the Save/Load system. I think the brushes are being re-created. This example has a transparent material in the scene, and it gets opaquer after each reload.

    Load the map, Press F5, and then press F6 to see the results.

    #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, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);
    
        //Create a world
        auto world = CreateWorld();
    
        //Create a framebuffer
        auto framebuffer = CreateFramebuffer(window);
    
        //Load scene
        auto scene = LoadMap(world, "Maps/savetest3.ultra");
    
        //Main loop
        while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
        {
            if (window->KeyHit(KEY_F5))
            {
                //Save the starting scene to a file
                scene->Save("game.sav");
            }
    
            //Reload the starting scene when space key is pressed
            if (window->KeyHit(KEY_F6))
            {
                scene->Reload("game.sav");
            }
    
            world->Update();
            world->Render(framebuffer);
        }
        return 0;
    }

     

    SaveTest3.zip

  3. In the asset browser, I can't seem to change the Collision Type or gravity settings for a gltf+bin model. Might be a carry over from a previous bug. Also, for appearance, it's missing the "Static Reflection" option.

    image.png.4982631b4898122b1f2b16a8ad177aa7.png

     

    Checked items are marked as False on the Map panel.

    image.png.fe3045547aca0ccb9b27c017ae8bbea5.png

    I'll report more when I find them...

    • Thanks 1
  4. Pausing/Resuming speakers aren't working as expected.

    #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, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);
    
        //Create a world
        auto world = CreateWorld();
    
        //Create a framebuffer
        auto framebuffer = CreateFramebuffer(window);
    
        //Create a camera
        auto camera = CreateCamera(world);
        camera->SetClearColor(0.125);
        camera->SetFov(70);
        camera->SetPosition(0, 0, -3);
        camera->Listen();
    
        //Create a light
        auto light = CreateBoxLight(world);
        light->SetRotation(35, 45, 0);
        light->SetRange(-10, 10);
    
        //Create a box
        auto box = CreateBox(world);
        box->SetColor(0, 0, 1);
    
        //Sound
        auto sound = LoadSound("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Sound/notification.wav");
        auto speaker = CreateSpeaker(sound);
        speaker->SetPosition(box->GetPosition(true));
        speaker->SetRange(10);
    
        auto speakerloop = CreateSpeaker(sound);
        speakerloop->SetPosition(box->GetPosition(true));
        speakerloop->SetRange(10);
        speakerloop->SetLooping(true);
    
        auto speakerstate = speaker->GetState();
        auto speakerloopstate = speakerloop->GetState();
        bool paused = false;
        //Main loop
        while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
        {
            // P Plays the normal non-looping speaker
            if (window->KeyHit(KEY_P))
            {
                speaker->Play();
            }
    
            // L Plays the looping speaker
            if (window->KeyHit(KEY_L))
            {
                speakerloop->Play();
            }
    
            // Space pauses both speakers
            if (window->KeyHit(KEY_SPACE))
            {
                if (!paused)
                {
                    speaker->Pause();
                    speakerloop->Pause();
                    paused = true;
                }
                else
                {
                    speaker->Resume();
                    speakerloop->Resume();
                    paused = false;
                }
            }
    
            // Report the state
            if (speaker->GetState() != speakerstate)
            {
                Print("Normal Speaker state at: " + String(speaker->GetState()));
                speakerstate = speaker->GetState();
            }
    
            if (speakerloop->GetState() != speakerloopstate)
            {
                Print("Looping Speaker state at: " + String(speakerloop->GetState()));
                speakerloopstate = speakerloop->GetState();
            }
    
            //Move and turn with the arrow keys - best experienced with headphones
            if (window->KeyDown(KEY_UP)) camera->Move(0, 0, 0.1);
            if (window->KeyDown(KEY_DOWN)) camera->Move(0, 0, -0.1);
            if (window->KeyDown(KEY_LEFT)) camera->Turn(0, -1, 0);
            if (window->KeyDown(KEY_RIGHT)) camera->Turn(0, 1, -0);
    
            world->Update();
            world->Render(framebuffer);
        }
        return 0;
    }

    Right now, I have to do this hack in my project.

    	void GameSpeaker::Pause()
    	{
    		if (speaker)
    		{
    			if (speaker->GetState() == SPEAKER_PLAYING)
    			{
    				pausetime = speaker->GetTime();
    				speaker->Pause();
    			}
    		}
    	}
    
    	void GameSpeaker::Resume()
    	{
    		if (speaker)
    		{
    			if (speaker->GetState() == SPEAKER_PAUSED || pausetime > 0)
    			{
    				speaker->SetTime(pausetime);
    				speaker->Play();
    				pausetime = 0;
    			}
    		}		
    	}

     

  5. I'm trying to make an editor extension that'll create new files from the editor. I'm working on a "Create New Material" function, but I get an error with the Save command saying it expects usedata type and not a string, although I feel like this code is correct.

    local extension = {}
    
    function CreateNewMaterial()
        local file = RequestFile("Select Material Location", "", "Ultra Engine Material File (*.mat):mat", 0, true)
        if file ~= nil then
            local mat = CreateMaterial()
            if mat ~= nil then
                mat:SetColor(1,1,1,1)
                local shaderfamily = LoadShaderFamily("Shaders/PBR.fam")
                if shaderfamily then
                    mat:SetShaderFamily(shaderfamily)
                    shaderfamily = nil
                end
                mat:Save(file);
            end
        end
    end
    
    function extension.hook(event, extension)
        if event.id == EVENT_WIDGETACTION then
            if event.source == extension.menuitem then
                CreateNewMaterial()
            end
        end
    end
    
    --------------------------------------------------------------------
    -- Add menu item
    --------------------------------------------------------------------
    
    local menu = program.menu:FindChild("Create", false)
    if menu ~= nil then
        local submenu = menu:FindChild("Asset", false)
        if submenu == nil then
            submenu = CreateMenu("Asset", menu)
        end
        extension.menuitem = CreateMenu("Material", submenu)
    end
    
    ListenEvent(EVENT_WIDGETACTION, extension.menuitem, extension.hook, extension)
    
    

    I also tried making a table and saving it, but it didn't work ether.

            local a = ctable()
            a["material"] = nil
            a["material"]["shaderFamily"] = "Shaders/PBR.fam"
            SaveTable(a, file)

    What am I doing wrong here?

  6. 11 hours ago, Josh said:

    Hmmm...I still have not made up my mind. What is our "native" texture format? DDS, Basis, or KTX2?

    I assumed it was DDS for traditional games, basis for simulations, and ktx for if Ultra runs on something like the quest.

    The question I've ran into is what is the best modeling format since gltf is technically 3 formats.

  7. I'm playing around with the editor and noticed when I set a light (Such as a point light) to static, my app crashes as soon as it renders in the camera.

    I'm noticing this from the editor, but I think this example will reproduce the results when pressing space.

    #include "UltraEngine.h"
    #include "Components/Motion/Mover.hpp"
    
    using namespace UltraEngine;
    
    int main(int argc, const char* argv[])
    {
        //Plugin for texture loading
        auto plugin = LoadPlugin("Plugins/FITextureLoader");
    
        //Get display
        auto displays = GetDisplays();
    
        //Create window
        auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_TITLEBAR | WINDOW_CENTER);
    
        //Create framebuffer
        auto framebuffer = CreateFramebuffer(window);
    
        //Create world
        auto world = CreateWorld();
        world->SetAmbientLight(0.1);
        world->RecordStats(true);
    
        //Create camera
        auto camera = CreateCamera(world);
        camera->SetClearColor(0.25);
        camera->SetPosition(0, 2, 0);
        camera->Move(0, 0, -5);
    
        //Build scene
        auto tunnel = LoadModel(world, "https://github.com/UltraEngine/Documentation/raw/master/Assets/Models/Underground/tunnel_t.glb");
        tunnel->SetRotation(0, 180, 0);
        tunnel->Staticize();
    
        auto cage = LoadModel(world, "https://github.com/UltraEngine/Documentation/raw/master/Assets/Models/Underground/fancage.glb");
        cage->Staticize();
    
        auto fan = LoadModel(world, "https://github.com/UltraEngine/Documentation/raw/master/Assets/Models/Underground/fanblades.glb");
        fan->SetPosition(0, 2, 0);
        auto mover = fan->AddComponent<Mover>();
        mover->rotation.z = 300;
    
        auto light = CreatePointLight(world);
        light->SetColor(2, 2, 2);
        light->SetRange(10);
        light->SetPosition(0, 2, 2);
        light->SetColor(4.0);
    
        //Display text
        auto orthocam = CreateCamera(world, PROJECTION_ORTHOGRAPHIC);
        orthocam->SetClearMode(CLEAR_DEPTH);
        orthocam->SetRenderLayers(128);
        orthocam->SetPosition(float(framebuffer->size.x) * 0.5, float(framebuffer->size.y) * 0.5f);
    
        auto font = LoadFont("Fonts/arial.ttf");
    
        auto text = CreateSprite(world, font, "Shadow polygons: 0", 14.0 * displays[0]->scale);
        text->SetPosition(2, framebuffer->size.y - 16.0f * displays[0]->scale);
        text->SetRenderLayers(128);
    
        auto text2 = CreateSprite(world, font, "Press space to make the light static.", 14.0 * displays[0]->scale);
        text2->SetPosition(2, framebuffer->size.y - 16.0f * 2.0f * displays[0]->scale);
        text2->SetRenderLayers(128);
    
        //Main loop
        while (!window->KeyHit(KEY_ESCAPE) and !window->Closed())
        {
            world->Update();
            world->Render(framebuffer);
    
            if (window->KeyHit(KEY_SPACE))
            {
                light->Staticize();
                text2->SetHidden(true);
            }
    
            text->SetText("Shadow polygons: " + String(world->renderstats.shadowpolygons));
        }
        return 0;
    }

     

  8. FYI, don't do this, The window didn't draw correctly at 100% scaling.

    #include "UltraEngine.h"
    #include "Components/Motion/Mover.hpp"
    #include "Components/Player/CameraControls.hpp"
    
    using namespace UltraEngine;
    
    int main(int argc, const char* argv[])
    {
        auto cl = ParseCommandLine(argc, argv);
    
        RegisterComponent<Mover>();
        RegisterComponent<CameraControls>();
    
        //Get the displays
        auto displays = GetDisplays();
    
        //Create a window
        auto window = CreateWindow("Ultra Engine", 0, 0, 1280 * 2, 720 * 2, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);
    
        //Create a world
        auto world = CreateWorld();
    
        //Create a framebuffer
        auto framebuffer = CreateFramebuffer(window);
    
        //Load the map
        WString mapname = "Maps/start.ultra";
        if (cl["map"].is_string()) mapname = std::string(cl["map"]);
        auto scene = LoadMap(world, mapname);
    
        //Main loop
        while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
        {
            world->Update();
            world->Render(framebuffer);
        }
        return 0;
    }

     

    Do something like this.

    #include "UltraEngine.h"
    #include "Components/Motion/Mover.hpp"
    #include "Components/Player/CameraControls.hpp"
    
    using namespace UltraEngine;
    
    int main(int argc, const char* argv[])
    {
        auto cl = ParseCommandLine(argc, argv);
    
        RegisterComponent<Mover>();
        RegisterComponent<CameraControls>();
    
        //Get the displays
        auto displays = GetDisplays();
    
        //Create a window
        auto window = CreateWindow("Ultra Engine", 0, 0, 1280 * (int)displays[0]->GetScale(), 720 * (int)displays[0]->GetScale(), displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);
    
        //Create a world
        auto world = CreateWorld();
    
        //Create a framebuffer
        auto framebuffer = CreateFramebuffer(window);
    
        //Load the map
        WString mapname = "Maps/start.ultra";
        if (cl["map"].is_string()) mapname = std::string(cl["map"]);
        auto scene = LoadMap(world, mapname);
    
        //Main loop
        while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
        {
            world->Update();
            world->Render(framebuffer);
        }
        return 0;
    }

    Only thing is that you need to cast the float to an int which might cause problems. 

  9. 1 hour ago, Josh said:

    The plugin is FITextureLoader.dll. FreeImage.dll is not a plugin, it is a required DLL the plugin DLL must use.

    I think the names of plugins should have a universal prefix so people know what to actually load. 

    • Upvote 2
  10. 17 hours ago, Josh said:

    Fixed.

    I removed the fog settings because fog is a per-camera settings and the other stuff is all per-world.

    I am not sure how fog and post-effects should be handled yet. Intuitively it seems like they would be set for the world, but I need to determine the rules that are in place for cameras that are created in code and in the scene, and whether cameras should have their own individual settings for these, and how that interacts with the per-map setting.

    I mean, it was the same thing in Leadwerks and although confusing at first, I understood how it worked after a while.

    I think the map should store the fog/post effect information and then the end user should be able to apply them in the load function of their component. It might be too much, but that's just a quick idea I had.

  11. 1. Create a json component file with these contents.

    {
        "component":
        {
            "properties":
            [
                {
                    "name": "filter",
                    "label": "Filter",
                    "value": ""
                },
                {
                    "name": "size",
                    "label": "Size",
                    "value": [0.0, 0.0, 0.0]
                }
            ]
        }
    }

    2. Create an entity and attach the component script to it.

    3. Change both values to anything.

    4. Create a new entity, attach the same component.

    You should see that "Size" is back to 0,0,0, but the "Filter" property got carried over from the first entity. 

    • Thanks 1
  12. 9 minutes ago, Josh said:

    Oh, okay it just looks like the ambient light is not being saved in the game save.

    As I mentioned here, a lot of scene properties don't get saved from the editor. Not sure if this carries over to user saves.

    But can't wait to try this. I've been very conservative about making components because I couldn't test reloading them.

×
×
  • Create New...