toggle fullscreen / window mode
christianclavet: I tried your work around. It seems to cause some bugs in Irrlicht though: When creating the second device, the video device, after having created the null device, the video device won't change the resolution when attempting to run in fullscreen mode - it just paints everythingin a window as big as the fullscreen resolution with no border at the top left screen. Either I made something terribly wrong or this is indeed unusable because Irrlicht gets confused about needing to change the screen resolution for the second device or not. (Or maybe it only works flawlessly on Windows - I'm on Linux here)
As I'm still new to IrrLicht, I can't seem to get this working correctly, or not entirely..
In my testcase I have created one window with one button in it. Clicking the button should trigger a switch between fullscreen and windowed operation.
What I'm doing in the event reciever is as follows:
The closing is caused by breaking out of the mainloop with the following condition:
However when I call device->run() directly after the loop, it returns 1, and driver is also a valid pointer (although still pointing to device->getVideoDriver() from the original device I believe...)
Full code:
In my testcase I have created one window with one button in it. Clicking the button should trigger a switch between fullscreen and windowed operation.
What I'm doing in the event reciever is as follows:
- Pointer to the device is known upon creation of the EventReciever
- Get the pointer to the GUIEnvironment of the device
- Get the drivertype and windowsize from the guiEnvironment
- call closeDevice upon the devicepointer
- call createDevice and store the result in the devicepointer
- get the pointer to the GUIEnvironment of the newly created device
- assign the pointer from the old environment to the new one.
The closing is caused by breaking out of the mainloop with the following condition:
Code: Select all
while (device->run() && driver)
Full code:
Code: Select all
#include "irrlicht/irrlicht.h"
using namespace irr;
using namespace irr::core;
using namespace irr::gui;
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
class EventReciever: public irr::IEventReceiver
{
private:
irr::IrrlichtDevice* contextDevice;
public:
EventReciever(irr::IrrlichtDevice const* device);
~EventReciever();
virtual bool OnEvent(const irr::SEvent& event);
};
int main(int argc, char* argv[])
{
//creating the render device - use OpenGL, fall back on software rendering
IrrlichtDevice* device = createDevice(
video::EDT_OPENGL, //E_DRIVER_TYPE videodriver
dimension2du(1024, 768), //dimension2d<signed int>& windowSize
32, //u32 color bits per pixel
false, //bool fullscreen
false, //bool stencilbuffer (used for dynamic shadows)
false, //bool vsync - only usefull in fullscreen
NULL //IEventReceiver* receiver
);
if (NULL == device) {
//we seem to be doomed
cout << "The application could not be launched, because the graphical" << endl
<< " interface wasn't started. OpenGL-support is required for this" << endl
<< " application to work correctly." << endl
<< endl
<< "Press Enter/Return-key to close this message...";
cin.get();
return 0;
}
//driver is needed for drawing and loading textures for example
video::IVideoDriver* driver = device->getVideoDriver();
//Environment is needed because that's where everything happens
IGUIEnvironment* env = device->getGUIEnvironment();
//disable transparent GUI
for (long i = 0; i < gui::EGDC_COUNT; ++i) {
video::SColor col = env->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);
col.setAlpha(255);
env->getSkin()->setColor((gui::EGUI_DEFAULT_COLOR)i, col);
}
//set a readable bitmap font - Arial 10
IGUIFont* font = env->getFont("irrFont_Arial_10.bmp");
if (font) {
env->getSkin()->setFont(font);
env->getSkin()->setFont(font, EGDF_WINDOW);
} else {
cout << "Failed to load the custom (readable) font (irrFont_Arial_10.bmp)" << endl;
}
//set a nice caption
device->setWindowCaption(L"FullScreen Testing");
//add stuff
env->addButton(rect<signed int>(20, 100, 600, 300), env->getRootGUIElement(), 1, L"Button", L"ButtonToolTip");
//Create the eventhandler, and link it to the device
EventReciever* er = new EventReciever(device);
device->setEventReceiver(er);
//app-loop
while (device->run() && driver) {
cout << "device->run() && driver" << endl;
if (device->isWindowActive()) {
driver->beginScene(true, false, video::SColor(255, 225, 225, 225));
env->drawAll();
driver->endScene();
}
device->yield();
}
cout << "-----" << endl << "broke out of loop:" << endl << "\tdevice->run() = " << device->run() << endl
<< "\tdriver = " << driver << endl;
delete er;
device->drop();
return 0;
}
EventReciever::EventReciever(IrrlichtDevice const* device)
{
this->contextDevice = (IrrlichtDevice*)device;
}
EventReciever::~EventReciever()
{
;//nothing
}
//return true is the event was processed
bool EventReciever::OnEvent(const irr::SEvent& event)
{
IGUIEnvironment* env = contextDevice->getGUIEnvironment();
//IGUIElement* statusbar = env->getRootGUIElement()->getElementFromId(STATUS_BAR, true);
switch (event.EventType) {
case EET_GUI_EVENT: { //button presses etc
s32 id = event.GUIEvent.Caller->getID();
switch (event.GUIEvent.EventType) {
//! A button was clicked.
case EGET_BUTTON_CLICKED: {
switch (id) {
case 1: {
if (!contextDevice->isFullscreen()) {
//change from windowed to fullscreen
video::E_DRIVER_TYPE deviceType = contextDevice->getVideoDriver()->getDriverType();
dimension2du windowSize = env->getVideoDriver()->getScreenSize();
cout << "Closing device" << endl;
contextDevice->closeDevice();
cout << "contextDevice->closeDevice() called" << endl;
//contextDevice->drop();
cout << "Creating new device" << endl;
contextDevice = createDevice(deviceType, windowSize, 32, true, false, false, this);
cout << "...created" << endl;
cout << "Requesting new environment..." << endl;
IGUIEnvironment* tempEnv = contextDevice->getGUIEnvironment();
cout << "Setting pointer to the new environment (env was " << env << " tempEnv is " << tempEnv << ")" << endl;
tempEnv = env;
cout << "done (tempEnv is now " << tempEnv << ")" << endl;
} else {
//change from fullscreen to windowed
video::E_DRIVER_TYPE deviceType = contextDevice->getVideoDriver()->getDriverType();
dimension2du windowSize = env->getVideoDriver()->getScreenSize();
contextDevice->closeDevice();
//contextDevice->drop();
contextDevice = createDevice(deviceType, windowSize, 32, false, false, false, this);
IGUIEnvironment* tempEnv = contextDevice->getGUIEnvironment();
tempEnv = env;
}
return true;
} break;
default: {
cout << "Pressed a Button";
} break;
}
} break;
//! A file has been selected in the file dialog
case EGET_FILE_SELECTED:
//! The mouse cursor hovered over a gui element.
case EGET_ELEMENT_HOVERED:
//! A menu item was selected in a (context) menu
case EGET_MENU_ITEM_SELECTED:
//! The mouse cursor left the hovered element.
case EGET_ELEMENT_LEFT:
//! A gui element has lost its focus.
/** GUIEvent.Caller is losing the focus to GUIEvent.Element.
If the event is absorbed then the focus will not be changed. */
case EGET_ELEMENT_FOCUS_LOST:
//! A gui element has got the focus.
/** If the event is absorbed then the focus will not be changed. */
case EGET_ELEMENT_FOCUSED:
//! An element would like to close.
/** Windows and context menus use this event when they would like to close,
this can be cancelled by absorbing the event. */
case EGET_ELEMENT_CLOSED:
//! A scrollbar has changed its position.
case EGET_SCROLL_BAR_CHANGED:
//! A checkbox has changed its check state.
case EGET_CHECKBOX_CHANGED:
//! A new item in a listbox was seleted.
case EGET_LISTBOX_CHANGED:
//! An item in the listbox was selected, which was already selected.
case EGET_LISTBOX_SELECTED_AGAIN:
//! A file open dialog has been closed without choosing a file
case EGET_FILE_CHOOSE_DIALOG_CANCELLED:
//! 'Yes' was clicked on a messagebox
case EGET_MESSAGEBOX_YES:
//! 'No' was clicked on a messagebox
case EGET_MESSAGEBOX_NO:
//! 'OK' was clicked on a messagebox
case EGET_MESSAGEBOX_OK:
//! 'Cancel' was clicked on a messagebox
case EGET_MESSAGEBOX_CANCEL:
//! In an editbox was pressed 'ENTER'
case EGET_EDITBOX_ENTER:
//! The tab was changed in an tab control
case EGET_TAB_CHANGED:
//! The selection in a combo box has been changed
case EGET_COMBO_BOX_CHANGED:
//! The value of a spin box has changed
case EGET_SPINBOX_CHANGED:
//! A table has changed
case EGET_TABLE_CHANGED:
case EGET_TABLE_HEADER_CHANGED:
case EGET_TABLE_SELECTED_AGAIN:
default: {
//nothing
} break;
}
} break;
case EET_LOG_TEXT_EVENT: { //consuming them doesn't send the output to the console
return true;
} break;
case EET_MOUSE_INPUT_EVENT:
case EET_KEY_INPUT_EVENT:
case EET_JOYSTICK_INPUT_EVENT:
case EET_USER_EVENT:
default: {
//nothing to do with these, just pass them on
} break;
}
return false;
}
Should I post an even more stripped version of the code as testcase? (which would be just removing empty cases, fontloading and custom coloring
actually)
Or am I correct in stating that switching devices/environments in an EventReciever is impossible? It seems even to be impossible to destroy the device withouth destroying it's environment, let alone reassigning the environment to a new device..
I have also thought of another way to achieve this, but it would involve creating a function that recreates my complete device/guiEnv. And that is a rather messy way of dealing with this issue.
actually)
Or am I correct in stating that switching devices/environments in an EventReciever is impossible? It seems even to be impossible to destroy the device withouth destroying it's environment, let alone reassigning the environment to a new device..
I have also thought of another way to achieve this, but it would involve creating a function that recreates my complete device/guiEnv. And that is a rather messy way of dealing with this issue.