Skip to content

Commit 58c07d8

Browse files
halx99axmol-bot
andauthored
Handling screen orientation change for all platforms (#2762)
* Handling orientation change * Gives the user a chance to re-layout scene content or reset designResolutionSize if needed * Handling ios screen orientation change * No longer need invoke applicationScreenSizeChanged in project template * Committing clang-format changes * Update copyright notice * Committing clang-format changes --------- Co-authored-by: axmol-bot <[email protected]>
1 parent 652244d commit 58c07d8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+228
-160
lines changed

axmol/platform/Application.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Copyright (c) 2010-2012 cocos2d-x.org
33
Copyright (c) 2013-2016 Chukong Technologies Inc.
44
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
5+
Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md).
56
67
https://axmol.dev/
78

axmol/platform/ApplicationBase.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,6 @@ ApplicationBase::~ApplicationBase()
3636
Director::destroyInstance();
3737
}
3838

39+
void ApplicationBase::applicationScreenSizeChanged(int newWidth, int newHeight) {}
40+
3941
} // namespace ax

axmol/platform/ApplicationBase.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,11 @@ namespace ax
3939
* @{
4040
*/
4141

42+
class RenderView;
4243
class AX_DLL ApplicationBase
4344
{
45+
friend class RenderView;
46+
4447
public:
4548
/** Since WINDOWS and ANDROID are defined as macros, we could not just use these keywords in enumeration(Platform).
4649
* Therefore, we use C# code style to define Platform enums to avoid conflicts with the definitions of system
@@ -138,6 +141,20 @@ class AX_DLL ApplicationBase
138141
* @lua NA
139142
*/
140143
virtual bool openURL(std::string_view url) = 0;
144+
145+
protected:
146+
/**
147+
* @brief Called when the application screen size changes.
148+
*
149+
* Users can override this method to listen for screen size changes,
150+
* including device rotation events. It is recommended to update the
151+
* designResolutionSize and adjust the layout of objects in the scene
152+
* accordingly when this callback is triggered.
153+
*
154+
* @param newWidth The new width of the application screen in pixels.
155+
* @param newHeight The new height of the application screen in pixels.
156+
*/
157+
virtual void applicationScreenSizeChanged(int newWidth, int newHeight);
141158
};
142159

143160
using ApplicationProtocol = ApplicationBase;

axmol/platform/RenderView.cpp

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -175,28 +175,65 @@ void RenderView::setDesignResolutionSize(float width, float height, ResolutionPo
175175
_designResolutionSize.set(width, height);
176176
_resolutionPolicy = resolutionPolicy;
177177

178-
updateDesignResolution();
178+
if (!_isResolutionUpdateLocked)
179+
updateDesignResolution();
179180
}
180181

181182
const Vec2& RenderView::getDesignResolutionSize() const
182183
{
183184
return _designResolutionSize;
184185
}
185186

186-
void RenderView::setRenderSize(float width, float height)
187+
void RenderView::updateRenderSurface(float width, float height, uint8_t updateFlag)
187188
{
188-
_renderSize.set(width, height);
189+
if (width == 0 || height == 0)
190+
return;
191+
192+
Vec2 value{width, height};
193+
194+
if (updateFlag & SurfaceUpdateFlag::WindowSizeChanged)
195+
_windowSize = value;
196+
197+
if (updateFlag & SurfaceUpdateFlag::RenderSizeChanged)
198+
{
199+
_isResolutionUpdateLocked = true;
200+
201+
_renderSize = value;
189202

190-
if (_windowSize.equals(Vec2::ZERO))
191-
_windowSize = _renderSize;
203+
// If designResolutionSize hasn't been set, default to renderSize
204+
if (_designResolutionSize.equals(Vec2::ZERO))
205+
_designResolutionSize = value;
192206

193-
// Github issue #16003 and #16485
194-
// only update the designResolution if it wasn't previously set
195-
if (_designResolutionSize.equals(Vec2::ZERO))
196-
_designResolutionSize = _renderSize;
207+
// Notify the application that the screen size has changed.
208+
// This gives the user a chance to re-layout scene content or reset designResolutionSize if needed.
209+
ax::Application::getInstance()->applicationScreenSizeChanged(width, height);
197210

198-
if (!_renderSize.equals(Vec2::ZERO))
211+
// then we update resolution and viewport
199212
updateDesignResolution();
213+
214+
_isResolutionUpdateLocked = false;
215+
}
216+
217+
// check does all updateed
218+
maybeDispatchResizeEvent(updateFlag);
219+
}
220+
221+
void RenderView::maybeDispatchResizeEvent(uint8_t updateFlag)
222+
{
223+
const bool silentUpdate = (updateFlag & SurfaceUpdateFlag::SilentUpdate) != 0;
224+
updateFlag &= ~SurfaceUpdateFlag::SilentUpdate; // Remove temporary flag
225+
226+
_surfaceUpdateFlags |= updateFlag;
227+
228+
constexpr uint8_t requiredFlags = SurfaceUpdateFlag::WindowSizeChanged | SurfaceUpdateFlag::RenderSizeChanged;
229+
230+
const bool readyToDispatch = (_surfaceUpdateFlags == requiredFlags);
231+
232+
if (readyToDispatch && !silentUpdate)
233+
{
234+
_surfaceUpdateFlags = 0;
235+
onSurfaceResized();
236+
}
200237
}
201238

202239
Rect RenderView::getVisibleRect() const
@@ -483,12 +520,13 @@ float RenderView::getScaleY() const
483520
return _viewScale.y;
484521
}
485522

486-
void RenderView::onRenderResized()
523+
void RenderView::onSurfaceResized()
487524
{
488-
AXLOGD("RenderView::onRenderResized");
525+
AXLOGD("RenderView::onSurfaceResized");
489526

490-
Director::getInstance()->resizeSwapchain(static_cast<uint32_t>(_renderSize.width),
491-
static_cast<uint32_t>(_renderSize.height));
527+
int screenWidth = static_cast<uint32_t>(_renderSize.width);
528+
int screenHeight = static_cast<uint32_t>(_renderSize.height);
529+
Director::getInstance()->resizeSwapchain(screenWidth, screenHeight);
492530

493531
#ifdef AX_ENABLE_VR
494532
if (_vrRenderer) [[unlikely]]

axmol/platform/RenderView.h

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ class AX_DLL RenderView : public Object
112112
friend class Director;
113113

114114
public:
115+
enum SurfaceUpdateFlag : uint8_t
116+
{
117+
WindowSizeChanged = 1, // Indicates that window size has changed
118+
RenderSizeChanged = 1 << 1, // Indicates that render surface size has changed
119+
SilentUpdate = 1 << 2, // Temporary flag: suppresses event dispatch for this update only.
120+
// Should be stripped before accumulating into persistent state.
121+
AllUpdates = WindowSizeChanged | RenderSizeChanged,
122+
AllUpdatesSilently = AllUpdates | SilentUpdate
123+
};
124+
115125
/**
116126
*/
117127
RenderView();
@@ -254,7 +264,8 @@ class AX_DLL RenderView : public Object
254264
* ratio, two areas of your game view will be cut. [3] SHOW_ALL Full screen with black border: if the design
255265
* resolution ratio of width to height is different from the screen resolution ratio, two black borders will be
256266
* shown.
257-
* @remark You shoud only set once
267+
* @remark For applications with a static design resolution, this method should typically be called only once during
268+
* initialization.
258269
*/
259270
virtual void setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy);
260271

@@ -456,29 +467,39 @@ class AX_DLL RenderView : public Object
456467
const std::unique_ptr<IVRRenderer>& getVR() const { return _vrRenderer; }
457468
#endif
458469

459-
protected:
460-
float transformInputX(float x) { return (x - _viewportRect.origin.x) / _viewScale.x; }
461-
float transformInputY(float y) { return (y - _viewportRect.origin.y) / _viewScale.y; }
462-
463470
/**
464-
* @brief Sets the render size (framebuffer/render target size) and updates the viewport and scaling.
471+
* @brief Updates the render surface size (framebuffer/render target) and synchronizes related view parameters.
472+
*
473+
* This method performs the following actions:
474+
* - Sets `_renderSize` to the specified dimensions;
475+
* - On mobile platforms (Android/iOS), `_windowSize` is synchronized to match `_renderSize`;
476+
* - On desktop platforms, `_windowSize` is only initialized to `_renderSize` if it hasn't been set yet;
477+
* - If `_designResolutionSize` is unset (`Vec2::ZERO`), it is initialized to `_renderSize`;
478+
* - Calls `updateDesignResolution()` to recalculate `_viewScale` and `_viewportRect` based on the current
479+
* `ResolutionPolicy`, and updates the Director's logical size and projection matrix accordingly.
480+
*
481+
* @param width The target width of the render surface. Its meaning depends on `updateFlag`:
482+
* it may represent the framebuffer width, logical window width, or design resolution width.
483+
* @param height The target height of the render surface. Its meaning depends on `updateFlag`:
484+
* it may represent the framebuffer height, logical window height, or design resolution height.
485+
* @param updateFlag Optional flags to control which parts of the view should be updated.
486+
* Defaults to `SurfaceUpdateFlag::AllUpdates`.
465487
*
466-
* This method will:
467-
* - Overwrite `_renderSize` with the given dimensions;
468-
* - If `_windowSize` has not been initialized (equals `Vec2::ZERO`), initialize it to `_renderSize`;
469-
* - If `_designResolutionSize` has not been initialized (equals `Vec2::ZERO`), initialize it to `_renderSize`;
470-
* - Call `updateDesignResolution()` to compute `_viewScale` and `_viewportRect` based on the current
471-
* `ResolutionPolicy`, and synchronize the Director's logical size and projection.
488+
* @warning This method may initialize `_windowSize` and `_designResolutionSize` on first invocation.
489+
* @note No update will occur if the given size is (0, 0).
472490
*
473-
* @param width The width of the render size.
474-
* @param height The height of the render size.
491+
* @internal This method is intended for internal use by platform-specific window or surface managers.
492+
* It should be called when the native surface size changes (e.g., orientation change, resize event).
475493
*
476-
* @warning This method has side effects: on the first call, it may initialize `_windowSize`
477-
* and `_designResolutionSize`.
478-
* @note If the given size is (0,0), no update will be performed.
479494
* @see updateDesignResolution(), setDesignResolutionSize()
480495
*/
481-
void setRenderSize(float width, float height);
496+
void updateRenderSurface(float width, float height, uint8_t updateFlag);
497+
498+
protected:
499+
float transformInputX(float x) { return (x - _viewportRect.origin.x) / _viewScale.x; }
500+
float transformInputY(float y) { return (y - _viewportRect.origin.y) / _viewScale.y; }
501+
502+
void maybeDispatchResizeEvent(uint8_t updateFlag);
482503

483504
/**
484505
* @brief Callback invoked after the RenderView size has changed and all related updates are complete.
@@ -488,7 +509,7 @@ class AX_DLL RenderView : public Object
488509
* It serves as a notification hook for any components that need to respond
489510
* to the final, settled render size.
490511
*/
491-
void onRenderResized();
512+
void onSurfaceResized();
492513

493514
void setScissorRect(float x, float y, float w, float h);
494515
const ScissorRect& getScissorRect() const;
@@ -516,6 +537,13 @@ class AX_DLL RenderView : public Object
516537
Vec2 _viewScale;
517538
ResolutionPolicy _resolutionPolicy;
518539

540+
// Flags indicating whether the window or framebuffer size was updated.
541+
// On desktop platforms, callback order is: framebufferSize => windowSize.
542+
// On WebAssembly, the order is reversed: windowSize => framebufferSize.
543+
uint8_t _surfaceUpdateFlags{0};
544+
545+
bool _isResolutionUpdateLocked{false};
546+
519547
#ifdef AX_ENABLE_VR
520548
std::unique_ptr<IVRRenderer> _vrRenderer{nullptr};
521549
#endif

axmol/platform/SAXParser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
Copyright (c) 2010 cocos2d-x.org
33
Copyright (c) 2010 Максим Аксенов
44
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
5+
Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md).
6+
7+
https://axmol.dev/
58
69
Permission is hereby granted, free of charge, to any person obtaining a copy
710
of this software and associated documentation files (the "Software"), to deal

axmol/platform/android/Application-android.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Copyright (c) 2010-2012 cocos2d-x.org
33
Copyright (c) 2013-2016 Chukong Technologies Inc.
44
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
5+
Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md).
56
67
https://axmol.dev/
78
@@ -110,8 +111,6 @@ bool Application::openURL(std::string_view url)
110111
return JniHelper::callStaticBooleanMethod(applicationHelperClassName, "openURL", url);
111112
}
112113

113-
void Application::applicationScreenSizeChanged(int newWidth, int newHeight) {}
114-
115114
} // namespace ax
116115

117116
#undef LOGD

axmol/platform/android/Application-android.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,6 @@ class AX_DLL Application : public ApplicationBase
8989
*/
9090
bool openURL(std::string_view url) override;
9191

92-
/**
93-
@brief This function will be called when the application screen size is changed.
94-
@param new width
95-
@param new height
96-
*/
97-
virtual void applicationScreenSizeChanged(int newWidth, int newHeight);
98-
9992
protected:
10093
static Application* sm_pSharedApplication;
10194
};

axmol/platform/android/RenderViewImpl-android.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ bool RenderViewImpl::initWithRect(std::string_view /*viewName*/,
9595
float /*frameZoomFactor*/,
9696
bool /*resizable*/)
9797
{
98-
setRenderSize(rect.size.width, rect.size.height);
98+
updateRenderSurface(rect.size.width, rect.size.height, SurfaceUpdateFlag::AllUpdatesSilently);
9999
return true;
100100
}
101101

axmol/platform/android/javaactivity-android.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,9 @@ JNIEXPORT jintArray JNICALL Java_dev_axmol_lib_AxmolActivity_getGLContextAttrs(J
147147

148148
JNIEXPORT void JNICALL Java_dev_axmol_lib_AxmolRenderer_nativeOnSurfaceChanged(JNIEnv*, jclass, jint w, jint h)
149149
{
150-
ax::Application::getInstance()->applicationScreenSizeChanged(w, h);
150+
auto renderView = ax::Director::getInstance()->getRenderView();
151+
if (renderView)
152+
renderView->updateRenderSurface(w, h, ax::RenderView::AllUpdates);
151153
}
152154
}
153155
#undef LOGD

0 commit comments

Comments
 (0)