I was always missing a feature that allows the players of my game to resize the game window. So I created a pull request that adds a “resizable” flag to desktop GLView that makes the GLFW window resizable and updates the viewport correctly when the window is resized.
Note that for the exact fit (and possibly others) design resolution policy you have to relayout and resize all nodes in a scene if you don’t want stretching to occur, or black borders to display.
One would need to implement a scene-wide relayout (or save state, restart the scene, and restore state). Ideally the scene would re-layout after every resizing movement, but a good compromise would be to have the scene stretch until the mouse is released and then re-layout.
Well, it won’t take a lot of resources to check if “Director::getInstance()->getVisibleSize()” changed. But if you really need it, I can add something like “windowSizeChanged” to ApplicationProtocol, but that will break compatibility with every cocos2d-x application out there.
Nah, don’t add anything. It’s fine. Mostly I’m just noting that changing the window size may require more work from the developer than setting the flag to true
I would like to see this feature implemented, but with addition to onResize() callback to scenes/layers so i could properly reposition all elements again. This is something that i really miss, and with this feature you could easily test your layout on different aspect ratios by just resizing a window.
Instead of adding it to ApplicationProtocol it could also be added as an event for v3.x and then in v4.x change it to either integrate with ApplicationProtocol or have an entirely new designed architecture for window management.
You could update your PR or I will create a new PR after yours is merged (or maybe before) to include something akin to this so that the developer would just have to add an event listener to any scene they wanted to capture resizing without breaking backward compatibility.
const std::string cocos2d::EVENT_WINDOW_RESIZED = "cc_event_window_resized";
void GLViewImpl::onGLFWWindowSizeFunCallback(GLFWwindow *window, int width, int height)
{
int frameWidth = width / _frameZoomFactor;
int frameHeight = height / _frameZoomFactor;
setFrameSize(frameWidth, frameHeight);
updateDesignResolutionSize();
Director::getInstance()->setViewport();
// passing this local stack variable is fine because the event listener callback is called immediately
Size frameSize(frameWidth, frameHeight);
Director::getInstance()->getEventDispatcher()->dispatchCustomEvent(EVENT_WINDOW_RESIZED, static_cast<void*>(&frameSize));
}
Edit: and could also attach the width/height, but I figure that’s easily polled from the director itself inside the custom event listener.
Edit2: updated to send new frame size along with the event.
Yes, custom event with new width and height looks good. If you need it just register for events and do as you wish, this way, current architecture wouldn’t change much
Unfortunately there’s no great way to send along data larger than a void* since you’d normally need to new it up and delete it in your handler.
We need an updated EventCustom that takes in a Value* or Ref* object that is internally retained in the same manner as ValueMap and ValueVector.
One could I suppose store the width height inside an void* by using Hight and Low bits for each. But that would require documentation so is bad idea. Could also create a struct of size void* (struct{short w; short h; } but we need a real solution, so for now passing a nullptr for the data and requiring the user to poll the data from getFrameSize() is prob best.
// something like this
void* data = (void*)((int)width & 0xffff << 16 & (int)height & 0xffff);
Unless I’m missing something. Sorry for the extra long discussion about something so minor
Ah @milos1290 reminded me that the custom event is dispatched immediately and so stack variables can be passed through and thus any data structure is appropriate for passing as the userData. There will need to be documentation noting that, for example, a Size instance is what is passed for the EVENT_WINDOW_RESIZED event.