Jump to content

Josh

Staff
  • Posts

    23,126
  • Joined

  • Last visited

Everything posted by Josh

  1. This is so cool. If you open an asset from a zip file, when you save the file it gets saved back into the Zip package just as if it was a folder. You can do all your development in your game's final ZIP files, if you wanted to, although there may be some issues with scaling as the content gets bigger.
  2. Josh

    Ziplib bug

    Replace this code: void ZipFile::Save(ZipArchive::Ptr zipArchive, const std::string& zipPath) { ZipFile::SaveAndClose(zipArchive, zipPath); zipArchive = ZipFile::Open(zipPath); } With this: void ZipFile::Save(ZipArchive::Ptr& zipArchive, const std::string& zipPath) { ZipFile::SaveAndClose(zipArchive, zipPath); zipArchive = ZipFile::Open(zipPath); } The & makes is to the value of the shared pointer passed to the argument gets assigned to the new object.
  3. I'm using 125% scaling, so everything looks 25% bigger when I post a screenshot.
  4. Okay, I think I fixed. This is how it's supposed to appear, correct?
  5. Fixed, sorry about that.
  6. Updated 1.0.2 Fixed menu hover bug in submenus EVENT_ZOOM now stores an integer in event.data and moves 100 units for every unit that EVENT_MOUSEWHEEL changes by Fixed alphabetical sorting when TREEVIEW_SORT style is in use Fixed TreeView::GetNodeAtPoint bug Drag and drop treeviews will now automatically expand a node when you drag over them Fixed widget cursor not working
  7. I tried this and it seems to work perfectly in Ultra Engine 1.0.2.
  8. Here is a function that will check if an app is open and if it is, it will send some data to the other application: bool CheckIfOpen(shared_ptr<Window> source, const WString& appid, const WString& apptitle, shared_ptr<Buffer> data) { const int DATA_ID = 345934;// whatever... auto m_singleInstanceMutex = CreateMutexW(NULL, TRUE, appid.c_str()); if (m_singleInstanceMutex == NULL or GetLastError() == ERROR_ALREADY_EXISTS) { HWND hwnd = FindWindowW(0, apptitle.c_str()); if (hwnd and data) { COPYDATASTRUCT copydata; copydata.dwData = DATA_ID; copydata.cbData = data->GetSize(); copydata.lpData = data->Data(); LPARAM srchwnd = 0L; if (source) srchwnd = (LPARAM) source->GetHandle(); SendNotifyMessageW(hwnd, WM_COPYDATA, srchwnd, (LPARAM) &copydata); } return false; // Exit the app. For MFC, return false from InitInstance } return true; }
  9. There is a bug in the current version of the client app that will write a null-terminated when syncing text-based files. CameraControls.hpp will not open in Visual Studio, but if you open it in Notepad and remove the NULL character at the end of the file, then save, it will work.
  10. I did a lot of work on sliders and I think they are 100% working in Ultra Engine 1.0.2.
  11. Updated 1.0.2 Fixed a lot of bugs with scrollbar sliders and improved their behavior when combined with treeviews and other scrolling widgets. Widget::SetRange now accepts a third parameter for the increments value. This allows you to create a smooth scrollbar slider that doesn't just move one pixel when the user clicks on the little arrows. The mouse wheel will move three times the increments. Window::GetMouseAxis now returns a Vec3 with the smooth mouse wheel / trackpad Z value EVENT_MOUSEWHEEL works as before, but EVENT_ZOOM will provide a high-resolution Z value for smooth trackpad scolling. Use IntBitsToFloat to convert event.data to a float value, otherwise it works just the same as EVENT_MOUSEWHEEL. Menus will now emit an action event for the top-most menu and an event for themselves, so two events go out and you can choose either. Added MENU_BORDER menu style (adds a 1-pixel line across the bottom of the menu) Added TABBER_MINIMAL tabber style
  12. I put together the first editor extension using a Lua module. LuaModule.zip Your main.c file needs one important function. The name of the module is "LuaZenMode", so the DLL needs to be called "LuaZenMode.dll" and the function needs to be called "luaopen_LuaZenMode". You will get an error if you call both the script and the module the same thing, because Lua will think the script is trying to load itself. __declspec(dllexport) int luaopen_LuaZenMode(lua_State* L) { lua_pushcfunction(L, SetWindowZenMode); return 1; } In this case I am just assigning a function to the return value, but in most cases you probably want to create a table and add the function pointers to the table. Here is our one function the lib uses: static int SetWindowZenMode(lua_State* L) { HWND hwnd = (HWND)luaL_checkinteger(L, 1); int state = luaL_checkint(L, 2); if (state == 1) { SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~(WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME)); } else { SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME); } return 0; } It's okay to treat the HWND as a Lua number because even 64-bit Windows uses 32-bit window handles. https://learn.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication?redirectedfrom=MSDN Here is how I load it in my script named ZenMode.lua: local extension = {} extension.func = require "LuaZenMode" The Lua code then creates a menu divider and a new menu item: local menu = program.menu:FindChild("View", false) if menu == nil then Print("Error: ZenMode extension cannot find View menu") return end --Add divider CreateMenu("", menu) --Add menu item extension.menu = CreateMenu("Zen Mode", menu) And then it declares a function and uses that as an event listener. Note that the extension table is being passed in the extra function parameter: function extension.ProcessEvent(event, extra) Print("Calling ProcessEvent...") local hwnd = program.window:GetHandle() if extra.menu:GetState() == 0 then Print("Enabling Zen mode...") extra.menu:SetState(1) extra.windowposition = {} extra.windowsize = {} extra.windowposition.x = program.window.position.x extra.windowposition.y = program.window.position.y extra.windowsize.x = program.window.size.x extra.windowsize.y = program.window.size.y program.window:SetShape(program.window.display.position.x, program.window.display.position.y, program.window.display.size.x, program.window.display.size.y) extra.func(hwnd, 1) Print("Zen mode enabled") else Print("Disabling Zen mode...") extra.menu:SetState(0) extra.func(hwnd, 0) program.window:SetShape(extra.windowposition.x, extra.windowposition.y, extra.windowsize.x, extra.windowsize.y) Print("Zen mode disabled") end end ListenEvent(EVENT_WIDGETACTION, extension.menu, extension.ProcessEvent, extension) And now the program has new functionality added entirely by the extension.
  13. Josh

    Zen Mode

    Full-screen no distraction mode: auto hwnd = window->GetHandle(); SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) &~ (WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME)); window->SetShape(0, 0, window->display->size.x, window->display->size.y);
  14. Yeah, I did a lot of work on the scroll bars today. The next update will have a lot of small GUI fixes. I also figured out how to get things to be really pixel-perfect at every scaling factor.
  15. I would never be able to fine-tune the interface like this using a third-party GUI library.
  16. More fine-tuning of the interface...
  17. Some things can't be improved...
  18. Got rid of the viewport toolbars, added a new tabber style, and made the menu and status bars span the entire window. This takes some space away from the side panel, but it makes it easier to recognize the program layout.
  19. Maybe it would be good to have regular "entity" mode editing, how Leadwerks and 3ds Max treat models, and then have a CSG mode you switch into for brush editing. In entity mode brushes would get treated like a model does, with the position / rotation / scale widget for control
  20. Yeah, so far I find TrenchBroom to e pretty confusing. It's a bit of a guessing game what will happen when you move the mouse. But there may be some good ideas in it.
  21. And this is the code to get the start menu location to place a link / shortcut in: PIDLIST_ABSOLUTE pidlist; wchar_t path[MAX_PATH]; HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAMS, &pidlist); BOOL b = SHGetPathFromIDListW(pidlist, path); WString s = WString(path); Print(s);
×
×
  • Create New...