-
Posts
929 -
Joined
-
Last visited
Content Type
Blogs
Forums
Store
Gallery
Videos
Downloads
Everything posted by klepto2
-
Some fixes and expermental features added to the Scintilla (SyntaxEditor) Widget
klepto2 commented on klepto2's gallery image in Screenshots
The Airspace problem is a description for mixing different GUI technologies. In this case, the scintilla control uses natively gdi+ and its own window class and HWND. this window is rendered by gdi+ while the rest of the ui is rendered by UltraEngine. So to show the scintilla control, it must always been on top of the Ultra Engine-Widgets, which means that the z-Index or order doesn't matter and in the gif you can see that the red overlay is clipped by the scintilla control, while with the redirection to the pixmap this is no problem, because i render the pixmap natively in UltraEngine and the original Scintilla Window is hidden. The term mostly comes from WPF and WinForms: https://adityaswami89.wordpress.com/2014/02/24/airspace-problem-wpf/ -
Some fixes and expermental features added to the Scintilla (SyntaxEditor) Widget
klepto2 posted a gallery image in Screenshots
In this gif you can see a small app with 3 tabs. The first tab renderes the scintilla control normally as an extra window above the actual Ultra Engine-Window. The second tab redirects the rendering to a pixmap and uses this to display the content in UltraEngine. The second appoach supprts full integration into the UltraEngine-UI with blending and overlays while the first has many drawbacks (airspace problem, no alpha blending) the 3rd is reserved for ingame ui mode, when the ui is rendered with vulkan. Then the control is redirected to a texture and this is used. -
#define ALLOCEVENTID EventId(10001 + __COUNTER__) #define RegisterEventEnum(T) \ bool operator==(const T& t, const EventId& g) { return static_cast<EventId>(t) == g; } \ bool operator==(const EventId& g, const T& t) { return static_cast<EventId>(t) == g; } \ \ bool operator!=(const T& t, const EventId& g) { return static_cast<EventId>(t) != g; } \ bool operator!=(const EventId& g, const T& t) { return static_cast<EventId>(t) != g; } \ \ EventId& operator<<=(EventId& g, T t) { g = static_cast<EventId>(t); return g; } \ T& operator<<=(T& t, EventId g) { t = static_cast<T>(g); return t; }; \ enum CustomEvent { TEST_1 = ALLOCEVENTID, TEST_2 = ALLOCEVENTID, }; RegisterEventEnum(CustomEvent); Try this. [Edit] Forget it, it is not working. switch statements work out of the box, but functions will not work without proper casting
-
#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], WINDOW_TITLEBAR | WINDOW_RESIZABLE); //Create User Interface auto ui = CreateInterface(window); auto sz = ui->root->ClientSize(); //Create widget auto panel = CreatePanel(50, 50, sz.x - 100, sz.y - 100, ui->root); panel->SetColor(0, 0, 0, 1); panel->SetLayout(1, 1, 1, 1); auto pixmap = CreatePixmap(256, 256); pixmap->Fill(0xFF0000FF); panel->SetPixmap(pixmap); auto btnChangeColor1 = CreateButton("Change Color without fill", 50, 10, 200, 30, ui->root); auto btnChangeColor2 = CreateButton("Change Color with fill", 260, 10, 200, 30, ui->root); while (true) { const Event ev = WaitEvent(); switch (ev.id) { case EVENT_WIDGETACTION: { if (ev.source == btnChangeColor1) { int color = Rgba(Random(255), Random(255), Random(255), 255); for (int x = 0; x < pixmap->size.width; x++) for (int y = 0; y < pixmap->size.height; y++) pixmap->WritePixel(x, y, color); } else if (ev.source == btnChangeColor2) { pixmap->Fill(Rgba(Random(255), Random(255), Random(255), 255)); } panel->Paint(); break; } case EVENT_WINDOWCLOSE: return 0; break; } } return 0; } I am currently experimenting with redirecting the scintilla rendering to a pixmap and found a small bug. The pixmap is only updated, in this case on the panel, but also when using just the WidgetBlock, when you use the Fill method. any other pixel manipulation is not working when using pixmaps in the ui. I assume, that it might have to do with the underlying Bitmap object is not updated. A nice way would be to have something to mark the pixmap as dirty, as i need to use memcpy for performance reasons and then the pixmap will not know if it has chnaged or not.
-
UltraEngine Utilities
klepto2 commented on klepto2's blog entry in UltraEngine - Experiences, add-ons and other Stuff
Sorry for the delay. I have added the missing lib files. You need to add the "external/libs" folder to the link path in your project. -
UltraEngine Utilities
klepto2 commented on klepto2's blog entry in UltraEngine - Experiences, add-ons and other Stuff
I will provide them, but it will take till tomorrow. You can create them by yourself, but you need to modify the scintilla and lexical project to build as libs and modify the debug output name. -
Note: The code above converts a deviceindependent bitmap into RGBA format, so you would just need this part in the loop: data[index + 3] = char(color[WIDGETCOLOR_BACKGROUND].a * 255);
-
The pixmap and texture block uses the alpha value of the pixmap or texture itself. I do something like this to render alpha based pixmaps: auto data = _scintillaRenderTarget->pixels->Data(); for (i = 0; i < _scintillaRenderTarget->pixels->GetSize(); i += 4) { index = i; B = data[index]; G = data[index + 1]; R = data[index + 2]; data[index] = R; data[index + 1] = G; data[index + 2] = B; data[index + 3] = char(color[WIDGETCOLOR_BACKGROUND].a * 255); } but i agree, the source alpha should be mulitplied with the destination alpha in the case of widget usage.
-
if you use this: auto texture = CreateTexture(TEXTURE_2D, 2048, 2048); auto pixmap = CreatePixmap(2048, 2048); you can see the memory grow in Gb steps
-
With the above sample (at least for me) the memory keeps growing constantly and later breaks the whole OS when no memory is left.
-
#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); auto texture = CreateTexture(TEXTURE_2D, 512, 512); auto pixmap = CreatePixmap(512, 512); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { texture->SetPixels(pixmap); world->Update(); world->Render(framebuffer); } return 0; } Using Texture::SetPixels (pixmap or buffer) leads to fast rising memory.
-
Loading order of plugins leads to crash on Pixmap::Save
klepto2 replied to klepto2's topic in Bug Reports
Yes, this looks right. But I don’t know what this has to do with the save function? Shouldn’t the save function just go by the extension ? -
When the KTX2 plugin is loaded before the FreeImage plugin, the Pixmap::Save method throws an exception in the KTX2 plugin when trying to save a jpg or png file: #include "UltraEngine.h" using namespace UltraEngine; #define BUG int main(int argc, const char* argv[]) { #ifdef BUG auto plg_2 = LoadPlugin("Plugins/KTX2TextureLoader"); auto plg_1 = LoadPlugin("Plugins/FITextureLoader"); #else auto plg_1 = LoadPlugin("Plugins/FITextureLoader"); auto plg_2 = LoadPlugin("Plugins/KTX2TextureLoader"); #endif auto pixmap = CreatePixmap(256, 256); pixmap->Save("test.jpg"); pixmap->Save("test.png"); return 0; }
-
UltraEngine Utilities
klepto2 commented on klepto2's blog entry in UltraEngine - Experiences, add-ons and other Stuff
Hi, i just came back from vacation. Normally if you cloned the repo you just need to run this from cmdline in the main folder: git submodule update --init this mirror is out of date for a long time I use this one: https://github.com/missdeer/scintilla but I will remove the scintilla submodule and just try to include all relevant files in the repo. -
You might be able to use std::bind like in the createthread sample. https://www.ultraengine.com/learn/CreateThread?lang=cpp here is some stackoverflow sample which might help you: https://stackoverflow.com/questions/37636373/how-stdbind-works-with-member-functions
-
Keep in mind that Threads are managed by the operating system and depending on the OS some threads can be blocked or used by other programs. Also if you have a modern cpu you normally have also something called Hyperthreading, which means you normally you can use MaxThreads() * 2.0 in parallel, but this depends on the cpu. Normally the os threadmanagement is highly optimized, so you could push 100 or 1000 threads at once and the os will handle the execution order by itself. So don't worry so much about the actual CPU usage or amount of threads you push to the cpu.
-
Small addition: This might not be the case for the int values in this case, they are just used for simplicity. int operations are atomic, and should work, without using a lock for reading. More complex objects of course can have other behavior and may need read and write mutex or other types of memory barriers.
-
Normally, I would use a mutex for writing and reading. Sample: With only read mutex: Thread A : Writes to node x the value 1 --> Just begins writing Thread B : Locks the Mutex and reads the value 0 and unlocks the mutex --> Thread A hasn't finished writing the 1 into the memory Thread A : Finishes Thread C : Locks the Mutex and reads the value 1 --> Thread A has finished writing the 1 into the memory and unlocks the mutex The read results might get out of sync. With read and write mutex: Thread A : Locks the mutex and writes to node x the value 1 --> Just begins writing Thread B : Waits for the unlocking of the mutex Thread A : Unlocks the Mutex: --> Finished writing Thread B : Locks the mutex and Reads the value 1 from memory and unlocks the mutex afterwards Thread C : Locks the Mutex and reads the value 1 from memory and unlocks the mutex afterwards The results are always in sync. The read and write approach is of course much slower then just locking the read. You need to make the mutex locks as small as possible and maybe optimize them to only lock when it is really necessary.
-
This is how i have done it with the ShaderWatcher: void UltraEngine::Utilities::Shader::ShaderWatcher::RunPreprocess(vector<shared_ptr<ShaderFile>> files) { int time = Millisecs(); Print("Preprocessing... (" + WString(files.size()) + " Shaders)"); vector<shared_ptr<Thread>> threads; for (auto f : files) { threads.push_back(CreateThread(bind(ThreadPreprocess,_compiler, f), true)); } for (auto t : threads) t->Wait(); Print("Preprocessing finished... (" + WString(Millisecs() - time) + "ms)"); } A semaphore or mutex isn't needed here as there are no resources shared by any thread. A mutex is a good way to sync access to specific functions which are not threadsafe. eg: Print. Semaphores (technically a Mutex is just a specialized Version of a semaphore) can be used for syncing as well, but also to limit the amount of maximum parallel threads used for execution.
-
Material::SetMappingScale has no effect. Not on normal meshes or terrains. Also the documentation doesn't include this function, which in my point is an essential part of terrain painting or custom materials.
-
UltraEngine Utilities
klepto2 commented on klepto2's blog entry in UltraEngine - Experiences, add-ons and other Stuff
Some ideas which you might consider. The createcodearea should be extended to get the filepath ( for parsing includes or imports) . A way to configure the required highlighting. Instead of pass these things one by one I would create a table ( maybe Document) containing all the infos required by the codearea. -
You can try this: Shaders.zip It contains 3 configurations for a FXAA shader. Just load them as posteffects depending on your settings.
-
UltraEngine Utilities
klepto2 commented on klepto2's blog entry in UltraEngine - Experiences, add-ons and other Stuff
What errors do you get? I only got problems, when i tried to link libs which where not exported for the correct project configuration. You need to reference the debug libs or release libs depending on you current build configuration. Otherwise you only have the option to use dlls together with the small lib files. For Scintilla i do something like this in my header: #if _DEBUG #pragma comment(lib, "Scintilla_d.lib") #pragma comment(lib, "Lexilla_d.lib") #else #pragma comment(lib, "Scintilla.lib") #pragma comment(lib, "Lexilla.lib") #endif -
If i remember correctly Josh uses the FXAA-Light version of FXAA and not the real nvidia one here. In the light version you can try to alter the #define FXAA_SPAN_MAX 8.0 but that might also lead to artifacts. I am currently trying to implement the nvidia way, there you can pass more quality options to the function, but it might be a bit slower than the original one. I will come back later today to let you know what i have till then.
-
UltraEngine Utilities
klepto2 commented on klepto2's blog entry in UltraEngine - Experiences, add-ons and other Stuff
The original design of scintilla on win32 is based on dll usage, but I have decided to use the lib approach because this will make it much easier to make it crossplatform, and it is much easier to debug. Nevertheless this will not limit you to create a DLL plugin using scintilla. If I think about it it is much better than the original scintilla way, as you don’t need any 3rd party dlls and you can create a shared lib for Linux or macOS the same way on all platforms.