Jump to content

Josh

Staff
  • Posts

    23,143
  • Joined

  • Last visited

Everything posted by Josh

  1. The default pixmap position mode is PIXMAP_CENTER. This places the image in the center of the widget, but does not stretch or squeeze the image to fill the widget. There are other options that can be used to change the size the image is displayed at. However, if you were to fit the image into a panel half its size, the one-pixel border on the edges would likely not be visible. When the panel is sized to the same size as the image, the image border is visible. This example also shows that the panel on the left, which uses the PANEL_BORDER style, has an error in its drawing, as the border is one pixel off where it should be. However, these small artifacts are the lowest priority to solve right now.
  2. 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.
  3. 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.
  4. @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; }
  5. I was actually looking at this recently. I used spreadshirt for the hoodies, which I feel were very nice. Unfortunately they “streamlined” their system so you cannot sell items made with the design tool. You can only upload a single logo and it just automatically applies it everywhere. The hoodies looked awesome because they had print on the front, back, and down one sleeve. there are some other sites that do the same thing but I have not looked into it thoroughly yet.
  6. Why indeed? I am looking into this. Stay tuned for more fun tomorrow...
  7. 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. auto ui = CreateInterface(window);
  8. 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.
  9. 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.
  10. Does this only happen when fog is enabled, or all the time?
  11. Moved here so I don't lose track of this...
  12. 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
  13. 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.
  14. 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.
  15. Josh

    ChatGPT

    Create a name or title to call this code example "Modifying a Terrain with Mouse Input in Ultra Engine" What aspect of the terrain is being modified? The elevation of the vertices of the terrain is being modified. Specifically, the elevation of the vertices within a certain radius of the mouse cursor are increased when the left mouse button is pressed. The strength of the brush decreases with distance from the center of the brush, so vertices further from the center are affected less.
  16. 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.
  17. Josh

    ChatGPT

    I removed all the comments and told it to add comments and a description to this C++ example: https://www.ultraengine.com/learn/Terrain_SetElevation Look at the results. The word "brush" does not appear in the code, but it inferred we are doing a brush-like operation. It knows what the code is doing "Calculate the position of the picked point on the terrain": /* This code is a program that displays a 3D terrain and allows the user to sculpt the terrain by clicking and dragging the mouse. The program creates a window, a 3D world, a camera, a light, and a terrain. It also loads two textures and creates a material using these textures. The material is then applied to the terrain. The program also creates an actor with a camera and adds the CameraControls component to it. The main loop of the program runs until the window is closed or the escape key is pressed. While the loop is running, if the left mouse button is down, the program retrieves the object under the mouse cursor and, if it is the terrain, calculates a region around the mouse cursor and increases the elevation of each point in this region by a value that decreases with distance from the mouse cursor. Finally, the program updates the world and renders it to the framebuffer. */ #include "UltraEngine.h" #include "ComponentSystem.h" // Adds the UltraEngine namespace to the code. using namespace UltraEngine; // The main function of the program. It takes two arguments: // - argc: the number of arguments passed to the program // - argv: an array of strings representing the arguments passed to the program int main(int argc, const char* argv[]) { // Retrieves a list of available displays. auto displays = GetDisplays(); // Creates a window with the specified parameters: // - "Terrain Sculpt": the title of the window // - 0, 0: the x and y position of the window // - 1280, 720: the width and height of the window // - displays[0]: the display on which to create the window // - WINDOW_TITLEBAR | WINDOW_CENTER: flags specifying that the window should have a title bar and be centered on the display auto window = CreateWindow("Terrain Sculpt", 0, 0, 1280, 720, displays[0], WINDOW_TITLEBAR | WINDOW_CENTER); // Creates an empty 3D world. auto world = CreateWorld(); // Creates a framebuffer for the specified window. auto framebuffer = CreateFramebuffer(window); // Creates a camera for the specified world. auto camera = CreateCamera(world); // Sets the field of view of the camera to 70 degrees. camera->SetFov(70); // Sets the position of the camera to (0, 100, -100). camera->SetPosition(0, 100, -100); // Sets the rotation of the camera to (45, 0, 0). camera->SetRotation(45, 0, 0); // Sets the clear color of the camera to a very light grey. camera->SetClearColor(0.125); // Creates a directional light for the specified world. auto light = CreateDirectionalLight(world); // Sets the rotation of the light to (45, 35, 0). light->SetRotation(45, 35, 0); // Creates a terrain with the specified parameters: // - world: the world to which to add the terrain // - 512: the resolution (number of vertices) of the terrain along each axis auto terrain = CreateTerrain(world, 512); // Sets the scale of the terrain to (1, 100, 1). terrain->SetScale(1, 100, 1); // Loads a texture from the specified URL. auto diffusemap = LoadTexture("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/river_small_rocks_diff_4k.dds"); // Loads a texture from the specified URL. auto normalmap = LoadTexture("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/river_small_rocks_nor_gl_4k.dds"); // Creates a material. auto ground = CreateMaterial(); // Sets the diffusemap texture as the diffuse texture of the material. ground->SetTexture(diffusemap, TEXTURE_DIFFUSE // Sets the normalmap texture as the normal texture of the material. ground->SetTexture(normalmap, TEXTURE_NORMAL); // Sets the ground material as the material of the terrain. terrain->SetMaterial(ground); // Creates an actor with the specified camera. auto actor = CreateActor(camera); // Adds the CameraControls component to the actor. actor->AddComponent<CameraControls>(); // The main loop of the program. This loop will run until the window is closed or the escape key is pressed. while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { // If the left mouse button is down: if (window->MouseDown(MOUSE_LEFT)) { // Get the current mouse position. auto mousepos = window->GetMousePosition(); // Get the pick information (information about the object under the mouse) from the camera. auto pickinfo = camera->Pick(framebuffer, mousepos.x, mousepos.y); // If a pick was successful: if (pickinfo.success) { // If the picked object is the terrain: if (pickinfo.entity == terrain) { // Calculate the position of the picked point on the terrain. iVec2 pos; pos.x = Round(pickinfo.position.x) + terrain->resolution.x / 2; pos.y = Round(pickinfo.position.z) + terrain->resolution.y / 2; // Set the radius of the brush to 20. int radius = 20; // Iterate over a square region centered at the picked point with the specified radius. for (int x = pos.x - radius; x < pos.x + radius; ++x) { for (int y = pos.y - radius; y < pos.y + radius; ++y) { // Calculate the strength of the brush at this point. float strength = 1.0f - Vec3(x, y, 0).DistanceToPoint(Vec3(pos.x, pos.y, 0)) / float(radius); // Skip this point if the strength is 0 or negative. if (strength <= 0.0f) continue; // Get the elevation of the terrain at this point. float h = terrain->GetElevation(x, y); // Increase the elevation by half the strength. h += 0.5 * strength; // Set the new elevation of the terrain at this point. terrain->SetElevation(x, y, h); } } } } } // Update the world. world->Update(); // Render the world to the framebuffer. world->Render(framebuffer); } // Return 0 to indicate that the program has finished executing successfully. return 0; }
  18. Please do not do this! You will definitely break things badly! 😂 This will cause newly created entities to modify the world octree and add commands to the rendering and physics command buffers, none of which is a thread-safe operation.
  19. Josh

    ChatGPT

    I asked for it to add a comment that describes what the code does:
  20. Josh

    ChatGPT

    Holy moly. I removed my own comments and started over, telling it to add comments. Its comments are all very accurate, and more descriptive than my own. "Create a window centered on the first display with a title bar"? 😱 -- Import the UltraEngine module local UltraEngine = require("UltraEngine") -- Get a list of displays local displays = UltraEngine.GetDisplays() -- Create a window centered on the first display with a title bar local window = UltraEngine.CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[1], UltraEngine.WINDOW_CENTER + UltraEngine.WINDOW_TITLEBAR) -- Create a framebuffer for the window local framebuffer = UltraEngine.CreateFramebuffer(window) -- Create a new world local world = UltraEngine.CreateWorld() -- Create a camera in the world local camera = UltraEngine.CreateCamera(world) -- Set the position of the camera camera:SetPosition(0, 0, -2) -- Set the clear color of the camera camera:SetClearColor(0.125) -- Create a box light in the world local light = UltraEngine.CreateBoxLight(world) -- Set the range of the light light:SetRange(-10, 10) -- Set the rotation of the light light:SetRotation(45, 35, 0) -- Set the color of the light light:SetColor(2) -- Create a box in the world local box = UltraEngine.CreateBox(world) -- Set the mass of the box box:SetMass(1) -- Set the color of the box box:SetColor(0, 0, 1) -- Disable gravity for the box box:SetGravityMode(false) -- Main game loop while window:Closed() == false and window:KeyDown(UltraEngine.KEY_ESCAPE) == false do -- Check if the space bar was hit if window:KeyHit(UltraEngine.KEY_SPACE) then -- Add a force to the box box:AddForce(100, 0, 0) end -- Update the world world:Update() -- Render the world to the framebuffer world:Render(framebuffer) end
  21. 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?".
  22. A model can have a skeleton, but a skeleton does not have a model. A skeleton can be used across multiple models: https://www.ultraengine.com/learn/Model_SetSkeleton?lang=cpp So the position and rotation will be relative to the skeleton, not to any model.
  23. These functions are for creating custom widgets, but I don't see any problem in how they are being used in the suggested solution above. Well, that's not exactly true. According to the documentation, these are supposed to be protected methods, meaning another class cannot access them, although they are not actually declared that way in the current build.
  24. The issue is that widget pixmaps do not get tinted by the widgetblock color. The reason for this is I am not sure if it is possible to draw a colored picture with XRender. It would be easy to enable this for Vulkan, but I want the GUI to have consistent capabilities everywhere it is being used.
  25. Josh

    ChatGPT

    Holy crap, it can convert code between languages. I pasted some C++ code and said to covert it to Lua and it gave me this. It even knows to use 1 instead of 0 for the array index in Lua: -- Import the UltraEngine module local UltraEngine = require("UltraEngine") -- Get the displays local displays = UltraEngine.GetDisplays() -- Create a window local window = UltraEngine.CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[1], UltraEngine.WINDOW_CENTER + UltraEngine.WINDOW_TITLEBAR) -- Create a framebuffer local framebuffer = UltraEngine.CreateFramebuffer(window) -- Create a world local world = UltraEngine.CreateWorld() -- Create a camera local camera = UltraEngine.CreateCamera(world) camera:SetPosition(0, 0, -2) camera:SetClearColor(0.125) -- Create light local light = UltraEngine.CreateBoxLight(world) light:SetRange(-10, 10) light:SetRotation(45, 35, 0) light:SetColor(2) -- Create model local box = UltraEngine.CreateBox(world) box:SetMass(1) box:SetColor(0, 0, 1) box:SetGravityMode(false) while window:Closed() == false and window:KeyDown(UltraEngine.KEY_ESCAPE) == false do -- Press the space key to apply a force if window:KeyHit(UltraEngine.KEY_SPACE) then box:AddForce(100, 0, 0) end world:Update() world:Render(framebuffer) end Then I told it to do the same without loading the "UltraEngine" module, and to assume the required functions and variables were already available to use: -- Get the displays local displays = GetDisplays() -- Create a window local window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[1], WINDOW_CENTER + WINDOW_TITLEBAR) -- Create a framebuffer local framebuffer = CreateFramebuffer(window) -- Create a world local world = CreateWorld() -- Create a camera local camera = CreateCamera(world) camera:SetPosition(0, 0, -2) camera:SetClearColor(0.125) -- Create light local light = CreateBoxLight(world) light:SetRange(-10, 10) light:SetRotation(45, 35, 0) light:SetColor(2) -- Create model local box = CreateBox(world) box:SetMass(1) box:SetColor(0, 0, 1) box:SetGravityMode(false) while window:Closed() == false and window:KeyDown(KEY_ESCAPE) == false do -- Press the space key to apply a force if window:KeyHit(KEY_SPACE) then box:AddForce(100, 0, 0) end world:Update() world:Render(framebuffer) end Then I asked it to add comments for every line of code. Look what it added to the main loop: -- Get the displays local displays = GetDisplays() -- Create a window local window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[1], WINDOW_CENTER + WINDOW_TITLEBAR) -- Create a framebuffer local framebuffer = CreateFramebuffer(window) -- Create a world local world = CreateWorld() -- Create a camera local camera = CreateCamera(world) camera:SetPosition(0, 0, -2) -- Set the position of the camera camera:SetClearColor(0.125) -- Set the clear color of the camera -- Create light local light = CreateBoxLight(world) light:SetRange(-10, 10) -- Set the range of the light light:SetRotation(45, 35, 0) -- Set the rotation of the light light:SetColor(2) -- Set the color of the light -- Create model local box = CreateBox(world) box:SetMass(1) -- Set the mass of the box box:SetColor(0, 0, 1) -- Set the color of the box box:SetGravityMode(false) -- Set the gravity mode of the box -- Update and render the world as long as the window is open and the escape key is not pressed while window:Closed() == false and window:KeyDown(KEY_ESCAPE) == false do -- Press the space key to apply a force to the box if window:KeyHit(KEY_SPACE) then box:AddForce(100, 0, 0) end world:Update() -- Update the world world:Render(framebuffer) -- Render the world end I asked for C# code and it gave me this: using UltraEngine; namespace UltraEngine { class Program { static void Main(string[] args) { // Get the displays var displays = GetDisplays(); // Create a window var window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); // Create a framebuffer var framebuffer = CreateFramebuffer(window); // Create a world var world = CreateWorld(); // Create a camera var camera = CreateCamera(world); camera.SetPosition(0, 0, -2); camera.SetClearColor(0.125); // Create light var light = CreateBoxLight(world); light.SetRange(-10, 10); light.SetRotation(45, 35, 0); light.SetColor(2); // Create model var box = CreateBox(world); box.SetMass(1); box.SetColor(0, 0, 1); box.SetGravityMode(false); while (window.Closed() == false && window.KeyDown(KEY_ESCAPE) == false) { // Press the space key to apply a force if (window.KeyHit(KEY_SPACE)) { box.AddForce(100, 0, 0); } world.Update(); world.Render(framebuffer); } } } }
×
×
  • Create New...