Add resizing of GUIEngine (only works with some screen)

This commit is contained in:
Benau 2020-06-04 15:49:34 +08:00
parent d7695cb0a7
commit da1d41bf85
12 changed files with 139 additions and 13 deletions

View File

@ -633,6 +633,11 @@ video::IVideoModeList* CIrrDeviceSDL::getVideoModeList()
//! Sets if the window should be resizable in windowed mode.
void CIrrDeviceSDL::setResizable(bool resize)
{
#if SDL_VERSION_ATLEAST(2, 0, 5)
if (CreationParams.Fullscreen)
return;
SDL_SetWindowResizable(Window, resize ? SDL_TRUE : SDL_FALSE);
#endif
}

View File

@ -82,6 +82,7 @@ FontWithFace::~FontWithFace()
*/
void FontWithFace::init()
{
m_glyph_max_height = 0;
setDPI();
#ifndef SERVER_ONLY
if (GUIEngine::isNoGraphics())

View File

@ -20,7 +20,10 @@
#include "challenges/story_mode_timer.hpp"
#include "config/player_manager.hpp"
#include "config/user_config.hpp"
#include "font/bold_face.hpp"
#include "font/digit_face.hpp"
#include "font/font_manager.hpp"
#include "font/regular_face.hpp"
#include "graphics/2dutils.hpp"
#include "graphics/b3d_mesh_loader.hpp"
#include "graphics/camera.hpp"
@ -54,6 +57,8 @@
#include "guiengine/modaldialog.hpp"
#include "guiengine/scalable_font.hpp"
#include "guiengine/screen.hpp"
#include "guiengine/screen_keyboard.hpp"
#include "guiengine/skin.hpp"
#include "io/file_manager.hpp"
#include "items/item_manager.hpp"
#include "items/powerup_manager.hpp"
@ -1982,6 +1987,24 @@ void IrrDriver::doScreenShot()
image->drop();
} // doScreenShot
// ----------------------------------------------------------------------------
void IrrDriver::handleWindowResize()
{
if (m_actual_screen_size != m_video_driver->getCurrentRenderTargetSize())
{
// Don't update when dialog is opened
if (GUIEngine::ModalDialog::isADialogActive() ||
GUIEngine::ScreenKeyboard::isActive() ||
StateManager::get()->getGameState() != GUIEngine::MENU)
return;
m_actual_screen_size = m_video_driver->getCurrentRenderTargetSize();
UserConfigParams::m_width = m_actual_screen_size.Width;
UserConfigParams::m_height = m_actual_screen_size.Height;
resizeWindow();
}
} // handleWindowResize
// ----------------------------------------------------------------------------
/** Update, called once per frame.
* \param dt Time since last update
@ -1990,18 +2013,23 @@ void IrrDriver::doScreenShot()
*/
void IrrDriver::update(float dt, bool is_loading)
{
bool show_dialog_yes = m_resolution_changing == RES_CHANGE_YES;
bool show_dialog_warn = m_resolution_changing == RES_CHANGE_YES_WARN;
// If the resolution should be switched, do it now. This will delete the
// old device and create a new one.
if (m_resolution_changing!=RES_CHANGE_NONE)
{
applyResolutionSettings(m_resolution_changing != RES_CHANGE_SAME);
if(m_resolution_changing==RES_CHANGE_YES)
new ConfirmResolutionDialog(false);
else if(m_resolution_changing==RES_CHANGE_YES_WARN)
new ConfirmResolutionDialog(true);
m_resolution_changing = RES_CHANGE_NONE;
}
handleWindowResize();
if (show_dialog_yes)
new ConfirmResolutionDialog(false);
else if (show_dialog_warn)
new ConfirmResolutionDialog(true);
m_wind->update();
PropertyAnimator::get()->update(dt);
@ -2301,3 +2329,35 @@ void IrrDriver::resetDebugModes()
SP::sp_debug_view = false;
#endif
}
// ----------------------------------------------------------------------------
void IrrDriver::resizeWindow()
{
// Reload fonts
font_manager->getFont<BoldFace>()->init();
font_manager->getFont<DigitFace>()->init();
font_manager->getFont<RegularFace>()->init();
// Reload GUIEngine
GUIEngine::reloadForNewSize();
#ifdef ENABLE_RECORDER
ogrDestroy();
RecorderConfig cfg;
cfg.m_triple_buffering = 1;
cfg.m_record_audio = 1;
cfg.m_width = m_actual_screen_size.Width;
cfg.m_height = m_actual_screen_size.Height;
int vf = UserConfigParams::m_video_format;
cfg.m_video_format = (VideoFormat)vf;
cfg.m_audio_format = OGR_AF_VORBIS;
cfg.m_audio_bitrate = UserConfigParams::m_audio_bitrate;
cfg.m_video_bitrate = UserConfigParams::m_video_bitrate;
cfg.m_record_fps = UserConfigParams::m_record_fps;
cfg.m_record_jpg_quality = UserConfigParams::m_recorder_jpg_quality;
if (ogrInitConfig(&cfg) == 0)
{
Log::error("irr_driver",
"RecorderConfig is invalid, use the default one.");
}
#endif
}

View File

@ -194,7 +194,8 @@ private:
/** Used to visualise skeletons. */
std::vector<irr::scene::IAnimatedMeshSceneNode*> m_debug_meshes;
#endif
// ------------------------------------------------------------------------
void resizeWindow();
public:
void doScreenShot();
public:
@ -534,6 +535,8 @@ public:
// ------------------------------------------------------------------------
u32 getDefaultFramebuffer() const
{ return m_video_driver->getDefaultFramebuffer(); }
// ------------------------------------------------------------------------
void handleWindowResize();
}; // IrrDriver
extern IrrDriver *irr_driver;

View File

@ -295,7 +295,8 @@ void AbstractStateManager::resetAndSetStack(Screen* screens[])
assert(!ModalDialog::isADialogActive());
assert(!ScreenKeyboard::isActive());
if (m_game_mode != GAME) getCurrentScreen()->tearDown();
if (m_game_mode != GAME && getCurrentScreen())
getCurrentScreen()->tearDown();
m_menu_stack.clear();
for (int n=0; screens[n] != NULL; n++)
@ -311,3 +312,21 @@ void AbstractStateManager::resetAndSetStack(Screen* screens[])
onTopMostScreenChanged();
} // resetAndSetStack
// ----------------------------------------------------------------------------
void AbstractStateManager::onResize()
{
// Happens in the first resize in main.cpp
if (m_menu_stack.empty())
return;
std::vector<std::function<Screen*()> > screen_function;
for (auto& p : m_menu_stack)
screen_function.push_back(p.second->getNewScreenPointer());
clearScreenCache();
std::vector<Screen*> new_screen;
for (auto& screen : screen_function)
new_screen.push_back(screen());
new_screen.push_back(NULL);
resetAndSetStack(new_screen.data());
} // onResize

View File

@ -110,6 +110,11 @@ namespace GUIEngine
*/
void resetAndSetStack(Screen* screens[]);
/**
* \brief Called when resizing of stk window
*/
void onResize();
/**
* \brief Used in no graphics STK to enter menu screen (when server is
* idle state)

View File

@ -1176,6 +1176,18 @@ namespace GUIEngine
assert(g_skin->getReferenceCount() == 1);
} // reloadSkin
// -----------------------------------------------------------------------
void reloadForNewSize()
{
g_skin->resetBackgroundImage();
Private::font_height = g_font->getDimension( L"X" ).Height;
Private::large_font_height = g_large_font->getDimension( L"X" ).Height;
Private::small_font_height = g_small_font->getDimension( L"X" ).Height;
Private::title_font_height =
g_title_font->getDimension( L"X" ).Height;
StateManager::get()->onResize();
} // reloadForNewSize
// -----------------------------------------------------------------------
void addGUIFunctionBeforeRendering(std::function<void()> func)
{

View File

@ -257,6 +257,11 @@ namespace GUIEngine
*/
void reloadSkin();
/**
* \brief call when screen size changed
*/
void reloadForNewSize();
/**
* \brief Add gui-related function before rendering GUI (from other thread)
*/

View File

@ -102,8 +102,9 @@ protected:
/** A pointer to the Container for the Message */
SkinWidgetContainer* m_container;
/** Font used to detect if re-initialization is needed */
/** Font and screen size used to detect if re-initialization is needed */
gui::IGUIFont* m_font;
core::dimension2du m_screen_size;
public:
TextMessage(MessageQueue::MessageType mt, const core::stringw &message) :
Message(5.0f, message)
@ -135,8 +136,9 @@ public:
{
const GUIEngine::BoxRenderParams &brp =
GUIEngine::getSkin()->getBoxRenderParams(m_render_type);
const unsigned width = irr_driver->getActualScreenSize().Width;
const unsigned height = irr_driver->getActualScreenSize().Height;
m_screen_size = irr_driver->getActualScreenSize();
const unsigned width = m_screen_size.Width;
const unsigned height = m_screen_size.Height;
m_font = GUIEngine::getFont();
m_font->initGlyphLayouts(m_message, m_gls);
// Reserve space for 3 lines of text, it will occupy the circle
@ -204,7 +206,8 @@ public:
Message::draw(dt);
// This happen when GUIEngine is reset (when font size changed for
// example)
if (m_font != GUIEngine::getFont())
if (m_font != GUIEngine::getFont() ||
m_screen_size != irr_driver->getActualScreenSize())
init();
int pos_transform = 0;
if (m_container == g_container.get())

View File

@ -39,9 +39,10 @@ using namespace irr;
#include "guiengine/event_handler.hpp"
#include "guiengine/widget.hpp"
#include "input/input.hpp"
#include "utils/leak_check.hpp"
#include "utils/ptr_vector.hpp"
#include "utils/leak_check.hpp"
#include <functional>
/**
* \ingroup guiengine
@ -58,7 +59,6 @@ namespace GUIEngine
{
protected:
static SCREEN* singleton;
public:
~ScreenSingleton()
@ -71,12 +71,14 @@ namespace GUIEngine
if (singleton == NULL)
{
singleton = new SCREEN();
std::function<SCREEN*()> new_screen_function = []()
{ return ScreenSingleton::getInstance(); };
singleton->setScreenPointerFunction(new_screen_function);
GUIEngine::addScreenToList(singleton);
}
return singleton;
}
};
template <typename SCREEN> SCREEN*
ScreenSingleton<SCREEN>::singleton = nullptr;
@ -118,6 +120,8 @@ namespace GUIEngine
*/
bool m_update_in_background;
/** For runtime screen reloading without template */
std::function<Screen*()> m_screen_func;
protected:
bool m_throttle_FPS;
@ -137,6 +141,12 @@ namespace GUIEngine
PtrVector<Widget>& append_to,
irr::gui::IGUIElement* parent = NULL);
/** Save the function before GUIEngine::clearScreenCache, call it after
* to get the new screen instance pointer
*/
std::function<Screen*()> getNewScreenPointer() const { return m_screen_func; }
void setScreenPointerFunction(const std::function<Screen*()>& f) { m_screen_func = f; }
Screen(bool pause_race=true);

View File

@ -334,6 +334,7 @@ namespace GUIEngine
~Skin();
void resetBackgroundImage() { m_bg_image = NULL; }
static video::SColor getColor(const std::string &name);
void renderSections(PtrVector<Widget>* within_vector=NULL);
void drawBgImage();

View File

@ -2152,6 +2152,8 @@ int main(int argc, char *argv[])
#ifndef SERVER_ONLY
if (!GUIEngine::isNoGraphics())
{
// The screen size may change after loading
irr_driver->handleWindowResize();
// Some Android devices have only 320x240 and height >= 480 is bare
// minimum to make the GUI working as expected.
if (irr_driver->getActualScreenSize().Height < 480)