ALL: Sync with ScummVM - rev. b272701834

This commit is contained in:
Bastien Bouclet 2018-03-17 14:40:39 +01:00
parent 1b9a28eb54
commit 455a409cab
113 changed files with 9871 additions and 9471 deletions

2
.gitignore vendored
View file

@ -158,7 +158,7 @@ dists/msvc*/**
#Ignore Xcode output/project files #Ignore Xcode output/project files
out/ out/
residualvm.xcodeproj /*.xcodeproj
#Ignore gmon.out created by gprof #Ignore gmon.out created by gprof
gmon.out gmon.out

View file

@ -150,6 +150,7 @@ Robert Kelsen
Ismail Khatib Ismail Khatib
Oliver Kiehl Oliver Kiehl
Martin Kiewitz Martin Kiewitz
Peter Kohaut
Pawel Kolodziejski Pawel Kolodziejski
George Kormendi George Kormendi
Mutwin Kraus Mutwin Kraus

View file

@ -92,9 +92,9 @@ MusicType MidiDriver::getMusicType(MidiDriver::DeviceHandle handle) {
return MT_MT32; return MT_MT32;
if (handle) { if (handle) {
const MusicPlugin::List p = MusicMan.getPlugins(); const PluginList p = MusicMan.getPlugins();
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { for (PluginList::const_iterator m = p.begin(); m != p.end(); m++) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) { for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) {
if (handle == d->getHandle()) if (handle == d->getHandle())
return d->getMusicType(); return d->getMusicType();
@ -107,9 +107,9 @@ MusicType MidiDriver::getMusicType(MidiDriver::DeviceHandle handle) {
Common::String MidiDriver::getDeviceString(DeviceHandle handle, DeviceStringType type) { Common::String MidiDriver::getDeviceString(DeviceHandle handle, DeviceStringType type) {
if (handle) { if (handle) {
const MusicPlugin::List p = MusicMan.getPlugins(); const PluginList p = MusicMan.getPlugins();
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { for (PluginList::const_iterator m = p.begin(); m != p.end(); m++) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) { for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) {
if (handle == d->getHandle()) { if (handle == d->getHandle()) {
if (type == kDriverName) if (type == kDriverName)
@ -226,7 +226,7 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
// If the selected driver did not match the flags setting, // If the selected driver did not match the flags setting,
// we try to determine a suitable and "optimal" music driver. // we try to determine a suitable and "optimal" music driver.
const MusicPlugin::List p = MusicMan.getPlugins(); const PluginList p = MusicMan.getPlugins();
// If only MDT_MIDI but not MDT_PREFER_MT32 or MDT_PREFER_GM is set we prefer the other devices (which will always be // If only MDT_MIDI but not MDT_PREFER_MT32 or MDT_PREFER_GM is set we prefer the other devices (which will always be
// detected since they are hard coded and cannot be disabled). // detected since they are hard coded and cannot be disabled).
bool skipMidi = !(flags & (MDT_PREFER_GM | MDT_PREFER_MT32)); bool skipMidi = !(flags & (MDT_PREFER_GM | MDT_PREFER_MT32));
@ -280,8 +280,8 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
// and there is no preferred MT32 or GM device selected either or if the detected device is unavailable we arrive here. // and there is no preferred MT32 or GM device selected either or if the detected device is unavailable we arrive here.
// If MT32 is preferred we try for the first available device with music type 'MT_MT32' (usually the mt32 emulator). // If MT32 is preferred we try for the first available device with music type 'MT_MT32' (usually the mt32 emulator).
if (flags & MDT_PREFER_MT32) { if (flags & MDT_PREFER_MT32) {
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
if (d->getMusicType() == MT_MT32) { if (d->getMusicType() == MT_MT32) {
hdl = d->getHandle(); hdl = d->getHandle();
@ -295,8 +295,8 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
// Now we default to the first available device with music type 'MT_GM' if not // Now we default to the first available device with music type 'MT_GM' if not
// MT-32 is preferred or if MT-32 is preferred but all other devices have failed. // MT-32 is preferred or if MT-32 is preferred but all other devices have failed.
if (!(flags & MDT_PREFER_MT32) || flags == (MDT_PREFER_MT32 | MDT_MIDI)) { if (!(flags & MDT_PREFER_MT32) || flags == (MDT_PREFER_MT32 | MDT_MIDI)) {
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
if (d->getMusicType() == MT_GM || d->getMusicType() == MT_GS) { if (d->getMusicType() == MT_GM || d->getMusicType() == MT_GS) {
hdl = d->getHandle(); hdl = d->getHandle();
@ -348,8 +348,8 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
tp = MT_AUTO; tp = MT_AUTO;
} }
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
if (d->getMusicType() == tp) { if (d->getMusicType() == tp) {
hdl = d->getHandle(); hdl = d->getHandle();
@ -365,33 +365,35 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
MidiDriver *MidiDriver::createMidi(MidiDriver::DeviceHandle handle) { MidiDriver *MidiDriver::createMidi(MidiDriver::DeviceHandle handle) {
MidiDriver *driver = 0; MidiDriver *driver = 0;
const MusicPlugin::List p = MusicMan.getPlugins(); const PluginList p = MusicMan.getPlugins();
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { for (PluginList::const_iterator m = p.begin(); m != p.end(); m++) {
if (getDeviceString(handle, MidiDriver::kDriverId).equals((**m)->getId())) const MusicPluginObject &musicPlugin = (*m)->get<MusicPluginObject>();
(**m)->createInstance(&driver, handle); if (getDeviceString(handle, MidiDriver::kDriverId).equals(musicPlugin.getId()))
musicPlugin.createInstance(&driver, handle);
} }
return driver; return driver;
} }
bool MidiDriver::checkDevice(MidiDriver::DeviceHandle handle) { bool MidiDriver::checkDevice(MidiDriver::DeviceHandle handle) {
const MusicPlugin::List p = MusicMan.getPlugins(); const PluginList p = MusicMan.getPlugins();
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { for (PluginList::const_iterator m = p.begin(); m != p.end(); m++) {
if (getDeviceString(handle, MidiDriver::kDriverId).equals((**m)->getId())) const MusicPluginObject &musicPlugin = (*m)->get<MusicPluginObject>();
return (**m)->checkDevice(handle); if (getDeviceString(handle, MidiDriver::kDriverId).equals(musicPlugin.getId()))
return musicPlugin.checkDevice(handle);
} }
return false; return false;
} }
MidiDriver::DeviceHandle MidiDriver::getDeviceHandle(const Common::String &identifier) { MidiDriver::DeviceHandle MidiDriver::getDeviceHandle(const Common::String &identifier) {
const MusicPlugin::List p = MusicMan.getPlugins(); const PluginList p = MusicMan.getPlugins();
if (p.begin() == p.end()) if (p.begin() == p.end())
error("MidiDriver::getDeviceHandle: Music plugins must be loaded prior to calling this method"); error("MidiDriver::getDeviceHandle: Music plugins must be loaded prior to calling this method");
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { for (PluginList::const_iterator m = p.begin(); m != p.end(); m++) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) { for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) {
// The music driver id isn't unique, but it will match // The music driver id isn't unique, but it will match
// driver's first device. This is useful when selecting // driver's first device. This is useful when selecting

View file

@ -112,11 +112,6 @@ public:
virtual Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const = 0; virtual Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const = 0;
}; };
// Music plugins
typedef PluginSubclass<MusicPluginObject> MusicPlugin;
/** /**
* Singleton class which manages all Music plugins. * Singleton class which manages all Music plugins.
*/ */
@ -125,7 +120,7 @@ private:
friend class Common::Singleton<SingletonBaseType>; friend class Common::Singleton<SingletonBaseType>;
public: public:
const MusicPlugin::List &getPlugins() const; const PluginList &getPlugins() const;
}; };
/** Convenience shortcut for accessing the Music manager. */ /** Convenience shortcut for accessing the Music manager. */

View file

@ -46,7 +46,7 @@ enum {
}; };
static inline void clampedAdd(int16& a, int b) { static inline void clampedAdd(int16& a, int b) {
register int val; int val;
#ifdef OUTPUT_UNSIGNED_AUDIO #ifdef OUTPUT_UNSIGNED_AUDIO
val = (a ^ 0x8000) + b; val = (a ^ 0x8000) + b;
#else #else

View file

@ -31,128 +31,34 @@
#include "common/util.h" #include "common/util.h"
#include "common/events.h" #include "common/events.h"
enum {
BTN_LEFT = 0,
BTN_DOWN = 1,
BTN_RIGHT = 2,
BTN_UP = 3,
BTN_START = 4,
BTN_R3 = 5,
BTN_L3 = 6,
BTN_SELECT = 7,
BTN_SQUARE = 8,
BTN_CROSS = 9,
BTN_CIRCLE = 10,
BTN_TRIANGLE = 11,
BTN_R1 = 12,
BTN_L1 = 13,
BTN_R2 = 14,
BTN_L2 = 15
};
bool PS3SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
event.kbd.flags = 0;
switch (ev.jbutton.button) {
case BTN_CROSS: // Left mouse button
event.type = Common::EVENT_LBUTTONDOWN;
processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
break;
case BTN_CIRCLE: // Right mouse button
event.type = Common::EVENT_RBUTTONDOWN;
processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
break;
case BTN_TRIANGLE: // Game menu
event.type = Common::EVENT_KEYDOWN;
event.kbd.keycode = Common::KEYCODE_F5;
event.kbd.ascii = mapKey(SDLK_F5, (SDLMod) ev.key.keysym.mod, 0);
break;
case BTN_SELECT: // Virtual keyboard
#ifdef ENABLE_VKEYBD
event.type = Common::EVENT_VIRTUAL_KEYBOARD;
#endif
break;
case BTN_SQUARE: // Escape
event.type = Common::EVENT_KEYDOWN;
event.kbd.keycode = Common::KEYCODE_ESCAPE;
event.kbd.ascii = mapKey(SDLK_ESCAPE, (SDLMod) ev.key.keysym.mod, 0);
break;
case BTN_L1: // Predictive input dialog
event.type = Common::EVENT_PREDICTIVE_DIALOG;
break;
case BTN_START: // ScummVM in game menu
event.type = Common::EVENT_MAINMENU;
break;
}
return true;
}
bool PS3SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
event.kbd.flags = 0;
switch (ev.jbutton.button) {
case BTN_CROSS: // Left mouse button
event.type = Common::EVENT_LBUTTONUP;
processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
break;
case BTN_CIRCLE: // Right mouse button
event.type = Common::EVENT_RBUTTONUP;
processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
break;
case BTN_TRIANGLE: // Game menu
event.type = Common::EVENT_KEYUP;
event.kbd.keycode = Common::KEYCODE_F5;
event.kbd.ascii = mapKey(SDLK_F5, (SDLMod) ev.key.keysym.mod, 0);
break;
case BTN_SELECT: // Virtual keyboard
// Handled in key down
break;
case BTN_SQUARE: // Escape
event.type = Common::EVENT_KEYUP;
event.kbd.keycode = Common::KEYCODE_ESCAPE;
event.kbd.ascii = mapKey(SDLK_ESCAPE, (SDLMod) ev.key.keysym.mod, 0);
break;
}
return true;
}
/** /**
* The XMB (PS3 in game menu) needs the screen buffers to be constantly flip while open. * The XMB (PS3 in game menu) needs the screen buffers to be constantly flip while open.
* This pauses execution and keeps redrawing the screen until the XMB is closed. * This pauses execution and keeps redrawing the screen until the XMB is closed.
*/ */
void PS3SdlEventSource::preprocessEvents(SDL_Event *event) { void PS3SdlEventSource::preprocessEvents(SDL_Event *event) {
if (event->type == SDL_WINDOWEVENT) { if (event->type == SDL_APP_DIDENTERBACKGROUND) {
if (event->window.event == SDL_WINDOWEVENT_LEAVE) { // XMB opened
// XMB opened if (g_engine)
if (g_engine) g_engine->pauseEngine(true);
g_engine->pauseEngine(true);
for (;;) { for (;;) {
if (!SDL_PollEvent(event)) { if (!SDL_PollEvent(event)) {
// Locking the screen forces a full redraw // Locking the screen forces a full redraw
Graphics::Surface* screen = g_system->lockScreen(); Graphics::Surface* screen = g_system->lockScreen();
if (screen) { if (screen) {
g_system->unlockScreen(); g_system->unlockScreen();
g_system->updateScreen(); g_system->updateScreen();
}
SDL_Delay(10);
continue;
}
if (event->type == SDL_QUIT)
return;
if (event->type != SDL_WINDOWEVENT)
continue;
if (event->window.event == SDL_WINDOWEVENT_ENTER) {
// XMB closed
if (g_engine)
g_engine->pauseEngine(false);
return;
} }
SDL_Delay(10);
continue;
}
if (event->type == SDL_QUIT)
return;
if (event->type == SDL_APP_DIDENTERFOREGROUND) {
// XMB closed
if (g_engine)
g_engine->pauseEngine(false);
return;
} }
} }
} }

View file

@ -31,8 +31,6 @@
class PS3SdlEventSource : public SdlEventSource { class PS3SdlEventSource : public SdlEventSource {
protected: protected:
void preprocessEvents(SDL_Event *event); void preprocessEvents(SDL_Event *event);
bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event);
bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event);
}; };
#endif /* BACKEND_EVENTS_PS3_H */ #endif /* BACKEND_EVENTS_PS3_H */

View file

@ -30,9 +30,9 @@
*/ */
class ResVmSdlEventSource : public SdlEventSource { class ResVmSdlEventSource : public SdlEventSource {
protected: protected:
bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event); bool handleJoyButtonDown(SDL_Event &ev, Common::Event &event) override;
bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event); bool handleJoyButtonUp(SDL_Event &ev, Common::Event &event) override;
bool handleJoyAxisMotion(SDL_Event &ev, Common::Event &event); bool handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) override;
}; };
#endif #endif

View file

@ -40,17 +40,8 @@
#endif #endif
#endif #endif
#ifdef JOY_ANALOG
#include "math.h"
#endif
// FIXME move joystick defines out and replace with confile file options // FIXME move joystick defines out and replace with confile file options
// we should really allow users to map any key to a joystick button // we should really allow users to map any key to a joystick button
#define JOY_DEADZONE 3200
#ifndef __SYMBIAN32__ // Symbian wants dialog joystick i.e cursor for movement/selection
#define JOY_ANALOG
#endif
// #define JOY_INVERT_Y // #define JOY_INVERT_Y
#define JOY_XAXIS 0 #define JOY_XAXIS 0
@ -87,7 +78,7 @@ static uint32 convUTF8ToUTF32(const char *src) {
SdlEventSource::SdlEventSource() SdlEventSource::SdlEventSource()
: EventSource(), _scrollLock(false), _joystick(0), _lastScreenID(0), _graphicsManager(0), _queuedFakeMouseMove(false) : EventSource(), _scrollLock(false), _joystick(0), _lastScreenID(0), _graphicsManager(0), _queuedFakeMouseMove(false)
#if SDL_VERSION_ATLEAST(2, 0, 0) #if SDL_VERSION_ATLEAST(2, 0, 0)
, _queuedFakeKeyUp(false), _fakeKeyUp() , _queuedFakeKeyUp(false), _fakeKeyUp(), _controller(nullptr)
#endif #endif
{ {
// Reset mouse state // Reset mouse state
@ -100,25 +91,18 @@ SdlEventSource::SdlEventSource()
error("Could not initialize SDL: %s", SDL_GetError()); error("Could not initialize SDL: %s", SDL_GetError());
} }
// Enable joystick
if (SDL_NumJoysticks() > joystick_num) {
_joystick = SDL_JoystickOpen(joystick_num);
debug("Using joystick: %s",
#if SDL_VERSION_ATLEAST(2, 0, 0) #if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_JoystickName(_joystick) if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == -1) {
#else error("Could not initialize SDL: %s", SDL_GetError());
SDL_JoystickName(joystick_num)
#endif
);
} else {
warning("Invalid joystick: %d", joystick_num);
} }
#endif
openJoystick(joystick_num);
} }
} }
SdlEventSource::~SdlEventSource() { SdlEventSource::~SdlEventSource() {
if (_joystick) closeJoystick();
SDL_JoystickClose(_joystick);
} }
int SdlEventSource::mapKey(SDLKey sdlKey, SDLMod mod, Uint16 unicode) { int SdlEventSource::mapKey(SDLKey sdlKey, SDLMod mod, Uint16 unicode) {
@ -241,46 +225,7 @@ bool SdlEventSource::handleKbdMouse(Common::Event &event) {
} }
} }
int16 speedFactor = 25; int16 speedFactor = computeJoystickMouseSpeedFactor();
if (g_system->hasFeature(OSystem::kFeatureKbdMouseSpeed)) {
switch (ConfMan.getInt("kbdmouse_speed")) {
// 0.25 keyboard pointer speed
case 0:
speedFactor = 100;
break;
// 0.5 speed
case 1:
speedFactor = 50;
break;
// 0.75 speed
case 2:
speedFactor = 33;
break;
// 1.0 speed
case 3:
speedFactor = 25;
break;
// 1.25 speed
case 4:
speedFactor = 20;
break;
// 1.5 speed
case 5:
speedFactor = 17;
break;
// 1.75 speed
case 6:
speedFactor = 14;
break;
// 2.0 speed
case 7:
speedFactor = 12;
break;
default:
speedFactor = 25;
}
}
// - The modifier key makes the mouse movement slower // - The modifier key makes the mouse movement slower
// - The extra factor "delay/speedFactor" ensures velocities // - The extra factor "delay/speedFactor" ensures velocities
@ -329,21 +274,59 @@ bool SdlEventSource::handleKbdMouse(Common::Event &event) {
return false; return false;
} }
int16 SdlEventSource::computeJoystickMouseSpeedFactor() const {
int16 speedFactor;
switch (ConfMan.getInt("kbdmouse_speed")) {
// 0.25 keyboard pointer speed
case 0:
speedFactor = 100;
break;
// 0.5 speed
case 1:
speedFactor = 50;
break;
// 0.75 speed
case 2:
speedFactor = 33;
break;
// 1.0 speed
case 3:
speedFactor = 25;
break;
// 1.25 speed
case 4:
speedFactor = 20;
break;
// 1.5 speed
case 5:
speedFactor = 17;
break;
// 1.75 speed
case 6:
speedFactor = 14;
break;
// 2.0 speed
case 7:
speedFactor = 12;
break;
default:
speedFactor = 25;
}
// Scale the mouse cursor speed with the display size so moving across
// the screen takes a reasonable amount of time at higher resolutions.
return speedFactor * 480 / _km.y_max;
}
void SdlEventSource::SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) { void SdlEventSource::SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) {
event.kbd.flags = 0; event.kbd.flags = 0;
#ifdef LINUPY
// Yopy has no ALT key, steal the SHIFT key
// (which isn't used much anyway)
if (mod & KMOD_SHIFT)
event.kbd.flags |= Common::KBD_ALT;
#else
if (mod & KMOD_SHIFT) if (mod & KMOD_SHIFT)
event.kbd.flags |= Common::KBD_SHIFT; event.kbd.flags |= Common::KBD_SHIFT;
if (mod & KMOD_ALT) if (mod & KMOD_ALT)
event.kbd.flags |= Common::KBD_ALT; event.kbd.flags |= Common::KBD_ALT;
#endif
if (mod & KMOD_CTRL) if (mod & KMOD_CTRL)
event.kbd.flags |= Common::KBD_CTRL; event.kbd.flags |= Common::KBD_CTRL;
if (mod & KMOD_META) if (mod & KMOD_META)
@ -554,12 +537,6 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
return handleMouseButtonDown(ev, event); return handleMouseButtonDown(ev, event);
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
return handleMouseButtonUp(ev, event); return handleMouseButtonUp(ev, event);
case SDL_JOYBUTTONDOWN:
return handleJoyButtonDown(ev, event);
case SDL_JOYBUTTONUP:
return handleJoyButtonUp(ev, event);
case SDL_JOYAXISMOTION:
return handleJoyAxisMotion(ev, event);
#if SDL_VERSION_ATLEAST(2, 0, 0) #if SDL_VERSION_ATLEAST(2, 0, 0)
case SDL_MOUSEWHEEL: { case SDL_MOUSEWHEEL: {
@ -627,6 +604,12 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
default: default:
return false; return false;
} }
case SDL_JOYDEVICEADDED:
return handleJoystickAdded(ev.jdevice);
case SDL_JOYDEVICEREMOVED:
return handleJoystickRemoved(ev.jdevice);
#else #else
case SDL_VIDEOEXPOSE: case SDL_VIDEOEXPOSE:
if (_graphicsManager) if (_graphicsManager)
@ -643,6 +626,30 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
} }
if (_joystick) {
switch (ev.type) {
case SDL_JOYBUTTONDOWN:
return handleJoyButtonDown(ev, event);
case SDL_JOYBUTTONUP:
return handleJoyButtonUp(ev, event);
case SDL_JOYAXISMOTION:
return handleJoyAxisMotion(ev, event);
}
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_controller) {
switch (ev.type) {
case SDL_CONTROLLERBUTTONDOWN:
return handleControllerButton(ev, event, false);
case SDL_CONTROLLERBUTTONUP:
return handleControllerButton(ev, event, true);
case SDL_CONTROLLERAXISMOTION:
return handleControllerAxisMotion(ev, event);
}
}
#endif
return false; return false;
} }
@ -817,6 +824,42 @@ bool SdlEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
return processMouseEvent(event, ev.button.x, ev.button.y); return processMouseEvent(event, ev.button.x, ev.button.y);
} }
void SdlEventSource::openJoystick(int joystickIndex) {
if (SDL_NumJoysticks() > joystickIndex) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (SDL_IsGameController(joystickIndex)) {
_controller = SDL_GameControllerOpen(joystickIndex);
debug("Using game controller: %s", SDL_GameControllerName(_controller));
} else
#endif
{
_joystick = SDL_JoystickOpen(joystickIndex);
debug("Using joystick: %s",
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_JoystickName(_joystick)
#else
SDL_JoystickName(joystickIndex)
#endif
);
}
} else {
warning("Invalid joystick: %d", joystickIndex);
}
}
void SdlEventSource::closeJoystick() {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (_controller) {
SDL_GameControllerClose(_controller);
_controller = nullptr;
}
#endif
if (_joystick) {
SDL_JoystickClose(_joystick);
_joystick = nullptr;
}
}
bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
if (ev.jbutton.button == JOY_BUT_LMOUSE) { if (ev.jbutton.button == JOY_BUT_LMOUSE) {
event.type = Common::EVENT_LBUTTONDOWN; event.type = Common::EVENT_LBUTTONDOWN;
@ -880,139 +923,189 @@ bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
} }
bool SdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) { bool SdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) {
if (ev.jaxis.axis == JOY_XAXIS) {
_km.joy_x = ev.jaxis.value;
return handleAxisToMouseMotion(_km.joy_x, _km.joy_y);
} else if (ev.jaxis.axis == JOY_YAXIS) {
_km.joy_y = ev.jaxis.value;
return handleAxisToMouseMotion(_km.joy_x, _km.joy_y);
}
return false;
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
bool SdlEventSource::handleJoystickAdded(const SDL_JoyDeviceEvent &device) {
debug(5, "SdlEventSource: Received joystick added event for index '%d'", device.which);
int joystick_num = ConfMan.getInt("joystick_num");
if (joystick_num == device.which) {
debug(5, "SdlEventSource: Newly added joystick with index '%d' matches 'joysticky_num', trying to use it", device.which);
closeJoystick();
openJoystick(joystick_num);
}
return false;
}
bool SdlEventSource::handleJoystickRemoved(const SDL_JoyDeviceEvent &device) {
debug(5, "SdlEventSource: Received joystick removed event for instance id '%d'", device.which);
SDL_Joystick *joystick;
if (_controller) {
joystick = SDL_GameControllerGetJoystick(_controller);
} else {
joystick = _joystick;
}
if (!joystick) {
return false;
}
if (SDL_JoystickInstanceID(joystick) == device.which) {
debug(5, "SdlEventSource: Newly removed joystick with instance id '%d' matches currently used joystick, closing current joystick", device.which);
closeJoystick();
}
return false;
}
bool SdlEventSource::handleControllerButton(const SDL_Event &ev, Common::Event &event, bool buttonUp) {
using namespace Common;
struct ControllerEventMapping {
EventType normalType;
KeyState normalKeystate;
EventType modifierType;
KeyState modifierKeystate;
};
static const ControllerEventMapping mapping[] = {
// SDL_CONTROLLER_BUTTON_A: Left mouse button
{ EVENT_LBUTTONDOWN, KeyState(), EVENT_LBUTTONDOWN, KeyState() },
// SDL_CONTROLLER_BUTTON_B: Right mouse button
{ EVENT_RBUTTONDOWN, KeyState(), EVENT_RBUTTONDOWN, KeyState() },
// SDL_CONTROLLER_BUTTON_X: Period (+R_trigger: Space)
{ EVENT_KEYDOWN, KeyState(KEYCODE_PERIOD, '.'), EVENT_KEYDOWN, KeyState(KEYCODE_SPACE, ASCII_SPACE) },
// SDL_CONTROLLER_BUTTON_Y: Escape (+R_trigger: Return)
{ EVENT_KEYDOWN, KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE), EVENT_KEYDOWN, KeyState(KEYCODE_RETURN, ASCII_RETURN) },
// SDL_CONTROLLER_BUTTON_BACK: Virtual keyboard (+R_trigger: Predictive Input Dialog)
#ifdef ENABLE_VKEYBD
{ EVENT_VIRTUAL_KEYBOARD, KeyState(), EVENT_PREDICTIVE_DIALOG, KeyState() },
#else
{ EVENT_INVALID, KeyState(), EVENT_PREDICTIVE_DIALOG, KeyState() },
#endif
// SDL_CONTROLLER_BUTTON_GUIDE: Unmapped
{ EVENT_INVALID, KeyState(), EVENT_INVALID, KeyState() },
// SDL_CONTROLLER_BUTTON_START: ScummVM in game menu
{ EVENT_MAINMENU, KeyState(), EVENT_MAINMENU, KeyState() },
// SDL_CONTROLLER_BUTTON_LEFTSTICK: Unmapped
{ EVENT_INVALID, KeyState(), EVENT_INVALID, KeyState() },
// SDL_CONTROLLER_BUTTON_RIGHTSTICK: Unmapped
{ EVENT_INVALID, KeyState(), EVENT_INVALID, KeyState() },
// SDL_CONTROLLER_BUTTON_LEFTSHOULDER: Game menu
{ EVENT_KEYDOWN, KeyState(KEYCODE_F5, ASCII_F5), EVENT_KEYDOWN, KeyState(KEYCODE_F5, ASCII_F5) },
// SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: Modifier + Shift
{ EVENT_KEYDOWN, KeyState(KEYCODE_INVALID, 0, KBD_SHIFT), EVENT_KEYDOWN, KeyState(KEYCODE_INVALID, 0, 0) },
// SDL_CONTROLLER_BUTTON_DPAD_UP: Up (+R_trigger: Up+Right)
{ EVENT_KEYDOWN, KeyState(KEYCODE_KP8, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP9, 0) },
// SDL_CONTROLLER_BUTTON_DPAD_DOWN: Down (+R_trigger: Down+Left)
{ EVENT_KEYDOWN, KeyState(KEYCODE_KP2, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP1, 0) },
// SDL_CONTROLLER_BUTTON_DPAD_LEFT: Left (+R_trigger: Up+Left)
{ EVENT_KEYDOWN, KeyState(KEYCODE_KP4, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP7, 0) },
// SDL_CONTROLLER_BUTTON_DPAD_RIGHT: Right (+R_trigger: Down+Right)
{ EVENT_KEYDOWN, KeyState(KEYCODE_KP6, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP3, 0) }
};
if (ev.cbutton.button > SDL_CONTROLLER_BUTTON_DPAD_RIGHT) {
warning("Unknown SDL controller button: '%d'", ev.cbutton.button);
return false;
}
if (!_km.modifier) {
event.type = mapping[ev.cbutton.button].normalType;
event.kbd = mapping[ev.cbutton.button].normalKeystate;
} else {
event.type = mapping[ev.cbutton.button].modifierType;
event.kbd = mapping[ev.cbutton.button].modifierKeystate;
}
// Setting the mouse speed modifier after filling the event structure above
// ensures that the shift key events are correctly handled
if (ev.cbutton.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) {
// Right shoulder is the modifier button that makes the mouse go slower
// and allows access to an extended layout while pressed.
_km.modifier = !buttonUp;
}
if (event.type == EVENT_LBUTTONDOWN || event.type == EVENT_RBUTTONDOWN) {
processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
}
if (buttonUp) {
// The event mapping table is for button down events. If we received a button up event,
// transform the event type to the corresponding up type.
if (event.type == EVENT_KEYDOWN) {
event.type = EVENT_KEYUP;
} else if (event.type == EVENT_LBUTTONDOWN) {
event.type = EVENT_LBUTTONUP;
} else if (event.type == EVENT_RBUTTONDOWN) {
event.type = EVENT_RBUTTONUP;
} else {
// Handled in key down
event.type = EVENT_INVALID;
}
}
return event.type != EVENT_INVALID;
}
bool SdlEventSource::handleControllerAxisMotion(const SDL_Event &ev, Common::Event &event) {
if (ev.caxis.axis == SDL_CONTROLLER_AXIS_LEFTX) {
_km.joy_x = ev.caxis.value;
return handleAxisToMouseMotion(_km.joy_x, _km.joy_y);
} else if (ev.caxis.axis == SDL_CONTROLLER_AXIS_LEFTY) {
_km.joy_y = ev.caxis.value;
return handleAxisToMouseMotion(_km.joy_x, _km.joy_y);
}
return false;
}
#endif
bool SdlEventSource::handleAxisToMouseMotion(int16 xAxis, int16 yAxis) {
#ifdef JOY_INVERT_Y
yAxis = -yAxis;
#endif
int axis = ev.jaxis.value;
#ifdef JOY_ANALOG
// conversion factor between keyboard mouse and joy axis value // conversion factor between keyboard mouse and joy axis value
int vel_to_axis = (1500 / MULTIPLIER); int vel_to_axis = (1500 / MULTIPLIER);
#else
if (axis > JOY_DEADZONE) {
axis -= JOY_DEADZONE;
} else if (axis < -JOY_DEADZONE) {
axis += JOY_DEADZONE;
} else
axis = 0;
#endif
if (ev.jaxis.axis == JOY_XAXIS) { // radial and scaled deadzone
#ifdef JOY_ANALOG
_km.joy_x = axis;
#else
if (axis != 0) {
_km.x_vel = (axis > 0) ? 1 * MULTIPLIER:-1 * MULTIPLIER;
_km.x_down_count = 1;
} else {
_km.x_vel = 0;
_km.x_down_count = 0;
}
#endif
} else if (ev.jaxis.axis == JOY_YAXIS) {
#ifndef JOY_INVERT_Y
axis = -axis;
#endif
#ifdef JOY_ANALOG
_km.joy_y = -axis;
#else
if (axis != 0) {
_km.y_vel = (-axis > 0) ? 1 * MULTIPLIER: -1 * MULTIPLIER;
_km.y_down_count = 1;
} else {
_km.y_vel = 0;
_km.y_down_count = 0;
}
#endif
}
#ifdef JOY_ANALOG
// radial and scaled analog joystick deadzone
float analogX = (float)_km.joy_x;
float analogY = (float)_km.joy_y;
float deadZone = (float)JOY_DEADZONE;
if (g_system->hasFeature(OSystem::kFeatureJoystickDeadzone))
deadZone = (float)ConfMan.getInt("joystick_deadzone") * 1000.0f;
float scalingFactor = 1.0f;
float magnitude = 0.0f;
magnitude = sqrt(analogX * analogX + analogY * analogY); float analogX = (float)xAxis;
float analogY = (float)yAxis;
float deadZone = (float)ConfMan.getInt("joystick_deadzone") * 1000.0f;
float magnitude = sqrt(analogX * analogX + analogY * analogY);
if (magnitude >= deadZone) { if (magnitude >= deadZone) {
_km.x_down_count = 0; _km.x_down_count = 0;
_km.y_down_count = 0; _km.y_down_count = 0;
scalingFactor = 1.0f / magnitude * (magnitude - deadZone) / (32769.0f - deadZone); float scalingFactor = 1.0f / magnitude * (magnitude - deadZone) / (32769.0f - deadZone);
_km.x_vel = (int16)(analogX * scalingFactor * 32768.0f / vel_to_axis); _km.x_vel = (int16)(analogX * scalingFactor * 32768.0f / vel_to_axis);
_km.y_vel = (int16)(analogY * scalingFactor * 32768.0f / vel_to_axis); _km.y_vel = (int16)(analogY * scalingFactor * 32768.0f / vel_to_axis);
} else { } else {
_km.x_vel = 0; _km.x_vel = 0;
_km.y_vel = 0; _km.y_vel = 0;
} }
#endif
return false; return false;
} }
bool SdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) { bool SdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) {
#ifdef LINUPY
// On Yopy map the End button to quit
if ((ev.key.keysym.sym == 293)) {
event.type = Common::EVENT_QUIT;
return true;
}
// Map menu key to f5 (scumm menu)
if (ev.key.keysym.sym == 306) {
event.type = Common::EVENT_KEYDOWN;
event.kbd.keycode = Common::KEYCODE_F5;
event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0);
return true;
}
// Map action key to action
if (ev.key.keysym.sym == 291) {
event.type = Common::EVENT_KEYDOWN;
event.kbd.keycode = Common::KEYCODE_TAB;
event.kbd.ascii = mapKey(SDLK_TAB, ev.key.keysym.mod, 0);
return true;
}
// Map OK key to skip cinematic
if (ev.key.keysym.sym == 292) {
event.type = Common::EVENT_KEYDOWN;
event.kbd.keycode = Common::KEYCODE_ESCAPE;
event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0);
return true;
}
#endif
#ifdef QTOPIA
// Quit on fn+backspace on zaurus
if (ev.key.keysym.sym == 127) {
event.type = Common::EVENT_QUIT;
return true;
}
// Map menu key (f11) to f5 (scumm menu)
if (ev.key.keysym.sym == SDLK_F11) {
event.type = Common::EVENT_KEYDOWN;
event.kbd.keycode = Common::KEYCODE_F5;
event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0);
}
// Map center (space) to tab (default action)
// I wanted to map the calendar button but the calendar comes up
else if (ev.key.keysym.sym == SDLK_SPACE) {
event.type = Common::EVENT_KEYDOWN;
event.kbd.keycode = Common::KEYCODE_TAB;
event.kbd.ascii = mapKey(SDLK_TAB, ev.key.keysym.mod, 0);
}
// Since we stole space (pause) above we'll rebind it to the tab key on the keyboard
else if (ev.key.keysym.sym == SDLK_TAB) {
event.type = Common::EVENT_KEYDOWN;
event.kbd.keycode = Common::KEYCODE_SPACE;
event.kbd.ascii = mapKey(SDLK_SPACE, ev.key.keysym.mod, 0);
} else {
// Let the events fall through if we didn't change them, this may not be the best way to
// set it up, but i'm not sure how sdl would like it if we let if fall through then redid it though.
// and yes i have an huge terminal size so i dont wrap soon enough.
event.type = Common::EVENT_KEYDOWN;
event.kbd.keycode = ev.key.keysym.sym;
event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode);
}
#endif
return false; return false;
} }

View file

@ -80,6 +80,11 @@ protected:
/** Joystick */ /** Joystick */
SDL_Joystick *_joystick; SDL_Joystick *_joystick;
#if SDL_VERSION_ATLEAST(2, 0, 0)
/** Game controller */
SDL_GameController *_controller;
#endif
/** Last screen id for checking if it was modified */ /** Last screen id for checking if it was modified */
int _lastScreenID; int _lastScreenID;
@ -88,6 +93,21 @@ protected:
*/ */
SdlGraphicsManager *_graphicsManager; SdlGraphicsManager *_graphicsManager;
/**
* Open the SDL joystick with the specified index
*
* After this function completes successfully, SDL sends events for the device.
*
* If the joystick is also a SDL game controller, open it as a controller
* so an extended button mapping can be used.
*/
void openJoystick(int joystickIndex);
/**
* Close the currently open joystick if any
*/
void closeJoystick();
/** /**
* Pre process an event before it is dispatched. * Pre process an event before it is dispatched.
*/ */
@ -117,8 +137,26 @@ protected:
virtual bool handleJoyAxisMotion(SDL_Event &ev, Common::Event &event); virtual bool handleJoyAxisMotion(SDL_Event &ev, Common::Event &event);
virtual bool handleKbdMouse(Common::Event &event); virtual bool handleKbdMouse(Common::Event &event);
#if SDL_VERSION_ATLEAST(2, 0, 0)
virtual bool handleJoystickAdded(const SDL_JoyDeviceEvent &event);
virtual bool handleJoystickRemoved(const SDL_JoyDeviceEvent &device);
virtual bool handleControllerButton(const SDL_Event &ev, Common::Event &event, bool buttonUp);
virtual bool handleControllerAxisMotion(const SDL_Event &ev, Common::Event &event);
#endif
//@} //@}
/**
* Update the virtual mouse according to a joystick or game controller axis position change
*/
virtual bool handleAxisToMouseMotion(int16 xAxis, int16 yAxis);
/**
* Compute the virtual mouse movement speed factor according to the 'kbdmouse_speed' setting.
* The speed factor is scaled with the display size.
*/
int16 computeJoystickMouseSpeedFactor() const;
/** /**
* Assigns the mouse coords to the mouse event. Furthermore notify the * Assigns the mouse coords to the mouse event. Furthermore notify the
* graphics manager about the position change. * graphics manager about the position change.

View file

@ -267,7 +267,7 @@ void RemapDialog::startRemapping(uint i) {
_remapTimeout = g_system->getMillis() + kRemapTimeoutDelay; _remapTimeout = g_system->getMillis() + kRemapTimeoutDelay;
Action *activeRemapAction = _currentActions[_topAction + i].action; Action *activeRemapAction = _currentActions[_topAction + i].action;
_keymapWidgets[i].keyButton->setLabel("..."); _keymapWidgets[i].keyButton->setLabel("...");
_keymapWidgets[i].keyButton->draw(); _keymapWidgets[i].keyButton->markAsDirty();
_keymapper->startRemappingMode(activeRemapAction); _keymapper->startRemappingMode(activeRemapAction);
} }
@ -414,8 +414,8 @@ void RemapDialog::refreshKeymap() {
_topAction = newTopAction; _topAction = newTopAction;
//_container->draw(); //_container->markAsDirty();
_scrollBar->draw(); _scrollBar->markAsDirty();
uint actionI = _topAction; uint actionI = _topAction;
@ -446,12 +446,12 @@ void RemapDialog::refreshKeymap() {
widg.keyButton->setVisible(false); widg.keyButton->setVisible(false);
widg.clearButton->setVisible(false); widg.clearButton->setVisible(false);
} }
//widg.actionText->draw(); //widg.actionText->markAsDirty();
//widg.keyButton->draw(); //widg.keyButton->markAsDirty();
} }
// need to redraw entire Dialog so that invisible // need to redraw entire Dialog so that invisible
// widgets disappear // widgets disappear
draw(); g_gui.scheduleTopDialogRedraw();
} }

View file

@ -31,6 +31,12 @@ MODULE_OBJS += \
amigaos/amigaos.o amigaos/amigaos.o
endif endif
ifdef RISCOS
MODULE_OBJS += \
riscos/riscos-main.o \
riscos/riscos.o
endif
ifdef PLAYSTATION3 ifdef PLAYSTATION3
MODULE_OBJS += \ MODULE_OBJS += \
ps3/ps3-main.o \ ps3/ps3-main.o \

View file

@ -22,7 +22,7 @@
#include "common/scummsys.h" #include "common/scummsys.h"
#if defined(POSIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(MAEMO) && !defined(WEBOS) && !defined(LINUXMOTO) && !defined(GPH_DEVICE) && !defined(GP2X) && !defined(DINGUX) && !defined(OPENPANDORA) && !defined(PLAYSTATION3) && !defined(PSP2) && !defined(ANDROIDSDL) && !defined(RISCOS) #if defined(POSIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(MAEMO) && !defined(WEBOS) && !defined(LINUXMOTO) && !defined(GPH_DEVICE) && !defined(GP2X) && !defined(DINGUX) && !defined(OPENPANDORA) && !defined(PLAYSTATION3) && !defined(PSP2) && !defined(ANDROIDSDL)
#include "backends/platform/sdl/posix/posix.h" #include "backends/platform/sdl/posix/posix.h"
#include "backends/plugins/sdl/sdl-provider.h" #include "backends/plugins/sdl/sdl-provider.h"

View file

@ -49,6 +49,11 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#ifdef HAS_POSIX_SPAWN
#include <spawn.h>
#endif
extern char **environ;
OSystem_POSIX::OSystem_POSIX(Common::String baseConfigName) OSystem_POSIX::OSystem_POSIX(Common::String baseConfigName)
: :
_baseConfigName(baseConfigName) { _baseConfigName(baseConfigName) {
@ -82,8 +87,12 @@ void OSystem_POSIX::initBackend() {
} }
bool OSystem_POSIX::hasFeature(Feature f) { bool OSystem_POSIX::hasFeature(Feature f) {
if (f == kFeatureDisplayLogFile || f == kFeatureOpenUrl) if (f == kFeatureDisplayLogFile)
return true; return true;
#ifdef HAS_POSIX_SPAWN
if (f == kFeatureOpenUrl)
return true;
#endif
return OSystem_SDL::hasFeature(f); return OSystem_SDL::hasFeature(f);
} }
@ -266,6 +275,7 @@ bool OSystem_POSIX::displayLogFile() {
} }
bool OSystem_POSIX::openUrl(const Common::String &url) { bool OSystem_POSIX::openUrl(const Common::String &url) {
#ifdef HAS_POSIX_SPAWN
// inspired by Qt's "qdesktopservices_x11.cpp" // inspired by Qt's "qdesktopservices_x11.cpp"
// try "standards" // try "standards"
@ -279,7 +289,7 @@ bool OSystem_POSIX::openUrl(const Common::String &url) {
// try desktop environment specific tools // try desktop environment specific tools
if (launchBrowser("gnome-open", url)) // gnome if (launchBrowser("gnome-open", url)) // gnome
return true; return true;
if (launchBrowser("kfmclient openURL", url)) // kde if (launchBrowser("kfmclient", url)) // kde
return true; return true;
if (launchBrowser("exo-open", url)) // xfce if (launchBrowser("exo-open", url)) // xfce
return true; return true;
@ -300,17 +310,33 @@ bool OSystem_POSIX::openUrl(const Common::String &url) {
warning("openUrl() (POSIX) failed to open URL"); warning("openUrl() (POSIX) failed to open URL");
return false; return false;
#else
return false;
#endif
} }
bool OSystem_POSIX::launchBrowser(const Common::String& client, const Common::String &url) { bool OSystem_POSIX::launchBrowser(const Common::String &client, const Common::String &url) {
// FIXME: system's input must be heavily escaped #ifdef HAS_POSIX_SPAWN
// well, when url's specified by user pid_t pid;
// it's OK now (urls are hardcoded somewhere in GUI) const char *argv[] = {
Common::String cmd = client + " " + url; client.c_str(),
return (system(cmd.c_str()) != -1); url.c_str(),
NULL,
NULL
};
if (client == "kfmclient") {
argv[2] = argv[1];
argv[1] = "openURL";
}
if (posix_spawnp(&pid, client.c_str(), NULL, NULL, const_cast<char **>(argv), environ) != 0) {
return false;
}
return (waitpid(pid, NULL, WNOHANG) != -1);
#else
return false;
#endif
} }
AudioCDManager *OSystem_POSIX::createAudioCDManager() { AudioCDManager *OSystem_POSIX::createAudioCDManager() {
#ifdef USE_LINUXCD #ifdef USE_LINUXCD
return createLinuxAudioCDManager(); return createLinuxAudioCDManager();

View file

@ -59,7 +59,6 @@ void OSystem_PS3::init() {
void OSystem_PS3::initBackend() { void OSystem_PS3::initBackend() {
ConfMan.set("joystick_num", 0); ConfMan.set("joystick_num", 0);
ConfMan.set("vkeybdpath", PREFIX "/data");
ConfMan.registerDefault("fullscreen", true); ConfMan.registerDefault("fullscreen", true);
ConfMan.registerDefault("aspect_ratio", true); ConfMan.registerDefault("aspect_ratio", true);

View file

@ -31,15 +31,8 @@
#include "common/scummsys.h" #include "common/scummsys.h"
// Remove FILE override from common/forbidden.h, and replace
// it with an alternate slightly less unfriendly override.
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_FILE) #if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_FILE)
#undef FILE #undef FILE
// Solaris has typedef __FILE FILE in several places already
#if !defined(__sun)
typedef struct { int FAKE; } FAKE_FILE;
#define FILE FAKE_FILE
#endif // (__sun)
#endif #endif
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strcasecmp) #if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_strcasecmp)

View file

@ -85,6 +85,8 @@ OSystem_SDL::OSystem_SDL()
_eventSource(0), _eventSource(0),
_window(0) { _window(0) {
ConfMan.registerDefault("kbdmouse_speed", 3);
ConfMan.registerDefault("joystick_deadzone", 3);
} }
OSystem_SDL::~OSystem_SDL() { OSystem_SDL::~OSystem_SDL() {
@ -175,15 +177,10 @@ bool OSystem_SDL::hasFeature(Feature f) {
#if SDL_VERSION_ATLEAST(2, 0, 0) #if SDL_VERSION_ATLEAST(2, 0, 0)
if (f == kFeatureClipboardSupport) return true; if (f == kFeatureClipboardSupport) return true;
#endif #endif
#ifdef JOY_ANALOG if (f == kFeatureJoystickDeadzone || f == kFeatureKbdMouseSpeed) {
if (f == kFeatureJoystickDeadzone) return true; bool joystickSupportEnabled = ConfMan.getInt("joystick_num") >= 0;
#endif return joystickSupportEnabled;
if (f == kFeatureKbdMouseSpeed) return true; }
// ResidualVM specific code:
if (f == kFeatureSideTextures)
return true;
return ModularBackend::hasFeature(f); return ModularBackend::hasFeature(f);
} }
@ -255,16 +252,6 @@ void OSystem_SDL::initBackend() {
_inited = true; _inited = true;
if (!ConfMan.hasKey("kbdmouse_speed")) {
ConfMan.registerDefault("kbdmouse_speed", 3);
ConfMan.setInt("kbdmouse_speed", 3);
}
#ifdef JOY_ANALOG
if (!ConfMan.hasKey("joystick_deadzone")) {
ConfMan.registerDefault("joystick_deadzone", 3);
ConfMan.setInt("joystick_deadzone", 3);
}
#endif
ModularBackend::initBackend(); ModularBackend::initBackend();
// We have to initialize the graphics manager before the event manager // We have to initialize the graphics manager before the event manager

View file

@ -38,21 +38,21 @@
namespace Common { namespace Common {
VirtualKeyboard::VirtualKeyboard() : _currentMode(0) { VirtualKeyboard::VirtualKeyboard() :
_currentMode(nullptr),
_fileArchive(nullptr, DisposeAfterUse::NO) {
assert(g_system); assert(g_system);
_system = g_system; _system = g_system;
_parser = new VirtualKeyboardParser(this); _parser = new VirtualKeyboardParser(this);
_kbdGUI = new VirtualKeyboardGUI(this); _kbdGUI = new VirtualKeyboardGUI(this);
_submitKeys = _loaded = false; _submitKeys = _loaded = false;
_fileArchive = 0;
} }
VirtualKeyboard::~VirtualKeyboard() { VirtualKeyboard::~VirtualKeyboard() {
deleteEvents(); deleteEvents();
delete _kbdGUI; delete _kbdGUI;
delete _parser; delete _parser;
delete _fileArchive;
} }
void VirtualKeyboard::deleteEvents() { void VirtualKeyboard::deleteEvents() {
@ -74,33 +74,31 @@ void VirtualKeyboard::reset() {
_kbdGUI->reset(); _kbdGUI->reset();
} }
bool VirtualKeyboard::openPack(const String &packName, const FSNode &node) { bool VirtualKeyboard::openPack(const String &packName, Archive *searchPath, DisposeAfterUse::Flag disposeSearchPath) {
if (node.getChild(packName + ".xml").exists()) { if (searchPath->hasFile(packName + ".xml")) {
_fileArchive = new FSDirectory(node, 1); _fileArchive.reset(searchPath, disposeSearchPath);
// uncompressed keyboard pack // uncompressed keyboard pack
if (!_parser->loadFile(node.getChild(packName + ".xml"))) { if (!_parser->loadStream(searchPath->createReadStreamForMember(packName + ".xml"))) {
delete _fileArchive; _fileArchive.reset();
_fileArchive = 0;
return false; return false;
} }
return true; return true;
} }
if (node.getChild(packName + ".zip").exists()) { if (searchPath->hasFile(packName + ".zip")) {
// compressed keyboard pack // compressed keyboard pack
_fileArchive = makeZipArchive(node.getChild(packName + ".zip")); Archive *zip = makeZipArchive(searchPath->createReadStreamForMember(packName + ".zip"));
_fileArchive.reset(zip, DisposeAfterUse::YES);
if (_fileArchive && _fileArchive->hasFile(packName + ".xml")) { if (_fileArchive && _fileArchive->hasFile(packName + ".xml")) {
if (!_parser->loadStream(_fileArchive->createReadStreamForMember(packName + ".xml"))) { if (!_parser->loadStream(_fileArchive->createReadStreamForMember(packName + ".xml"))) {
delete _fileArchive; _fileArchive.reset();
_fileArchive = 0;
return false; return false;
} }
} else { } else {
warning("Could not find %s.xml file in %s.zip virtual keyboard pack", packName.c_str(), packName.c_str()); warning("Could not find %s.xml file in %s.zip virtual keyboard pack", packName.c_str(), packName.c_str());
delete _fileArchive; _fileArchive.reset();
_fileArchive = 0;
return false; return false;
} }
@ -113,19 +111,18 @@ bool VirtualKeyboard::openPack(const String &packName, const FSNode &node) {
bool VirtualKeyboard::loadKeyboardPack(const String &packName) { bool VirtualKeyboard::loadKeyboardPack(const String &packName) {
_kbdGUI->initSize(_system->getOverlayWidth(), _system->getOverlayHeight()); _kbdGUI->initSize(_system->getOverlayWidth(), _system->getOverlayHeight());
delete _fileArchive; _fileArchive.reset();
_fileArchive = 0;
_loaded = false; _loaded = false;
bool opened = false; bool opened = false;
if (ConfMan.hasKey("vkeybdpath")) if (ConfMan.hasKey("vkeybdpath"))
opened = openPack(packName, FSNode(ConfMan.get("vkeybdpath"))); opened = openPack(packName, new FSDirectory(ConfMan.get("vkeybdpath")), DisposeAfterUse::YES);
else if (ConfMan.hasKey("extrapath")) else if (ConfMan.hasKey("extrapath"))
opened = openPack(packName, FSNode(ConfMan.get("extrapath"))); opened = openPack(packName, new FSDirectory(ConfMan.get("extrapath")), DisposeAfterUse::YES);
// fallback to the current dir // fallback to SearchMan
if (!opened) if (!opened)
opened = openPack(packName, FSNode(".")); opened = openPack(packName, &SearchMan, DisposeAfterUse::NO);
if (opened) { if (opened) {
_parser->setParseMode(VirtualKeyboardParser::kParseFull); _parser->setParseMode(VirtualKeyboardParser::kParseFull);
@ -136,8 +133,7 @@ bool VirtualKeyboard::loadKeyboardPack(const String &packName) {
} else { } else {
warning("Error parsing the virtual keyboard pack '%s'", packName.c_str()); warning("Error parsing the virtual keyboard pack '%s'", packName.c_str());
delete _fileArchive; _fileArchive.reset();
_fileArchive = 0;
} }
} else { } else {
warning("Virtual keyboard disabled due to missing pack file"); warning("Virtual keyboard disabled due to missing pack file");

View file

@ -226,7 +226,7 @@ public:
protected: protected:
OSystem *_system; OSystem *_system;
Archive *_fileArchive; DisposablePtr<Archive> _fileArchive;
friend class VirtualKeyboardGUI; friend class VirtualKeyboardGUI;
VirtualKeyboardGUI *_kbdGUI; VirtualKeyboardGUI *_kbdGUI;
@ -237,7 +237,7 @@ protected:
VirtualKeyboardParser *_parser; VirtualKeyboardParser *_parser;
void reset(); void reset();
bool openPack(const String &packName, const FSNode &node); bool openPack(const String &packName, Archive *searchPath, DisposeAfterUse::Flag disposeSearchPath);
void deleteEvents(); void deleteEvents();
bool checkModeResolutions(); bool checkModeResolutions();
void switchMode(Mode *newMode); void switchMode(Mode *newMode);

View file

@ -35,6 +35,7 @@
#include "common/config-manager.h" #include "common/config-manager.h"
#include "common/fs.h" #include "common/fs.h"
#include "common/rendermode.h" #include "common/rendermode.h"
#include "common/stack.h"
#include "common/system.h" #include "common/system.h"
#include "common/textconsole.h" #include "common/textconsole.h"
@ -70,9 +71,18 @@ static const char HELP_STRING[] =
" -z, --list-games Display list of supported games and exit\n" " -z, --list-games Display list of supported games and exit\n"
" -t, --list-targets Display list of configured targets and exit\n" " -t, --list-targets Display list of configured targets and exit\n"
" --list-saves=TARGET Display a list of saved games for the game (TARGET) specified\n" " --list-saves=TARGET Display a list of saved games for the game (TARGET) specified\n"
" -a, --add Add all games from current or specified directory.\n"
" If --game=ID is passed only the game with id ID is added. See also --detect\n"
" Use --path=PATH before -a, --add to specify a directory.\n"
" --detect Display a list of games with their ID from current or\n"
" specified directory without adding it to the config.\n"
" Use --path=PATH before --detect to specify a directory.\n"
" --game=ID In combination with --add or --detect only adds or attempts to\n"
" detect the game with id ID.\n"
" --auto-detect Display a list of games from current or specified directory\n" " --auto-detect Display a list of games from current or specified directory\n"
" and start the first one. Use --path=PATH before --auto-detect\n" " and start the first one. Use --path=PATH before --auto-detect\n"
" to specify a directory.\n" " to specify a directory.\n"
" --recursive In combination with --add or --detect recurse down all subdirectories\n"
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) #if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
" --console Enable the console window (default:enabled)\n" " --console Enable the console window (default:enabled)\n"
#endif #endif
@ -229,6 +239,7 @@ void registerDefaults() {
ConfMan.registerDefault("gui_saveload_last_pos", "0"); ConfMan.registerDefault("gui_saveload_last_pos", "0");
ConfMan.registerDefault("gui_browser_show_hidden", false); ConfMan.registerDefault("gui_browser_show_hidden", false);
ConfMan.registerDefault("game", "");
#ifdef USE_FLUIDSYNTH #ifdef USE_FLUIDSYNTH
// The settings are deliberately stored the same way as in Qsynth. The // The settings are deliberately stored the same way as in Qsynth. The
@ -356,9 +367,15 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
} else { } else {
// On MacOS X prior to 10.9 the OS is sometimes adding a -psn_X_XXXXXX argument (where X are digits) // On MacOS X prior to 10.9 the OS is sometimes adding a -psn_X_XXXXXX argument (where X are digits)
// to pass the process serial number. We need to ignore it to avoid an error. // to pass the process serial number. We need to ignore it to avoid an error.
// When using XCode it also adds -NSDocumentRevisionsDebugMode YES argument if XCode option
// "Allow debugging when using document Versions Browser" is on (which is the default).
#ifdef MACOSX #ifdef MACOSX
if (strncmp(s, "-psn_", 5) == 0) if (strncmp(s, "-psn_", 5) == 0)
continue; continue;
if (strcmp(s, "-NSDocumentRevisionsDebugMode") == 0) {
++i; // Also skip the YES that follows
continue;
}
#endif #endif
bool isLongCmd = (s[0] == '-' && s[1] == '-'); bool isLongCmd = (s[0] == '-' && s[1] == '-');
@ -375,6 +392,12 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
DO_COMMAND('z', "list-games") DO_COMMAND('z', "list-games")
END_COMMAND END_COMMAND
DO_COMMAND('a', "add")
END_COMMAND
DO_LONG_COMMAND("detect")
END_COMMAND
DO_LONG_COMMAND("auto-detect") DO_LONG_COMMAND("auto-detect")
END_COMMAND END_COMMAND
@ -557,6 +580,12 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
DO_LONG_OPTION("gui-theme") DO_LONG_OPTION("gui-theme")
END_OPTION END_OPTION
DO_LONG_OPTION("game")
END_OPTION
DO_LONG_OPTION_BOOL("recursive")
END_OPTION
DO_LONG_OPTION("themepath") DO_LONG_OPTION("themepath")
Common::FSNode path(option); Common::FSNode path(option);
if (!path.exists()) { if (!path.exists()) {
@ -610,9 +639,9 @@ static void listGames() {
printf("Game ID Full Title \n" printf("Game ID Full Title \n"
"-------------------- ------------------------------------------------------\n"); "-------------------- ------------------------------------------------------\n");
const EnginePlugin::List &plugins = EngineMan.getPlugins(); const PluginList &plugins = EngineMan.getPlugins();
for (EnginePlugin::List::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) { for (PluginList::const_iterator iter = plugins.begin(); iter != plugins.end(); ++iter) {
GameList list = (**iter)->getSupportedGames(); GameList list = (*iter)->get<MetaEngine>().getSupportedGames();
for (GameList::iterator v = list.begin(); v != list.end(); ++v) { for (GameList::iterator v = list.begin(); v != list.end(); ++v) {
printf("%-20s %s\n", v->gameid().c_str(), v->description().c_str()); printf("%-20s %s\n", v->gameid().c_str(), v->description().c_str());
} }
@ -678,7 +707,7 @@ static Common::Error listSaves(const char *target) {
gameid.toLowercase(); // Normalize it to lower case gameid.toLowercase(); // Normalize it to lower case
// Find the plugin that will handle the specified gameid // Find the plugin that will handle the specified gameid
const EnginePlugin *plugin = 0; const Plugin *plugin = nullptr;
GameDescriptor game = EngineMan.findGame(gameid, &plugin); GameDescriptor game = EngineMan.findGame(gameid, &plugin);
if (!plugin) { if (!plugin) {
@ -686,13 +715,15 @@ static Common::Error listSaves(const char *target) {
Common::String::format("target '%s', gameid '%s", target, gameid.c_str())); Common::String::format("target '%s', gameid '%s", target, gameid.c_str()));
} }
if (!(*plugin)->hasFeature(MetaEngine::kSupportsListSaves)) { const MetaEngine &metaEngine = plugin->get<MetaEngine>();
if (!metaEngine.hasFeature(MetaEngine::kSupportsListSaves)) {
// TODO: Include more info about the target (desc, engine name, ...) ??? // TODO: Include more info about the target (desc, engine name, ...) ???
return Common::Error(Common::kEnginePluginNotSupportSaves, return Common::Error(Common::kEnginePluginNotSupportSaves,
Common::String::format("target '%s', gameid '%s", target, gameid.c_str())); Common::String::format("target '%s', gameid '%s", target, gameid.c_str()));
} else { } else {
// Query the plugin for a list of saved games // Query the plugin for a list of saved games
SaveStateList saveList = (*plugin)->listSaves(target); SaveStateList saveList = metaEngine.listSaves(target);
if (saveList.size() > 0) { if (saveList.size() > 0) {
// TODO: Include more info about the target (desc, engine name, ...) ??? // TODO: Include more info about the target (desc, engine name, ...) ???
@ -730,13 +761,14 @@ static void listThemes() {
/** Lists all output devices */ /** Lists all output devices */
static void listAudioDevices() { static void listAudioDevices() {
MusicPlugin::List pluginList = MusicMan.getPlugins(); PluginList pluginList = MusicMan.getPlugins();
printf("ID Description\n"); printf("ID Description\n");
printf("------------------------------ ------------------------------------------------\n"); printf("------------------------------ ------------------------------------------------\n");
for (MusicPlugin::List::const_iterator i = pluginList.begin(), iend = pluginList.end(); i != iend; ++i) { for (PluginList::const_iterator i = pluginList.begin(), iend = pluginList.end(); i != iend; ++i) {
MusicDevices deviceList = (**i)->getDevices(); const MusicPluginObject &musicObject = (*i)->get<MusicPluginObject>();
MusicDevices deviceList = musicObject.getDevices();
for (MusicDevices::iterator j = deviceList.begin(), jend = deviceList.end(); j != jend; ++j) { for (MusicDevices::iterator j = deviceList.begin(), jend = deviceList.end(); j != jend; ++j) {
printf("%-30s %s\n", Common::String::format("\"%s\"", j->getCompleteId().c_str()).c_str(), j->getCompleteName().c_str()); printf("%-30s %s\n", Common::String::format("\"%s\"", j->getCompleteId().c_str()).c_str(), j->getCompleteName().c_str());
} }
@ -744,31 +776,132 @@ static void listAudioDevices() {
} }
/** Display all games in the given directory, or current directory if empty */ /** Display all games in the given directory, or current directory if empty */
static bool autoDetect(Common::String path) { static GameList getGameList(const Common::FSNode &dir) {
if (path.empty())
path = ".";
//Current directory
Common::FSNode dir(path);
Common::FSList files; Common::FSList files;
//Collect all files from directory //Collect all files from directory
dir.getChildren(files, Common::FSNode::kListAll); if (!dir.getChildren(files, Common::FSNode::kListAll)) {
printf("Path %s does not exist or is not a directory.\n", dir.getPath().c_str());
return GameList();
}
// detect Games
GameList candidates(EngineMan.detectGames(files)); GameList candidates(EngineMan.detectGames(files));
if (candidates.empty()) { Common::String dataPath = dir.getPath();
printf("ScummVM could not find any game in %s\n", path.c_str()); // add game data path
for (GameList::iterator v = candidates.begin(); v != candidates.end(); ++v) {
(*v)["path"] = dataPath;
}
return candidates;
}
static bool addGameToConf(const GameDescriptor &gd) {
const Common::String &domain = gd.preferredtarget();
// If game has already been added, don't add
if (ConfMan.hasGameDomain(domain))
return false; return false;
// Add the name domain
ConfMan.addGameDomain(domain);
// Copy all non-empty key/value pairs into the new domain
for (GameDescriptor::const_iterator iter = gd.begin(); iter != gd.end(); ++iter) {
if (!iter->_value.empty() && iter->_key != "preferredtarget")
ConfMan.set(iter->_key, iter->_value, domain);
} }
// Print all the candidate found // Display added game info
printf("ID Description\n"); printf("Game Added: \n GameID: %s\n Name: %s\n Language: %s\n Platform: %s\n",
printf("-------------------- ---------------------------------------------------------\n"); gd.gameid().c_str(),
for (GameList::iterator v = candidates.begin(); v != candidates.end(); ++v) { gd.description().c_str(),
printf("%-20s %s\n", v->gameid().c_str(), v->description().c_str()); Common::getLanguageDescription(gd.language()),
Common::getPlatformDescription(gd.platform()));
return true;
}
static GameList recListGames(const Common::FSNode &dir, const Common::String &gameId, bool recursive) {
GameList list = getGameList(dir);
if (recursive) {
Common::FSList files;
dir.getChildren(files, Common::FSNode::kListDirectoriesOnly);
for (Common::FSList::const_iterator file = files.begin(); file != files.end(); ++file) {
GameList rec = recListGames(*file, gameId, recursive);
for (GameList::const_iterator game = rec.begin(); game != rec.end(); ++game) {
if (gameId.empty() || game->gameid().c_str() == gameId)
list.push_back(*game);
}
}
} }
// Set the active domain to the first one to start it.
ConfMan.setActiveDomain(candidates.begin()->gameid()); return list;
}
/** Display all games in the given directory, return ID of first detected game */
static Common::String detectGames(const Common::String &path, const Common::String &gameId, bool recursive) {
bool noPath = path.empty();
//Current directory
Common::FSNode dir(path);
GameList candidates = recListGames(dir, gameId, recursive);
if (candidates.empty()) {
printf("WARNING: ResidualVM could not find any game in %s\n", dir.getPath().c_str());
if (noPath) {
printf("WARNING: Consider using --path=<path> *before* --add or --detect to specify a directory\n");
}
if (!recursive) {
printf("WARNING: Consider using --recursive *before* --add or --detect to search inside subdirectories\n");
}
return Common::String();
}
// TODO this is not especially pretty
printf("ID Description Full Path\n");
printf("-------------- ---------------------------------------------------------- ---------------------------------------------------------\n");
for (GameList::iterator v = candidates.begin(); v != candidates.end(); ++v) {
printf("%-14s %-58s %s\n", v->gameid().c_str(), v->description().c_str(), (*v)["path"].c_str());
}
return candidates[0].gameid();
}
static int recAddGames(const Common::FSNode &dir, const Common::String &game, bool recursive) {
int count = 0;
GameList list = getGameList(dir);
for (GameList::iterator v = list.begin(); v != list.end(); ++v) {
if (v->gameid().c_str() != game && !game.empty()) {
printf("Found %s, only adding %s per --game option, ignoring...\n", v->gameid().c_str(), game.c_str());
} else if (!addGameToConf(*v)) {
// TODO Is it reall the case that !addGameToConf iff already added?
printf("Found %s, but has already been added, skipping\n", v->gameid().c_str());
} else {
printf("Found %s, adding...\n", v->gameid().c_str());
count++;
}
}
if (recursive) {
Common::FSList files;
if (dir.getChildren(files, Common::FSNode::kListDirectoriesOnly)) {
for (Common::FSList::const_iterator file = files.begin(); file != files.end(); ++file) {
count += recAddGames(*file, game, recursive);
}
}
}
return count;
}
static bool addGames(const Common::String &path, const Common::String &game, bool recursive) {
//Current directory
Common::FSNode dir(path);
int added = recAddGames(dir, game, recursive);
printf("Added %d games\n", added);
if (added == 0 && !recursive) {
printf("Consider using --recursive to search inside subdirectories\n");
}
ConfMan.flushToDisk();
return true; return true;
} }
@ -998,9 +1131,30 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
printf(HELP_STRING, s_appName); printf(HELP_STRING, s_appName);
return true; return true;
} else if (command == "auto-detect") { } else if (command == "auto-detect") {
// If auto-detects succeed, we want to return false so that the game is started bool resursive = settings["recursive"] == "true";
return !autoDetect(settings["path"]); // If auto-detects fails (returns an empty ID) return true to close ScummVM.
//return true; // If we get a non-empty ID, we store it in command so that it gets processed together with the
// other command line options below.
if (resursive) {
printf("ERROR: Autodetection not supported with --recursive; are you sure you didn't want --detect?\n");
err = Common::kUnknownError;
return true;
// There is not a particularly good technical reason for this.
// From an UX point of view, however, it might get confusing.
// Consider removing this if consensus says otherwise.
} else {
command = detectGames(settings["path"], settings["game"], resursive);
if (command.empty()) {
err = Common::kNoGameDataFoundError;
return true;
}
}
} else if (command == "detect") {
detectGames(settings["path"], settings["game"], settings["recursive"] == "true");
return true;
} else if (command == "add") {
addGames(settings["path"], settings["game"], settings["recursive"] == "true");
return true;
} }
#ifdef DETECTOR_TESTING_HACK #ifdef DETECTOR_TESTING_HACK
else if (command == "test-detector") { else if (command == "test-detector") {

View file

@ -106,8 +106,8 @@ static bool launcherDialog() {
return (dlg.runModal() != -1); return (dlg.runModal() != -1);
} }
static const EnginePlugin *detectPlugin() { static const Plugin *detectPlugin() {
const EnginePlugin *plugin = 0; const Plugin *plugin = nullptr;
// Make sure the gameid is set in the config manager, and that it is lowercase. // Make sure the gameid is set in the config manager, and that it is lowercase.
Common::String gameid(ConfMan.getActiveDomainName()); Common::String gameid(ConfMan.getActiveDomainName());
@ -141,7 +141,7 @@ static const EnginePlugin *detectPlugin() {
} }
// TODO: specify the possible return values here // TODO: specify the possible return values here
static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const Common::String &edebuglevels) { static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common::String &edebuglevels) {
// Determine the game data path, for validation and error messages // Determine the game data path, for validation and error messages
Common::FSNode dir(ConfMan.get("path")); Common::FSNode dir(ConfMan.get("path"));
Common::Error err = Common::kNoError; Common::Error err = Common::kNoError;
@ -170,15 +170,16 @@ static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const
// Create the game engine // Create the game engine
if (err.getCode() == Common::kNoError) { if (err.getCode() == Common::kNoError) {
const MetaEngine &metaEngine = plugin->get<MetaEngine>();
// Set default values for all of the custom engine options // Set default values for all of the custom engine options
// Appareantly some engines query them in their constructor, thus we // Appareantly some engines query them in their constructor, thus we
// need to set this up before instance creation. // need to set this up before instance creation.
const ExtraGuiOptions engineOptions = (*plugin)->getExtraGuiOptions(Common::String()); const ExtraGuiOptions engineOptions = metaEngine.getExtraGuiOptions(Common::String());
for (uint i = 0; i < engineOptions.size(); i++) { for (uint i = 0; i < engineOptions.size(); i++) {
ConfMan.registerDefault(engineOptions[i].configOption, engineOptions[i].defaultState); ConfMan.registerDefault(engineOptions[i].configOption, engineOptions[i].defaultState);
} }
err = (*plugin)->createInstance(&system, &engine); err = metaEngine.createInstance(&system, &engine);
} }
// Check for errors // Check for errors
@ -506,7 +507,7 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
// cleanly, so this is now enabled to encourage people to fix bits :) // cleanly, so this is now enabled to encourage people to fix bits :)
while (0 != ConfMan.getActiveDomain()) { while (0 != ConfMan.getActiveDomain()) {
// Try to find a plugin which feels responsible for the specified game. // Try to find a plugin which feels responsible for the specified game.
const EnginePlugin *plugin = detectPlugin(); const Plugin *plugin = detectPlugin();
if (plugin) { if (plugin) {
// Unload all plugins not needed for this game, // Unload all plugins not needed for this game,
// to save memory // to save memory

View file

@ -458,7 +458,7 @@ DECLARE_SINGLETON(EngineManager);
* For the uncached version, we first try to find the plugin using the gameId * For the uncached version, we first try to find the plugin using the gameId
* and only if we can't find it there, we loop through the plugins. * and only if we can't find it there, we loop through the plugins.
**/ **/
GameDescriptor EngineManager::findGame(const Common::String &gameName, const EnginePlugin **plugin) const { GameDescriptor EngineManager::findGame(const Common::String &gameName, const Plugin **plugin) const {
GameDescriptor result; GameDescriptor result;
// First look for the game using the plugins in memory. This is critical // First look for the game using the plugins in memory. This is critical
@ -494,18 +494,18 @@ GameDescriptor EngineManager::findGame(const Common::String &gameName, const Eng
/** /**
* Find the game within the plugins loaded in memory * Find the game within the plugins loaded in memory
**/ **/
GameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String &gameName, const EnginePlugin **plugin) const { GameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String &gameName, const Plugin **plugin) const {
// Find the GameDescriptor for this target // Find the GameDescriptor for this target
const EnginePlugin::List &plugins = getPlugins(); const PluginList &plugins = getPlugins();
GameDescriptor result; GameDescriptor result;
if (plugin) if (plugin)
*plugin = 0; *plugin = 0;
EnginePlugin::List::const_iterator iter; PluginList::const_iterator iter;
for (iter = plugins.begin(); iter != plugins.end(); ++iter) { for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
result = (**iter)->findGame(gameName.c_str()); result = (*iter)->get<MetaEngine>().findGame(gameName.c_str());
if (!result.gameid().empty()) { if (!result.gameid().empty()) {
if (plugin) if (plugin)
*plugin = *iter; *plugin = *iter;
@ -517,22 +517,22 @@ GameDescriptor EngineManager::findGameInLoadedPlugins(const Common::String &game
GameList EngineManager::detectGames(const Common::FSList &fslist) const { GameList EngineManager::detectGames(const Common::FSList &fslist) const {
GameList candidates; GameList candidates;
EnginePlugin::List plugins; PluginList plugins;
EnginePlugin::List::const_iterator iter; PluginList::const_iterator iter;
PluginManager::instance().loadFirstPlugin(); PluginManager::instance().loadFirstPlugin();
do { do {
plugins = getPlugins(); plugins = getPlugins();
// Iterate over all known games and for each check if it might be // Iterate over all known games and for each check if it might be
// the game in the presented directory. // the game in the presented directory.
for (iter = plugins.begin(); iter != plugins.end(); ++iter) { for (iter = plugins.begin(); iter != plugins.end(); ++iter) {
candidates.push_back((**iter)->detectGames(fslist)); candidates.push_back((*iter)->get<MetaEngine>().detectGames(fslist));
} }
} while (PluginManager::instance().loadNextPlugin()); } while (PluginManager::instance().loadNextPlugin());
return candidates; return candidates;
} }
const EnginePlugin::List &EngineManager::getPlugins() const { const PluginList &EngineManager::getPlugins() const {
return (const EnginePlugin::List &)PluginManager::instance().getPlugins(PLUGIN_TYPE_ENGINE); return PluginManager::instance().getPlugins(PLUGIN_TYPE_ENGINE);
} }
@ -544,6 +544,6 @@ namespace Common {
DECLARE_SINGLETON(MusicManager); DECLARE_SINGLETON(MusicManager);
} }
const MusicPlugin::List &MusicManager::getPlugins() const { const PluginList &MusicManager::getPlugins() const {
return (const MusicPlugin::List &)PluginManager::instance().getPlugins(PLUGIN_TYPE_MUSIC); return PluginManager::instance().getPlugins(PLUGIN_TYPE_MUSIC);
} }

View file

@ -190,6 +190,15 @@ public:
PluginType getType() const; PluginType getType() const;
const char *getName() const; const char *getName() const;
template <class T>
T &get() const {
T *pluginObject = dynamic_cast<T *>(_pluginObject);
if (!pluginObject) {
error("Invalid cast of plugin %s", getName());
}
return *pluginObject;
}
/** /**
* The getFileName() function gets the name of the plugin file for those * The getFileName() function gets the name of the plugin file for those
* plugins that have files (ie. not static). It doesn't require the plugin * plugins that have files (ie. not static). It doesn't require the plugin
@ -201,25 +210,6 @@ public:
/** List of Plugin instances. */ /** List of Plugin instances. */
typedef Common::Array<Plugin *> PluginList; typedef Common::Array<Plugin *> PluginList;
/**
* Convenience template to make it easier defining normal Plugin
* subclasses. Namely, the PluginSubclass will manage PluginObjects
* of a type specified via the PO_t template parameter.
*/
template<class PO_t>
class PluginSubclass : public Plugin {
public:
PO_t &operator*() const {
return *(PO_t *)_pluginObject;
}
PO_t *operator->() const {
return (PO_t *)_pluginObject;
}
typedef Common::Array<PluginSubclass *> List;
};
/** /**
* Abstract base class for Plugin factories. Subclasses of this * Abstract base class for Plugin factories. Subclasses of this
* are responsible for creating plugin objects, e.g. by loading * are responsible for creating plugin objects, e.g. by loading

View file

@ -98,7 +98,7 @@ static const char LogTable256[256] = {
}; };
inline int intLog2(uint32 v) { inline int intLog2(uint32 v) {
register uint32 t, tt; uint32 t, tt;
if ((tt = v >> 16)) if ((tt = v >> 16))
return (t = tt >> 8) ? 24 + LogTable256[t] : 16 + LogTable256[tt]; return (t = tt >> 8) ? 24 + LogTable256[t] : 16 + LogTable256[tt];

View file

@ -301,6 +301,22 @@ public:
*/ */
bool operator_bool() const { return _pointer != nullptr; } bool operator_bool() const { return _pointer != nullptr; }
/**
* Resets the pointer with the new value. Old object will be destroyed
*/
void reset(PointerType o, DisposeAfterUse::Flag dispose) {
if (_dispose) D()(_pointer);
_pointer = o;
_dispose = dispose;
}
/**
* Clears the pointer. Old object will be destroyed
*/
void reset() {
reset(nullptr, DisposeAfterUse::NO);
}
/** /**
* Returns the plain pointer value. * Returns the plain pointer value.
* *

View file

@ -28,6 +28,7 @@
namespace Common { namespace Common {
#define VER(x) Common::Serializer::Version(x)
#define SYNC_AS(SUFFIX,TYPE,SIZE) \ #define SYNC_AS(SUFFIX,TYPE,SIZE) \
template<typename T> \ template<typename T> \
@ -43,6 +44,11 @@ namespace Common {
_bytesSynced += SIZE; \ _bytesSynced += SIZE; \
} }
#define SYNC_PRIMITIVE(suffix) \
template <typename T> \
static inline void suffix(Serializer &s, T &value) { \
s.syncAs##suffix(value); \
}
/** /**
* This class allows syncing / serializing data (primarily game savestates) * This class allows syncing / serializing data (primarily game savestates)
@ -67,6 +73,17 @@ public:
typedef uint32 Version; typedef uint32 Version;
static const Version kLastVersion = 0xFFFFFFFF; static const Version kLastVersion = 0xFFFFFFFF;
SYNC_PRIMITIVE(Uint32LE)
SYNC_PRIMITIVE(Uint32BE)
SYNC_PRIMITIVE(Sint32LE)
SYNC_PRIMITIVE(Sint32BE)
SYNC_PRIMITIVE(Uint16LE)
SYNC_PRIMITIVE(Uint16BE)
SYNC_PRIMITIVE(Sint16LE)
SYNC_PRIMITIVE(Sint16BE)
SYNC_PRIMITIVE(Byte)
SYNC_PRIMITIVE(SByte)
protected: protected:
SeekableReadStream *_loadStream; SeekableReadStream *_loadStream;
WriteStream *_saveStream; WriteStream *_saveStream;
@ -94,6 +111,7 @@ public:
// in the line "syncAsUint32LE(_version);" of // in the line "syncAsUint32LE(_version);" of
// "bool syncVersion(Version currentVersion)". // "bool syncVersion(Version currentVersion)".
SYNC_AS(Byte, byte, 1) SYNC_AS(Byte, byte, 1)
SYNC_AS(SByte, int8, 1)
SYNC_AS(Uint16LE, uint16, 2) SYNC_AS(Uint16LE, uint16, 2)
SYNC_AS(Uint16BE, uint16, 2) SYNC_AS(Uint16BE, uint16, 2)
@ -237,8 +255,18 @@ public:
} }
} }
template <typename T>
void syncArray(T *arr, size_t entries, void (*serializer)(Serializer &, T &), Version minVersion = 0, Version maxVersion = kLastVersion) {
if (_version < minVersion || _version > maxVersion)
return;
for (size_t i = 0; i < entries; ++i) {
serializer(*this, arr[i]);
}
}
}; };
#undef SYNC_PRIMITIVE
#undef SYNC_AS #undef SYNC_AS

51
configure vendored
View file

@ -174,6 +174,7 @@ _build_scalers=no
_build_hq_scalers=no _build_hq_scalers=no
_enable_prof=no _enable_prof=no
_global_constructors=no _global_constructors=no
_no_undefined_var_template=no
_bink=yes _bink=yes
_cloud=no _cloud=no
# Default vkeybd/keymapper/eventrec options # Default vkeybd/keymapper/eventrec options
@ -220,6 +221,7 @@ _tainted_build=no
# The following variables are automatically detected, and should not # The following variables are automatically detected, and should not
# be modified otherwise. Consider them read-only. # be modified otherwise. Consider them read-only.
_posix=no _posix=no
_has_posix_spawn=no
_endian=unknown _endian=unknown
_need_memalign=yes _need_memalign=yes
_have_x86=no _have_x86=no
@ -497,8 +499,8 @@ find_libcurlconfig() {
# #
get_system_exe_extension() { get_system_exe_extension() {
case $1 in case $1 in
arm-riscos) riscos)
_exeext=",ff8" _exeext=",e1f"
;; ;;
3ds | dreamcast | ds | gamecube | n64 | ps2 | psp | wii) 3ds | dreamcast | ds | gamecube | n64 | ps2 | psp | wii)
_exeext=".elf" _exeext=".elf"
@ -935,6 +937,7 @@ Game engines:
The values of <engine name> for these options are as follows: The values of <engine name> for these options are as follows:
$engines_help $engines_help
Optional Features: Optional Features:
--enable-static build a static binary instead of using shared objects
--enable-c++11 build as C++11 if the compiler allows that --enable-c++11 build as C++11 if the compiler allows that
--disable-debug disable building with debugging symbols --disable-debug disable building with debugging symbols
--enable-Werror treat warnings as errors --enable-Werror treat warnings as errors
@ -1076,6 +1079,7 @@ for ac_option in $@; do
# --disable-16bit) _16bit=no ;; #ResidualVM: not supported # --disable-16bit) _16bit=no ;; #ResidualVM: not supported
# --enable-highres) _highres=yes ;; #ResidualVM: not supported # --enable-highres) _highres=yes ;; #ResidualVM: not supported
# --disable-highres) _highres=no ;; #ResidualVM: not supported # --disable-highres) _highres=no ;; #ResidualVM: not supported
--enable-static) _static_build=yes ;;
--disable-savegame-timestamp) _savegame_timestamp=no ;; --disable-savegame-timestamp) _savegame_timestamp=no ;;
# --disable-scalers) _build_scalers=no ;; #ResidualVM: not supported # --disable-scalers) _build_scalers=no ;; #ResidualVM: not supported
# --disable-hq-scalers) _build_hq_scalers=no ;; #ResidualVM: not supported # --disable-hq-scalers) _build_hq_scalers=no ;; #ResidualVM: not supported
@ -1435,9 +1439,12 @@ androidsdl-x86_64)
_host_cpu=x86_64 _host_cpu=x86_64
_host_alias=x86_64-linux-android _host_alias=x86_64-linux-android
;; ;;
arm-riscos) arm-*riscos)
_host_os=riscos _host_os=riscos
_host_cpu=arm _host_cpu=arm
datarootdir='/\<ScummVM\$$Dir\>'
datadir='${datarootdir}/data'
docdir='${datarootdir}/docs'
;; ;;
raspberrypi) raspberrypi)
_host_os=linux _host_os=linux
@ -1497,14 +1504,10 @@ ios7)
_host_cpu=arm _host_cpu=arm
_host_alias=arm-apple-darwin11 _host_alias=arm-apple-darwin11
;; ;;
linupy)
_host_os=linux
_host_cpu=arm
;;
maemo) maemo)
_host_os=maemo _host_os=maemo
_host_cpu=arm _host_cpu=arm
_host_alias=arm-linux _host_alias=arm-none-linux-gnueabi
# The prefix is always the same on Maemo so we hardcode the default # The prefix is always the same on Maemo so we hardcode the default
# here. It is still possible to define a custom prefix which is # here. It is still possible to define a custom prefix which is
@ -2663,7 +2666,7 @@ case $_host_os in
_libcurlpath="$PS3DEV/portlibs/ppu:$PS3DEV/portlibs/ppu/bin" _libcurlpath="$PS3DEV/portlibs/ppu:$PS3DEV/portlibs/ppu/bin"
append_var DEFINES "-DPLAYSTATION3" append_var DEFINES "-DPLAYSTATION3"
append_var CXXFLAGS "-mcpu=cell -mminimal-toc -I$PSL1GHT/ppu/include -I$PS3DEV/portlibs/ppu/include" append_var CXXFLAGS "-mcpu=cell -mno-fp-in-toc -I$PSL1GHT/ppu/include -I$PS3DEV/portlibs/ppu/include"
append_var LDFLAGS "-L$PSL1GHT/ppu/lib -L$PS3DEV/portlibs/ppu/lib" append_var LDFLAGS "-L$PSL1GHT/ppu/lib -L$PS3DEV/portlibs/ppu/lib"
# The network libraries are statically linked and need to be specified in the following order # The network libraries are statically linked and need to be specified in the following order
append_var SDL_NET_LIBS "-lSDL_net -lnet -lsysmodule" append_var SDL_NET_LIBS "-lSDL_net -lnet -lsysmodule"
@ -2836,8 +2839,6 @@ if test -n "$_host"; then
arm-linux|arm*-linux-gnueabi|arm-*-linux) arm-linux|arm*-linux-gnueabi|arm-*-linux)
;; ;;
arm-*riscos) arm-*riscos)
_seq_midi=no
_timidity=no
_opengl_mode=none _opengl_mode=none
_build_hq_scalers=no _build_hq_scalers=no
# toolchain binaries prefixed by host # toolchain binaries prefixed by host
@ -3037,9 +3038,6 @@ if test -n "$_host"; then
_seq_midi=no _seq_midi=no
_timidity=no _timidity=no
;; ;;
linupy)
append_var DEFINES "-DLINUPY"
;;
m68k-atari-mint) m68k-atari-mint)
append_var DEFINES "-DSYSTEM_NOT_SUPPORTING_D_TYPE" append_var DEFINES "-DSYSTEM_NOT_SUPPORTING_D_TYPE"
_ranlib=m68k-atari-mint-ranlib _ranlib=m68k-atari-mint-ranlib
@ -3214,7 +3212,6 @@ if test -n "$_host"; then
fi fi
;; ;;
ps3) ps3)
_mt32emu=no
_timidity=no _timidity=no
_vkeybd=yes _vkeybd=yes
_eventrec=no _eventrec=no
@ -3231,6 +3228,7 @@ if test -n "$_host"; then
_port_mk="backends/platform/sdl/psp2/psp2.mk" _port_mk="backends/platform/sdl/psp2/psp2.mk"
;; ;;
psp) psp)
append_var DEFINES "-DGUI_ONLY_FULLSCREEN"
_backend="psp" _backend="psp"
_build_scalers=no _build_scalers=no
_mt32emu=no _mt32emu=no
@ -3407,7 +3405,7 @@ case $_backend in
append_var LIBS "-lSceSysmodule_stub -lSceDisplay_stub -lSceGxm_stub" append_var LIBS "-lSceSysmodule_stub -lSceDisplay_stub -lSceGxm_stub"
append_var LIBS "-lSceAudio_stub -lSceCtrl_stub -lScePower_stub" append_var LIBS "-lSceAudio_stub -lSceCtrl_stub -lScePower_stub"
append_var LIBS "-lSceNet_stub -lSceNetCtl_stub -lSceAppMgr_stub -lScePgf_stub" append_var LIBS "-lSceNet_stub -lSceNetCtl_stub -lSceAppMgr_stub -lScePgf_stub"
append_var LIBS "-lSceTouch_stub" append_var LIBS "-lSceTouch_stub -lSceHid_stub"
append_var DEFINES "-DSDL_BACKEND" append_var DEFINES "-DSDL_BACKEND"
add_line_to_config_mk "SDL_BACKEND = 1" add_line_to_config_mk "SDL_BACKEND = 1"
add_line_to_config_mk "USE_SDL2 = 1" add_line_to_config_mk "USE_SDL2 = 1"
@ -3483,7 +3481,11 @@ case $_backend in
androidsdl | dingux | gph | linuxmoto | maemo | openpandora | samsungtv | sdl) androidsdl | dingux | gph | linuxmoto | maemo | openpandora | samsungtv | sdl)
find_sdlconfig find_sdlconfig
append_var INCLUDES "`$_sdlconfig --prefix="$_sdlpath" --cflags`" append_var INCLUDES "`$_sdlconfig --prefix="$_sdlpath" --cflags`"
append_var LIBS "`$_sdlconfig --prefix="$_sdlpath" --libs`" if test "$_static_build" = yes ; then
append_var LIBS "`$_sdlconfig --prefix="$_sdlpath" --static-libs`"
else
append_var LIBS "`$_sdlconfig --prefix="$_sdlpath" --libs`"
fi
append_var DEFINES "-DSDL_BACKEND" append_var DEFINES "-DSDL_BACKEND"
add_line_to_config_mk "SDL_BACKEND = 1" add_line_to_config_mk "SDL_BACKEND = 1"
@ -3600,10 +3602,10 @@ esac
# #
echo_n "Checking if host is POSIX compliant... " echo_n "Checking if host is POSIX compliant... "
case $_host_os in case $_host_os in
amigaos* | cygwin* | dreamcast | ds | gamecube | mingw* | n64 | ps2 | ps3 | psp2 | psp | wii | wince) amigaos* | cygwin* | dreamcast | ds | gamecube | mingw* | n64 | ps2 | ps3 | psp2 | psp | riscos | wii | wince)
_posix=no _posix=no
;; ;;
3ds | android | androidsdl | beos* | bsd* | darwin* | freebsd* | gnu* | gph-linux | haiku* | hpux* | iphone | ios7 | irix*| k*bsd*-gnu* | linux* | maemo | mint* | netbsd* | openbsd* | riscos | solaris* | sunos* | uclinux* | webos) 3ds | android | androidsdl | beos* | bsd* | darwin* | freebsd* | gnu* | gph-linux | haiku* | hpux* | iphone | ios7 | irix*| k*bsd*-gnu* | linux* | maemo | mint* | netbsd* | openbsd* | solaris* | sunos* | uclinux* | webos)
_posix=yes _posix=yes
;; ;;
os2-emx*) os2-emx*)
@ -3623,6 +3625,17 @@ echo $_posix
if test "$_posix" = yes ; then if test "$_posix" = yes ; then
append_var DEFINES "-DPOSIX" append_var DEFINES "-DPOSIX"
add_line_to_config_mk 'POSIX = 1' add_line_to_config_mk 'POSIX = 1'
echo_n "Checking if posix_spawn is supported... "
cat > $TMPC << EOF
#include <spawn.h>
int main(void) { return posix_spawn(0, 0, 0, 0, 0, 0); }
EOF
cc_check && _has_posix_spawn=yes
echo $_has_posix_spawn
if test "$_has_posix_spawn" = yes ; then
append_var DEFINES "-DHAS_POSIX_SPAWN"
fi
fi fi
# #

View file

@ -1,5 +1,5 @@
/* /*
README to .guide converter $Ver: 0.13 (29.01.2016) README to .guide converter $VER: RM2AG.rx 0.15 (25.01.2018)
This script converts the pure ASCII-text based README file of ResidualVM to a This script converts the pure ASCII-text based README file of ResidualVM to a
basic Amiga guide file. basic Amiga guide file.
@ -23,7 +23,6 @@ ELSE DO
END END
/* If it's the proper file, lets start converting */ /* If it's the proper file, lets start converting */
OPEN(readme_read,readme_txt,'R') OPEN(readme_read,readme_txt,'R')
OPEN(guide_write,'README.guide','W') OPEN(guide_write,'README.guide','W')
@ -38,7 +37,6 @@ WRITELN(guide_write,READLN(readme_read))
WRITELN(guide_write,'@{ub}') WRITELN(guide_write,'@{ub}')
/* Creating the main link nodes */ /* Creating the main link nodes */
x=1 x=1
DO WHILE EOF(readme_read) = 0 DO WHILE EOF(readme_read) = 0
@ -46,60 +44,59 @@ DO WHILE EOF(readme_read) = 0
working_line=READLN(readme_read) working_line=READLN(readme_read)
/* Checking if the sub links have been reached and leave the loop, if met */ /* Checking if the sub links have been reached and leave the loop, if met */
IF POS('°1.0°',working_line) = 1 & x > 1 THEN IF POS('<>1.0<>',working_line) = 1 & x > 1 THEN
LEAVE LEAVE
ENDIF
/* If no chapter has been found, simply write the line */ /* If no chapter has been found, simply write the line */
IF POS('°',working_line) = 0 THEN IF POS('<>',working_line) = 0 THEN
WRITELN(guide_write,working_line) WRITELN(guide_write,working_line)
ENDIF
/* Fix the empty chapters - two chapters (1.0 and 7.8) are empty and consist of only the headlines. /* Fix the empty chapters - two chapters (1.0 and 7.8) are empty and consist of only the headlines.
We add them to the following chapter and link both of them to the empty one */ We add them to the following chapter and link both of them to the empty one */
/* If chapter 1.1 is found add a link node to 1.0 (as chapter 1.0 is empty) */ /* If chapter 1.1 is found add a link node to 1.0 (as chapter 1.0 is empty) */
IF POS(' * °1.1°',working_line) = 1 THEN DO IF POS(' * <>1.1<>',working_line) = 1 THEN DO
/* Get rid of the markers so the following loops doesn't process them again */ /* Get rid of the markers so the following loops doesn't process them again */
working_line=COMPRESS(working_line,'*°') working_line=COMPRESS(working_line,'*<>')
WRITELN(guide_write,' @{" 1.1 " Link "1.0"} 'working_line) WRITELN(guide_write,' @{" 1.1 " Link "1.0"} 'working_line)
END END
/* If chapter 7.8.1 is found add a link node to 7.8 (as chapter 7.8 is empty) */ /* If chapter 7.8.1 is found add a link node to 7.8 (as chapter 7.8 is empty) */
IF POS(' * * °7.8.1°',working_line) = 1 THEN DO IF POS(' * * <>7.8.1<>',working_line) = 1 THEN DO
/* Get rid of the markers so the following loops doesn't process them again */ /* Get rid of the markers so the following loops doesn't process them again */
working_line=COMPRESS(working_line,'*°') working_line=COMPRESS(working_line,'*<>')
WRITELN(guide_write,' @{" 7.8.1 " Link "7.8"} 'working_line) WRITELN(guide_write,' @{" 7.8.1 " Link "7.8"} 'working_line)
END END
/* If a single number main chapter is found 1.0 upto 9.0), prepare and write the link node */ /* If a single number main chapter is found 1.0 upto 9.0), prepare and write the link node */
IF POS('.0',working_line) = 3 THEN DO IF POS('.0',working_line) = 4 THEN DO
WRITELN(guide_write,' ') WRITELN(guide_write,' ')
WRITELN(guide_write,' @{" 'SUBSTR(working_line,POS('°',working_line)+1,LASTPOS('°',working_line)-POS('°',working_line)-1) '" Link "'SUBSTR(working_line,POS('°',working_line)+1,LASTPOS('°',working_line)-POS('°',working_line)-1)'"} 'COMPRESS(working_line,'*°')) WRITELN(guide_write,' @{" 'SUBSTR(working_line,POS('<>',working_line)+2,LASTPOS('<>',working_line)-POS('<>',working_line)-2) '" Link "'SUBSTR(working_line,POS('<>',working_line)+2,LASTPOS('<>',working_line)-POS('<>',working_line)-2)'"} 'COMPRESS(working_line,'*<>'))
/* Get rid of the markers so the following loops doesn't process them again */ /* Get rid of the markers so the following loops doesn't process them again */
working_line=COMPRESS(working_line,'*°') working_line=COMPRESS(working_line,'*<>')
x=x+1 x=x+1
END END
/* If a double number main chapter is found (10.0 ff), prepare and write the link node */ /* If a double number main chapter is found (10.0 ff), prepare and write the link node */
IF POS('.0',working_line) = 4 THEN DO IF POS('.0',working_line) = 5 THEN DO
WRITELN(guide_write,' ') WRITELN(guide_write,' ')
WRITELN(guide_write,' @{" 'SUBSTR(working_line,POS('°',working_line)+1,LASTPOS('°',working_line)-POS('°',working_line)-1) '" Link "'SUBSTR(working_line,POS('°',working_line)+1,LASTPOS('°',working_line)-POS('°',working_line)-1)'"} 'COMPRESS(working_line,'*°')) WRITELN(guide_write,' @{" 'SUBSTR(working_line,POS('<>',working_line)+2,LASTPOS('<>',working_line)-POS('<>',working_line)-2) '" Link "'SUBSTR(working_line,POS('<>',working_line)+2,LASTPOS('<>',working_line)-POS('<>',working_line)-2)'"} 'COMPRESS(working_line,'*<>'))
/* Get rid of the markers so the following loops doesn't process them again */ /* Get rid of the markers so the following loops doesn't process them again */
working_line=COMPRESS(working_line,'*°') working_line=COMPRESS(working_line,'*<>')
END END
/* If a level one sub chapter is found (i.e. 1.1), prepare and write the link node */ /* If a level one sub chapter is found (i.e. 1.1), prepare and write the link node */
IF POS(' * °',working_line) = 1 THEN DO IF POS(' * <>',working_line) = 1 THEN DO
WRITELN(guide_write,' @{" 'SUBSTR(working_line,POS('°',working_line)+1,LASTPOS('°',working_line)-POS('°',working_line)-1) '" Link "'SUBSTR(working_line,POS('°',working_line)+1,LASTPOS('°',working_line)-POS('°',working_line)-1)'"} 'COMPRESS(working_line,'*°')) WRITELN(guide_write,' @{" 'SUBSTR(working_line,POS('<>',working_line)+2,LASTPOS('<>',working_line)-POS('<>',working_line)-2) '" Link "'SUBSTR(working_line,POS('<>',working_line)+2,LASTPOS('<>',working_line)-POS('<>',working_line)-2)'"} 'COMPRESS(working_line,'*<>'))
/* Get rid of the markers so the following loops doesn't process them again */ /* Get rid of the markers so the following loops doesn't process them again */
working_line=COMPRESS(working_line,'*°') working_line=COMPRESS(working_line,'*<>')
END END
/* If a level two sub chapter is found (i.e. 1.1.1), prepare and write the link node */ /* If a level two sub chapter is found (i.e. 1.1.1), prepare and write the link node */
IF POS(' * * °',working_line) = 1 THEN DO IF POS(' * * <>',working_line) = 1 THEN DO
WRITELN(guide_write,' @{" 'SUBSTR(working_line,POS('°',working_line)+1,LASTPOS('°',working_line)-POS('°',working_line)-1) '" Link "'SUBSTR(working_line,POS('°',working_line)+1,LASTPOS('°',working_line)-POS('°',working_line)-1)'"} 'COMPRESS(working_line,'*°')) WRITELN(guide_write,' @{" 'SUBSTR(working_line,POS('<>',working_line)+2,LASTPOS('<>',working_line)-POS('<>',working_line)-2) '" Link "'SUBSTR(working_line,POS('<>',working_line)+2,LASTPOS('<>',working_line)-POS('<>',working_line)-2)'"} 'COMPRESS(working_line,'*<>'))
/* Get rid of the markers so the following loops doesn't process them again */ /* Get rid of the markers so the following loops doesn't process them again */
working_line=COMPRESS(working_line,'*°') working_line=COMPRESS(working_line,'*<>')
END END
END END
@ -111,43 +108,42 @@ WRITELN(guide_write,'@{"http://www.residualvm.org/" System "URLOpen http://www.r
WRITELN(guide_write,'------------------------------------------------------------------------') WRITELN(guide_write,'------------------------------------------------------------------------')
/* Creating the sub links nodes */ /* Creating the sub links nodes */
DO WHILE EOF(readme_read) = 0 DO WHILE EOF(readme_read) = 0
/* If no chapter has been found, simply write the line */ /* If no chapter has been found, simply write the line */
IF POS('°',working_line) = 0 THEN IF POS('<>',working_line) = 0 THEN
WRITELN(guide_write,working_line) WRITELN(guide_write,working_line)
ENDIF
/* Fix the empty chapters - two chapters (1.0 and 7.8) are empty and consist of only the Headlines. /* Fix the empty chapters - two chapters (1.0 and 7.8) are empty and consist of only the Headlines.
We don't close the NODE, rather add the following chapter to the former empty one */ We don't close the NODE, rather add the following chapter to the former empty one */
/* If chapter 1.1 is found don't close the NODE, just write the line */ /* If chapter 1.1 is found don't close the NODE, just write the line */
IF POS('°1.1°',working_line) = 1 THEN DO IF POS('<>1.1<>',working_line) = 1 THEN DO
/* Get rid of the markers so the following loops doesn't process them again */ /* Get rid of the markers so the following loops doesn't process them again */
working_line=COMPRESS(working_line,'°') working_line=COMPRESS(working_line,'<>')
WRITELN(guide_write,working_line)
END
/* If chapter 7.8.1 is found don't close the NODE, just write the line */
IF POS('°7.8.1°',working_line) = 1 THEN DO
/* Get rid of the markers so the following loops doesn't process them again */
working_line=COMPRESS(working_line,'°')
WRITELN(guide_write,working_line) WRITELN(guide_write,working_line)
END END
IF POS('°',working_line) > 0 THEN DO /* If chapter 7.8.1 is found don't close the NODE, just write the line */
IF POS('<>7.8.1<>',working_line) = 1 THEN DO
/* Get rid of the markers so the following loops doesn't process them again */
working_line=COMPRESS(working_line,'<>')
WRITELN(guide_write,working_line)
END
IF POS('<>',working_line) > 0 THEN DO
/* Check for link references inside the text and create link nodes for them */ /* Check for link references inside the text and create link nodes for them */
IF POS('section °',working_line) > 0 THEN DO IF POS('section <>',working_line) > 0 THEN DO
working_line=SUBSTR(working_line,1,POS('°',working_line)-1)'@{"'SUBSTR(working_line,POS('°',working_line)+1,LASTPOS('°',working_line)-POS('°',working_line)-1)'" Link "'SUBSTR(working_line,POS('°',working_line)+1,LASTPOS('°',working_line)-POS('°',working_line)-1)'"}'SUBSTR(working_line,LASTPOS('°',working_line)+1) working_line=SUBSTR(working_line,1,POS('<>',working_line)-1)'@{"'SUBSTR(working_line,POS('<>',working_line)+2,LASTPOS('<>',working_line)-POS('<>',working_line)-2)'" Link "'SUBSTR(working_line,POS('<>',working_line)+2,LASTPOS('<>',working_line)-POS('<>',working_line)-2)'"}'SUBSTR(working_line,LASTPOS('<>',working_line)+2)
/* Get rid of the markers so the following loops doesn't process them again */ /* Get rid of the markers so the following loops doesn't process them again */
WRITELN(guide_write,COMPRESS(working_line,'°')) WRITELN(guide_write,COMPRESS(working_line,'<>'))
END END
ELSE DO ELSE DO
/* If a chapter has been found, prepare and write the link */ /* If a chapter has been found, prepare and write the link */
WRITELN(guide_write,'@ENDNODE') WRITELN(guide_write,'@ENDNODE')
WRITELN(guide_write,'@NODE "'SUBSTR(working_line,POS('°',working_line)+1,LASTPOS('°',working_line)-POS('°',working_line)-1)'" "'COMPRESS(working_line,'°')'"') WRITELN(guide_write,'@NODE "'SUBSTR(working_line,POS('<>',working_line)+2,LASTPOS('<>',working_line)-POS('<>',working_line)-2)'" "'COMPRESS(working_line,'<>')'"')
WRITELN(guide_write,' ') WRITELN(guide_write,' ')
/* Get rid of the markers so the following loops doesn't process them again */ /* Get rid of the markers so the following loops doesn't process them again */
WRITELN(guide_write,COMPRESS(working_line,'°')) WRITELN(guide_write,COMPRESS(working_line,'<>'))
END END
END END
@ -157,7 +153,6 @@ DO WHILE EOF(readme_read) = 0
/* If the outtro text is found, leave the loop and prepare for closing */ /* If the outtro text is found, leave the loop and prepare for closing */
IF POS('------------------------------------------------------------------------',working_line) > 0 THEN IF POS('------------------------------------------------------------------------',working_line) > 0 THEN
LEAVE LEAVE
ENDIF
END END
WRITELN(guide_write,'@ENDNODE') WRITELN(guide_write,'@ENDNODE')
@ -167,4 +162,5 @@ WRITELN(guide_write,'@ENDNODE')
CLOSE(readme_read) CLOSE(readme_read)
CLOSE(guide_write) CLOSE(guide_write)
EXIT 0
EXIT 0

View file

@ -1,17 +1,17 @@
# $VER: READMEconverter.sed 1.04 (22.12.2015) © Eugene "sev" Sandulenko # $VER: READMEconverter.sed 1.05 (25.01.2018) © Eugene "sev" Sandulenko
# Additions by Raziel # Additions and changes by Raziel
# #
# Preprocessing the README file and adding some landmarks for easier parsing # Preprocessing the README file and adding some markers for easier parsing
# and for converting it to an AmigaGuide Hypertext file later. # and later converting it to an AmigaGuide Hypertext file.
# #
s/http:\/\/[#?=&a-zA-Z0-9_.\/\-]*/@{"&" System "URLOpen &"}/ # Convert all URLs to AmigaGuide format s/http:\/\/[#?=&a-zA-Z0-9_.\/\-]*/@{"&" System "URLOpen &"}/ # Convert all URLs to AmigaGuide format
s/https:\/\/[#?=&a-zA-Z0-9_.\/\-]*/@{"&" System "URLOpen &"}/ # Convert all secure URLs to AmigaGuide format s/https:\/\/[#?=&a-zA-Z0-9_.\/\-]*/@{"&" System "URLOpen &"}/ # Convert all secure URLs to AmigaGuide format
s/[0-9][0-9]*\.[0-9][0-9]*/°&°/ # Convert all chapter numbers to °x°... s/[0-9][0-9]*\.[0-9][0-9]*/<>&<>/ # Convert all chapter numbers to <>x<>...
s/°\([0-9][0-9]*\.[0-9][0-9]*\)°\(\.[0-9]\)/°\1\2°/ # ...and all three-digit chapter numbers... s/<>\([0-9][0-9]*\.[0-9][0-9]*\)<>\(\.[0-9]\)/<>\1\2<>/ # ...and all three-digit chapter numbers...
s/°\([01]\.[0-9][0-9]*\.[0-9][0-9]*\)°/\1/ # ...and restore mentioned version numbers like 1.0.0 and 0.7.0. s/<>\([01]\.[0-9][0-9]*\.[0-9][0-9]*\)<>/\1/ # ...and restore mentioned version numbers like 1.0.0 and 0.7.0.
s/of °0\.0°/of 0.0/ # "Fluidsynth's gain setting of 0.0" is not a chapter reference. s/of <>0\.0<>/of 0.0/ # "Fluidsynth's gain setting of 0.0" is not a chapter reference.
s/through °10\.0°/through 10.0/ # "through 10.0" is not a chapter reference. s/through <>10\.0<>/through 10.0/ # "through 10.0" is not a chapter reference.
s/ttf-°2\.00.1°/ttf-2.00.1/ # This part of an url link is not a chapter reference. s/ttf-<>2\.00.1<>/ttf-2.00.1/ # This part of an url link is not a chapter reference.
s/patch °1\.2°/patch 1.2/ # "Zork patch 1.2" is not a chapter reference. s/patch <>1\.2<>/patch 1.2/ # "Zork patch 1.2" is not a chapter reference.
s/Mac OS X °10\.2.8°/Mac OS X 10.2.8/ # "Mac OS X 10.2.8" is not a chapter reference. s/Mac OS X <>10\.2.8<>/Mac OS X 10.2.8/ # "Mac OS X 10.2.8" is not a chapter reference.
s/Mac_OS_X_°10\.2.8°/Mac_OS_X_10.2.8/ # "Mac_OS_X_10.2.8" is not a chapter reference. s/Mac_OS_X_<>10\.2.8<>/Mac_OS_X_10.2.8/ # "Mac_OS_X_10.2.8" is not a chapter reference.

View file

@ -19,7 +19,7 @@
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>0.4.0git</string> <string>0.4.0git</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>Copyright 2003-2016 The ResidualVM Team</string> <string>Copyright 2003-2018 The ResidualVM Team</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string>ResidualVMDockTilePlugIn</string> <string>ResidualVMDockTilePlugIn</string>
</dict> </dict>

View file

@ -19,7 +19,7 @@
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>@VERSION@</string> <string>@VERSION@</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>Copyright 2003-2016 The ResidualVM Team</string> <string>Copyright 2003-2018 The ResidualVM Team</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string>ResidualVMDockTilePlugIn</string> <string>ResidualVMDockTilePlugIn</string>
</dict> </dict>

View file

@ -20,14 +20,21 @@ Savegames are wrote in the /hdd0/game/RESI12000/saves folder.
Joypad button mapping Joypad button mapping
===================== =====================
- Left stick => Mouse - Left stick => Mouse
- Cross => Left mouse button - R1 + Left stick => Slow Mouse
- Circle => Right mouse button - Cross => Left mouse button
- Triangle => Game menu (F5) - Circle => Right mouse button
- Square => Escape - DPad => Cursor Keys (useful for character motion)
- Start => ResidualVM's in global game menu - R1 + DPad => Diagonal Cursor Keys
- Select => Toggle virtual keyboard - L1 => Game menu (F5)
- L1 => AGI predictive input dialog - R1 => Shift (used to enable Mass Add in menu)
- Square => Period '.' (used to skip dialog lines)
- R1 + Square => Space ' '
- Triangle => Escape (used to skip cutscenes)
- R1 + Triangle => Return
- Start => ScummVM's global in-game menu
- Select => Toggle virtual keyboard
- R1 + Select => AGI predictive input dialog
Disclaimer Disclaimer
========== ==========

View file

@ -313,7 +313,7 @@ protected:
* @param extra restrict results to specified extra string (only if kADFlagUseExtraAsHint is set) * @param extra restrict results to specified extra string (only if kADFlagUseExtraAsHint is set)
* @return list of ADGameDescription pointers corresponding to matched games * @return list of ADGameDescription pointers corresponding to matched games
*/ */
ADGameDescList detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const; virtual ADGameDescList detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const;
/** /**
* Iterates over all ADFileBasedFallback records inside fileBasedFallback. * Iterates over all ADFileBasedFallback records inside fileBasedFallback.

View file

@ -74,21 +74,14 @@ MD5CheckDialog::MD5CheckDialog() :
} }
height += 20; height += 20;
_progressRect = Common::Rect(_x + 20, _y + height + 10, _x + _w - 20, _y + height + 20); _progressSliderWidget = new GUI::SliderWidget(this, 20, height + 10, _w - 40, 10);
check(); check();
} }
void MD5CheckDialog::drawDialog() {
GUI::Dialog::drawDialog();
g_gui.theme()->drawSlider(_progressRect, (int)(_progressRect.width() * _progress));
}
void MD5CheckDialog::check() { void MD5CheckDialog::check() {
_checkOk = true; _checkOk = true;
MD5Check::startCheckFiles(); MD5Check::startCheckFiles();
_progress = 0.f;
draw();
} }
void MD5CheckDialog::handleTickle() { void MD5CheckDialog::handleTickle() {
@ -97,13 +90,13 @@ void MD5CheckDialog::handleTickle() {
if (!MD5Check::advanceCheck(&p, &t)) { if (!MD5Check::advanceCheck(&p, &t)) {
_checkOk = false; _checkOk = false;
} }
_progress = (float)p / (float)t; _progressSliderWidget->setValue(p * 100 / t);
_progressSliderWidget->markAsDirty();
if (p == t) { if (p == t) {
setResult(_checkOk); setResult(_checkOk);
close(); close();
} }
draw();
} }
} }

View file

@ -27,6 +27,10 @@
#include "gui/dialog.h" #include "gui/dialog.h"
namespace GUI {
class SliderWidget;
}
namespace Grim { namespace Grim {
class MD5CheckDialog : public GUI::Dialog { class MD5CheckDialog : public GUI::Dialog {
@ -34,14 +38,13 @@ public:
MD5CheckDialog(); MD5CheckDialog();
protected: protected:
virtual void handleTickle() override; void handleTickle() override;
virtual void drawDialog() override;
private: private:
void check(); void check();
Common::Rect _progressRect; GUI::SliderWidget *_progressSliderWidget;
float _progress;
bool _checkOk; bool _checkOk;
}; };

View file

@ -262,20 +262,15 @@ public:
//@} //@}
}; };
// Engine plugins
typedef PluginSubclass<MetaEngine> EnginePlugin;
/** /**
* Singleton class which manages all Engine plugins. * Singleton class which manages all Engine plugins.
*/ */
class EngineManager : public Common::Singleton<EngineManager> { class EngineManager : public Common::Singleton<EngineManager> {
public: public:
GameDescriptor findGameInLoadedPlugins(const Common::String &gameName, const EnginePlugin **plugin = NULL) const; GameDescriptor findGameInLoadedPlugins(const Common::String &gameName, const Plugin **plugin = NULL) const;
GameDescriptor findGame(const Common::String &gameName, const EnginePlugin **plugin = NULL) const; GameDescriptor findGame(const Common::String &gameName, const Plugin **plugin = NULL) const;
GameList detectGames(const Common::FSList &fslist) const; GameList detectGames(const Common::FSList &fslist) const;
const EnginePlugin::List &getPlugins() const; const PluginList &getPlugins() const;
}; };
/** Convenience shortcut for accessing the engine manager. */ /** Convenience shortcut for accessing the engine manager. */

View file

@ -289,6 +289,13 @@ public:
_activeSurface = surface; _activeSurface = surface;
} }
/**
* Returns the currently active drawing surface
*/
virtual TransparentSurface *getActiveSurface() {
return _activeSurface;
}
/** /**
* Fills the active surface with the specified fg/bg color or the active gradient. * Fills the active surface with the specified fg/bg color or the active gradient.
* Defaults to using the active Foreground color for filling. * Defaults to using the active Foreground color for filling.

View file

@ -52,7 +52,7 @@ inline frac_t fp_sqroot(uint32 x) {
// decreasing values. By feeding it the sqrt of the previous old x, as well // decreasing values. By feeding it the sqrt of the previous old x, as well
// as the old x, it should be possible to compute the correct sqrt with far // as the old x, it should be possible to compute the correct sqrt with far
// fewer than 23 iterations. // fewer than 23 iterations.
register uint32 root, remHI, remLO, testDIV, count; uint32 root, remHI, remLO, testDIV, count;
root = 0; root = 0;
remHI = 0; remHI = 0;
@ -443,10 +443,10 @@ namespace Graphics {
*/ */
template<typename PixelType> template<typename PixelType>
void colorFill(PixelType *first, PixelType *last, PixelType color) { void colorFill(PixelType *first, PixelType *last, PixelType color) {
register int count = (last - first); int count = (last - first);
if (!count) if (!count)
return; return;
register int n = (count + 7) >> 3; int n = (count + 7) >> 3;
switch (count % 8) { switch (count % 8) {
case 0: do { case 0: do {
*first++ = color; // fall through *first++ = color; // fall through
@ -466,26 +466,26 @@ void colorFillClip(PixelType *first, PixelType *last, PixelType color, int realX
if (realY < clippingArea.top || realY >= clippingArea.bottom) if (realY < clippingArea.top || realY >= clippingArea.bottom)
return; return;
register int count = (last - first); int count = (last - first);
if (realX > clippingArea.right || realX + count < clippingArea.left) if (realX > clippingArea.right || realX + count < clippingArea.left)
return; return;
if (realX < clippingArea.left) { if (realX < clippingArea.left) {
register int diff = (clippingArea.left - realX); int diff = (clippingArea.left - realX);
realX += diff; realX += diff;
count -= diff; count -= diff;
} }
if (clippingArea.right <= realX + count) { if (clippingArea.right <= realX + count) {
register int diff = (realX + count - clippingArea.right); int diff = (realX + count - clippingArea.right);
count -= diff; count -= diff;
} }
if (!count) if (!count)
return; return;
register int n = (count + 7) >> 3; int n = (count + 7) >> 3;
switch (count % 8) { switch (count % 8) {
case 0: do { case 0: do {
*first++ = color; // fall through *first++ = color; // fall through
@ -936,34 +936,26 @@ blitKeyBitmapClip(const Graphics::Surface *source, const Common::Rect &r, const
if (r.height() > source->h) if (r.height() > source->h)
y = y + (r.height() >> 1) - (source->h >> 1); y = y + (r.height() >> 1) - (source->h >> 1);
int w = source->w, h = source->h; Common::Rect drawRect(x, y, x + source->w, y + source->h);
int usedW = w, usedH = h; drawRect.clip(clipping);
int offsetX = 0, offsetY = 0;
if (x > clipping.right || x + w < clipping.left) return; if (drawRect.isEmpty()) {
if (y > clipping.bottom || y + h < clipping.top) return; return;
if (x < clipping.left) {
offsetX = clipping.left - x;
usedW -= offsetX;
x = clipping.left;
} }
if (y < clipping.top) {
offsetY = clipping.top - y;
usedH -= offsetY;
y = clipping.top;
}
if (usedW > clipping.width()) usedW = clipping.width();
if (usedH > clipping.height()) usedH = clipping.height();
PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(x, y); int sourceOffsetX = drawRect.left - x;
const PixelType *src_ptr = (const PixelType *)source->getBasePtr(offsetX, offsetY); int sourceOffsetY = drawRect.top - y;
PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(drawRect.left, drawRect.top);
const PixelType *src_ptr = (const PixelType *)source->getBasePtr(sourceOffsetX, sourceOffsetY);
int dst_pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int dst_pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int src_pitch = source->pitch / source->format.bytesPerPixel; int src_pitch = source->pitch / source->format.bytesPerPixel;
h = usedH; int w, h = drawRect.height();
while (h--) { while (h--) {
w = usedW; w = drawRect.width();
while (w--) { while (w--) {
if (*src_ptr != _bitmapAlphaColor) if (*src_ptr != _bitmapAlphaColor)
@ -973,8 +965,8 @@ blitKeyBitmapClip(const Graphics::Surface *source, const Common::Rect &r, const
src_ptr++; src_ptr++;
} }
dst_ptr = dst_ptr - usedW + dst_pitch; dst_ptr = dst_ptr - drawRect.width() + dst_pitch;
src_ptr = src_ptr - usedW + src_pitch; src_ptr = src_ptr - drawRect.width() + src_pitch;
} }
} }
@ -3207,8 +3199,6 @@ drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType colo
while (x++ < y) { while (x++ < y) {
BE_ALGORITHM(); BE_ALGORITHM();
if (y1 + r + y < _clippingArea.top || y1 + r + y > _clippingArea.bottom) continue;
color1 = calcGradient(real_radius - x, long_h); color1 = calcGradient(real_radius - x, long_h);
color2 = calcGradient(real_radius - y, long_h); color2 = calcGradient(real_radius - y, long_h);
color3 = calcGradient(long_h - r + x, long_h); color3 = calcGradient(long_h - r + x, long_h);
@ -3587,42 +3577,44 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8; uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
// These constants ensure a border of 2px on the left and of each rounded square // These constants ensure a border of 2px on the left and of each rounded square
int xstart = (x1 > 2) ? x1 - 2 : x1; Common::Rect shadowRect(w + offset + 2, h + offset + 1);
int ystart = y1; shadowRect.translate((x1 > 2) ? x1 - 2 : x1, y1);
int width = w + offset + 2;
int height = h + offset + 1;
// The rounded rectangle drawn on top of this shadow is guaranteed
// to occlude entirely the following rect with a non-transparent color.
// As an optimization, we don't draw the shadow inside of it.
Common::Rect occludingRect(x1, y1, x1 + w, y1 + h);
occludingRect.top += r;
occludingRect.bottom -= r;
// Soft shadows are constructed by drawing increasingly
// darker and smaller rectangles on top of each other.
for (int i = offset; i >= 0; i--) { for (int i = offset; i >= 0; i--) {
int f, ddF_x, ddF_y; int f, ddF_x, ddF_y;
int x, y, px, py; int x, y, px, py;
PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r); PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left + r, shadowRect.top + r);
PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r); PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.top + r);
PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + height - r); PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left + r, shadowRect.bottom - r);
PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + height - r); PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.bottom - r);
PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
int short_h = height - (2 * r) + 2;
PixelType color = _format.RGBToColor(0, 0, 0); PixelType color = _format.RGBToColor(0, 0, 0);
BE_RESET(); BE_RESET();
// HACK: As we are drawing circles exploting 8-axis symmetry, // HACK: As we are drawing circles exploiting 8-axis symmetry,
// there are 4 pixels on each circle which are drawn twice. // there are 4 pixels on each circle which are drawn twice.
// this is ok on filled circles, but when blending on surfaces, // this is ok on filled circles, but when blending on surfaces,
// we cannot let it blend twice. awful. // we cannot let it blend twice. awful.
uint32 hb = 0; uint32 hb = 0;
// Draw the top and bottom parts of the shadow. Those parts have rounded corners.
while (x++ < y) { while (x++ < y) {
BE_ALGORITHM(); BE_ALGORITHM();
if (((1 << x) & hb) == 0) { if (((1 << x) & hb) == 0) {
blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha); blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
blendFill(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
// Will create a dark line of pixles if left out
if (hb > 0) {
blendFill(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
}
hb |= (1 << x); hb |= (1 << x);
} }
@ -3633,17 +3625,26 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
} }
} }
ptr_fill += pitch * r; // Draw the middle part of the shadow. This part is a rectangle with regular corners.
while (short_h--) { PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(0, shadowRect.top + r);
blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha); for (int y2 = shadowRect.top + r; y2 < shadowRect.bottom - r + 1; y2++) {
if (occludingRect.top <= y2 && y2 < occludingRect.bottom) {
if (shadowRect.left < occludingRect.left) {
blendFill(ptr_fill + shadowRect.left, ptr_fill + occludingRect.left, color, (uint8)alpha);
}
if (occludingRect.right < shadowRect.right + 1) {
blendFill(ptr_fill + occludingRect.right, ptr_fill + shadowRect.right + 1, color, (uint8)alpha);
}
} else {
blendFill(ptr_fill + shadowRect.left, ptr_fill + shadowRect.right + 1, color, (uint8)alpha);
}
ptr_fill += pitch; ptr_fill += pitch;
} }
// Make shadow smaller each iteration, and move it one pixel inward // Make shadow smaller each iteration
xstart += 1; shadowRect.grow(-1);
ystart += 1;
width -= 2;
height -= 2;
if (_shadowFillMode == kShadowExponential) if (_shadowFillMode == kShadowExponential)
// Multiply with expfactor // Multiply with expfactor
@ -3661,27 +3662,32 @@ drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset) {
uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8; uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
// These constants ensure a border of 2px on the left and of each rounded square // These constants ensure a border of 2px on the left and of each rounded square
int xstart = (x1 > 2) ? x1 - 2 : x1; Common::Rect shadowRect(w + offset + 2, h + offset + 1);
int ystart = y1; shadowRect.translate((x1 > 2) ? x1 - 2 : x1, y1);
int width = w + offset + 2;
int height = h + offset + 1;
// The rounded rectangle drawn on top of this shadow is guaranteed
// to occlude entirely the following rect with a non-transparent color.
// As an optimization, we don't draw the shadow inside of it.
Common::Rect occludingRect(x1, y1, x1 + w, y1 + h);
occludingRect.top += r;
occludingRect.bottom -= r;
// Soft shadows are constructed by drawing increasingly
// darker and smaller rectangles on top of each other.
for (int i = offset; i >= 0; i--) { for (int i = offset; i >= 0; i--) {
int f, ddF_x, ddF_y; int f, ddF_x, ddF_y;
int x, y, px, py; int x, y, px, py;
PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r); PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left + r, shadowRect.top + r);
PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r); PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.top + r);
PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + height - r); PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left + r, shadowRect.bottom - r);
PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + height - r); PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.bottom - r);
PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
int short_h = height - (2 * r) + 2;
PixelType color = _format.RGBToColor(0, 0, 0); PixelType color = _format.RGBToColor(0, 0, 0);
BE_RESET(); BE_RESET();
// HACK: As we are drawing circles exploting 8-axis symmetry, // HACK: As we are drawing circles exploiting 8-axis symmetry,
// there are 4 pixels on each circle which are drawn twice. // there are 4 pixels on each circle which are drawn twice.
// this is ok on filled circles, but when blending on surfaces, // this is ok on filled circles, but when blending on surfaces,
// we cannot let it blend twice. awful. // we cannot let it blend twice. awful.
@ -3692,36 +3698,46 @@ drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset) {
if (((1 << x) & hb) == 0) { if (((1 << x) & hb) == 0) {
blendFillClip(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha, blendFillClip(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha,
xstart + r - y, ystart + r - x); shadowRect.left + r - y, shadowRect.top + r - x);
blendFillClip(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha,
shadowRect.left + r - y, shadowRect.bottom - r + x);
// Will create a dark line of pixles if left out
if (hb > 0) {
blendFillClip(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha,
xstart + r - y, ystart + height - r + x);
}
hb |= (1 << x); hb |= (1 << x);
} }
if (((1 << y) & hb) == 0) { if (((1 << y) & hb) == 0) {
blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha, xstart + r - x, ystart + r - y); blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha,
blendFillClip(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha, xstart + r - x, ystart + height - r + y); shadowRect.left + r - x, shadowRect.top + r - y);
blendFillClip(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha,
shadowRect.left + r - x, shadowRect.bottom - r + y);
hb |= (1 << y); hb |= (1 << y);
} }
} }
ptr_fill += pitch * r; // Draw the middle part of the shadow. This part is a rectangle with regular corners.
int orig_short_h = short_h; PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(0, shadowRect.top + r);
while (short_h--) { for (int y2 = shadowRect.top + r; y2 < shadowRect.bottom - r + 1; y2++) {
blendFillClip(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha,
xstart, ystart + r + orig_short_h - short_h - 1); if (occludingRect.top <= y2 && y2 < occludingRect.bottom) {
if (shadowRect.left < occludingRect.left) {
blendFillClip(ptr_fill + shadowRect.left, ptr_fill + occludingRect.left, color, (uint8)alpha,
shadowRect.left, y2);
}
if (occludingRect.right < shadowRect.right + 1) {
blendFillClip(ptr_fill + occludingRect.right, ptr_fill + shadowRect.right + 1, color, (uint8)alpha,
occludingRect.right, y2);
}
} else {
blendFillClip(ptr_fill + shadowRect.left, ptr_fill + shadowRect.right + 1, color, (uint8)alpha,
shadowRect.left, y2);
}
ptr_fill += pitch; ptr_fill += pitch;
} }
// Make shadow smaller each iteration, and move it one pixel inward // Make shadow smaller each iteration
xstart += 1; shadowRect.grow(-1);
ystart += 1;
width -= 2;
height -= 2;
if (_shadowFillMode == kShadowExponential) if (_shadowFillMode == kShadowExponential)
// Multiply with expfactor // Multiply with expfactor

View file

@ -335,7 +335,8 @@ void ManagedSurface::addDirtyRect(const Common::Rect &r) {
} }
void ManagedSurface::clear(uint color) { void ManagedSurface::clear(uint color) {
fillRect(getBounds(), color); if (!empty())
fillRect(getBounds(), color);
} }
} // End of namespace Graphics } // End of namespace Graphics

View file

@ -46,8 +46,8 @@ static inline uint32 interpolate32_1_1(uint32 p1, uint32 p2) {
*/ */
template<typename ColorMask> template<typename ColorMask>
static inline uint32 interpolate32_3_1(uint32 p1, uint32 p2) { static inline uint32 interpolate32_3_1(uint32 p1, uint32 p2) {
register uint32 x = ((p1 & ColorMask::qhighBits) >> 2) * 3 + ((p2 & ColorMask::qhighBits) >> 2); uint32 x = ((p1 & ColorMask::qhighBits) >> 2) * 3 + ((p2 & ColorMask::qhighBits) >> 2);
register uint32 y = ((p1 & ColorMask::qlowBits) * 3 + (p2 & ColorMask::qlowBits)) >> 2; uint32 y = ((p1 & ColorMask::qlowBits) * 3 + (p2 & ColorMask::qlowBits)) >> 2;
y &= ColorMask::qlowBits; y &= ColorMask::qlowBits;
return x + y; return x + y;

View file

@ -207,7 +207,7 @@ void convertYUV444ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
for (int h = 0; h < yHeight; h++) { for (int h = 0; h < yHeight; h++) {
for (int w = 0; w < yWidth; w++) { for (int w = 0; w < yWidth; w++) {
register const uint32 *L; const uint32 *L;
int16 cr_r = Cr_r_tab[*vSrc]; int16 cr_r = Cr_r_tab[*vSrc];
int16 crb_g = Cr_g_tab[*vSrc] + Cb_g_tab[*uSrc]; int16 crb_g = Cr_g_tab[*vSrc] + Cb_g_tab[*uSrc];
@ -256,7 +256,7 @@ void convertYUV420ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
for (int h = 0; h < halfHeight; h++) { for (int h = 0; h < halfHeight; h++) {
for (int w = 0; w < halfWidth; w++) { for (int w = 0; w < halfWidth; w++) {
register const uint32 *L; const uint32 *L;
int16 cr_r = Cr_r_tab[*vSrc]; int16 cr_r = Cr_r_tab[*vSrc];
int16 crb_g = Cr_g_tab[*vSrc] + Cb_g_tab[*uSrc]; int16 crb_g = Cr_g_tab[*vSrc] + Cb_g_tab[*uSrc];
@ -346,7 +346,7 @@ void convertYUV410ToRGB(byte *dstPtr, int dstPitch, const YUVToRGBLookup *lookup
// Declare some variables for the following macros // Declare some variables for the following macros
byte u, v; byte u, v;
int16 cr_r, crb_g, cb_b; int16 cr_r, crb_g, cb_b;
register const uint32 *L; const uint32 *L;
READ_QUAD(uSrc, u); READ_QUAD(uSrc, u);
READ_QUAD(vSrc, v); READ_QUAD(vSrc, v);

View file

@ -557,17 +557,19 @@ Common::SaveFileManager *EventRecorder::getSaveManager(Common::SaveFileManager *
} }
void EventRecorder::preDrawOverlayGui() { void EventRecorder::preDrawOverlayGui() {
if ((_initialized) || (_needRedraw)) { if ((_initialized) || (_needRedraw)) {
RecordMode oldMode = _recordMode; RecordMode oldMode = _recordMode;
_recordMode = kPassthrough; _recordMode = kPassthrough;
g_system->showOverlay(); g_system->showOverlay();
g_gui.theme()->clearAll(); g_gui.theme()->clearAll();
g_gui.theme()->openDialog(true, GUI::ThemeEngine::kShadingNone); g_gui.theme()->drawToBackbuffer();
_controlPanel->drawDialog(); _controlPanel->drawDialog(kDrawLayerBackground);
g_gui.theme()->finishBuffering(); g_gui.theme()->drawToScreen();
g_gui.theme()->copyBackBufferToScreen();
_controlPanel->drawDialog(kDrawLayerForeground);
g_gui.theme()->updateScreen(); g_gui.theme()->updateScreen();
_recordMode = oldMode; _recordMode = oldMode;
} }
} }
void EventRecorder::postDrawOverlayGui() { void EventRecorder::postDrawOverlayGui() {
@ -598,8 +600,7 @@ void EventRecorder::setFileHeader() {
return; return;
} }
TimeDate t; TimeDate t;
const EnginePlugin *plugin = 0; GameDescriptor desc = EngineMan.findGame(ConfMan.getActiveDomainName());
GameDescriptor desc = EngineMan.findGame(ConfMan.getActiveDomainName(), &plugin);
g_system->getTimeAndDate(t); g_system->getTimeAndDate(t);
if (_author.empty()) { if (_author.empty()) {
setAuthor("Unknown Author"); setAuthor("Unknown Author");
@ -619,19 +620,19 @@ SDL_Surface *EventRecorder::getSurface(int width, int height) {
bool EventRecorder::switchMode() { bool EventRecorder::switchMode() {
const Common::String gameId = ConfMan.get("gameid"); const Common::String gameId = ConfMan.get("gameid");
const EnginePlugin *plugin = 0; const Plugin *plugin = nullptr;
EngineMan.findGame(gameId, &plugin); EngineMan.findGame(gameId, &plugin);
bool metaInfoSupport = (*plugin)->hasFeature(MetaEngine::kSavesSupportMetaInfo); bool metaInfoSupport = plugin->get<MetaEngine>().hasFeature(MetaEngine::kSavesSupportMetaInfo);
bool featuresSupport = metaInfoSupport && bool featuresSupport = metaInfoSupport &&
g_engine->canSaveGameStateCurrently() && g_engine->canSaveGameStateCurrently() &&
(*plugin)->hasFeature(MetaEngine::kSupportsListSaves) && plugin->get<MetaEngine>().hasFeature(MetaEngine::kSupportsListSaves) &&
(*plugin)->hasFeature(MetaEngine::kSupportsDeleteSave); plugin->get<MetaEngine>().hasFeature(MetaEngine::kSupportsDeleteSave);
if (!featuresSupport) { if (!featuresSupport) {
return false; return false;
} }
int emptySlot = 1; int emptySlot = 1;
SaveStateList saveList = (*plugin)->listSaves(gameId.c_str()); SaveStateList saveList = plugin->get<MetaEngine>().listSaves(gameId.c_str());
for (SaveStateList::const_iterator x = saveList.begin(); x != saveList.end(); ++x) { for (SaveStateList::const_iterator x = saveList.begin(); x != saveList.end(); ++x) {
int saveSlot = x->getSaveSlot(); int saveSlot = x->getSaveSlot();
if (saveSlot == 0) { if (saveSlot == 0) {
@ -667,9 +668,9 @@ bool EventRecorder::checkForContinueGame() {
void EventRecorder::deleteTemporarySave() { void EventRecorder::deleteTemporarySave() {
if (_temporarySlot == -1) return; if (_temporarySlot == -1) return;
const Common::String gameId = ConfMan.get("gameid"); const Common::String gameId = ConfMan.get("gameid");
const EnginePlugin *plugin = 0; const Plugin *plugin = 0;
EngineMan.findGame(gameId, &plugin); EngineMan.findGame(gameId, &plugin);
(*plugin)->removeSaveState(gameId.c_str(), _temporarySlot); plugin->get<MetaEngine>().removeSaveState(gameId.c_str(), _temporarySlot);
_temporarySlot = -1; _temporarySlot = -1;
} }

View file

@ -82,7 +82,7 @@ void KeysDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
selection = Common::String::format(_("Associated key : none")); selection = Common::String::format(_("Associated key : none"));
_keyMapping->setLabel(selection); _keyMapping->setLabel(selection);
_keyMapping->draw(); _keyMapping->markAsDirty();
} }
break; break;
case kMapCmd: case kMapCmd:
@ -105,11 +105,11 @@ void KeysDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
_actionTitle->setLabel(_("Press the key to associate")); _actionTitle->setLabel(_("Press the key to associate"));
_keyMapping->setLabel(selection); _keyMapping->setLabel(selection);
_keyMapping->draw(); _keyMapping->markAsDirty();
Actions::Instance()->beginMapping(true); Actions::Instance()->beginMapping(true);
_actionsList->setEnabled(false); _actionsList->setEnabled(false);
} }
_actionTitle->draw(); _actionTitle->markAsDirty();
break; break;
case kOKCmd: case kOKCmd:
Actions::Instance()->saveMapping(); Actions::Instance()->saveMapping();
@ -144,8 +144,8 @@ void KeysDialog::handleKeyUp(Common::KeyState state) {
_actionTitle->setLabel(_("Choose an action to map")); _actionTitle->setLabel(_("Choose an action to map"));
_keyMapping->setLabel(selection); _keyMapping->setLabel(selection);
_keyMapping->draw(); _keyMapping->markAsDirty();
_actionTitle->draw(); _actionTitle->markAsDirty();
_actionSelected = -1; _actionSelected = -1;
_actionsList->setEnabled(true); _actionsList->setEnabled(true);
Actions::Instance()->beginMapping(false); Actions::Instance()->beginMapping(false);

File diff suppressed because it is too large Load diff

View file

@ -54,7 +54,6 @@ struct TextColorData;
class Dialog; class Dialog;
class GuiObject; class GuiObject;
class ThemeEval; class ThemeEval;
class ThemeItem;
class ThemeParser; class ThemeParser;
/** /**
@ -113,6 +112,18 @@ enum DrawData {
kDDNone = -1 kDDNone = -1
}; };
/**
* Dialog layers.
* The currently active dialog has two layers, background and foreground.
* The background layer is drawn to the backbuffer. The foreground layer
* is drawn to the screen. This allows draw calls to restore the background
* layer before redrawing a widget.
*/
enum DrawLayer {
kDrawLayerBackground,
kDrawLayerForeground
};
// FIXME: TextData is really a bad name, not conveying what this enum is about. // FIXME: TextData is really a bad name, not conveying what this enum is about.
enum TextData { enum TextData {
kTextDataNone = -1, kTextDataNone = -1,
@ -308,22 +319,38 @@ public:
const Graphics::PixelFormat getPixelFormat() const { return _overlayFormat; } const Graphics::PixelFormat getPixelFormat() const { return _overlayFormat; }
/** /**
* Implementation of the GUI::Theme API. Called when a * Draw full screen shading with the supplied style
* new dialog is opened. Note that the boolean parameter
* meaning has been changed.
* *
* @param enableBuffering If set to true, buffering is enabled for * This is used to dim the inactive dialogs so the active one stands out.
* drawing this dialog, and will continue enabled
* until disabled.
*/ */
void openDialog(bool enableBuffering, ShadingStyle shading = kShadingNone); void applyScreenShading(ShadingStyle shading);
/**
* Sets the active drawing surface to the back buffer.
*
* All drawing from this point on will be done on that surface.
* The back buffer surface needs to be copied to the screen surface
* in order to become visible.
*/
void drawToBackbuffer();
/**
* Sets the active drawing surface to the screen.
*
* All drawing from this point on will be done on that surface.
*/
void drawToScreen();
/** /**
* The updateScreen() method is called every frame. * The updateScreen() method is called every frame.
* It processes all the drawing queues and then copies dirty rects * It copies dirty rectangles in the Screen surface to the overlay.
* in the current Screen surface to the overlay.
*/ */
void updateScreen(bool render = true); void updateScreen();
/**
* Copy the entire backbuffer surface to the screen surface
*/
void copyBackBufferToScreen();
/** @name FONT MANAGEMENT METHODS */ /** @name FONT MANAGEMENT METHODS */
@ -425,8 +452,8 @@ public:
/** /**
* Actual implementation of a dirty rect handling. * Actual implementation of a dirty rect handling.
* Dirty rectangles are queued on a list and are later used for the * Dirty rectangles are queued on a list, merged and optimized
* actual drawing. * when possible and are later used for the actual drawing.
* *
* @param r Area of the dirty rect. * @param r Area of the dirty rect.
*/ */
@ -534,13 +561,6 @@ protected:
void setGraphicsMode(GraphicsMode mode); void setGraphicsMode(GraphicsMode mode);
public: public:
/**
* Finishes buffering: widgets from then on will be drawn straight on the screen
* without drawing queues.
*/
inline void finishBuffering() { _buffering = false; }
inline void startBuffering() { _buffering = true; }
inline ThemeEval *getEvaluator() { return _themeEval; } inline ThemeEval *getEvaluator() { return _themeEval; }
inline Graphics::VectorRenderer *renderer() { return _vectorRenderer; } inline Graphics::VectorRenderer *renderer() { return _vectorRenderer; }
@ -623,33 +643,35 @@ protected:
const Graphics::Font *loadFont(const Common::String &filename, const Common::String &scalableFilename, const Common::String &charset, const int pointsize, const bool makeLocalizedFont); const Graphics::Font *loadFont(const Common::String &filename, const Common::String &scalableFilename, const Common::String &charset, const int pointsize, const bool makeLocalizedFont);
/** /**
* Actual Dirty Screen handling function. * Dirty Screen handling function.
* Handles all the dirty squares in the list, merges and optimizes * Draws all the dirty rectangles in the list to the overlay.
* them when possible and draws them to the screen.
* Called from updateScreen()
*/ */
void renderDirtyScreen(); void updateDirtyScreen();
/** /**
* Generates a DrawQueue item and enqueues it so it's drawn to the screen * Draws a GUI element according to a DrawData descriptor.
* when the drawing queue is processed.
* *
* If Buffering is enabled, the DrawQueue item will be automatically placed * Only calls with a DrawData layer attribute matching the active layer
* on its corresponding queue. * are actually drawn to the active surface.
* If Buffering is disabled, the DrawQueue item will be processed immediately
* and drawn to the screen.
* *
* This function is called from all the Widget Drawing methods. * These functions are called from all the Widget drawing methods.
*/ */
void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0, bool restore = false); void drawDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0, bool forceRestore = false);
void queueDDClip(DrawData type, const Common::Rect &r, const Common::Rect &clippingRect, uint32 dynamic = 0, bool restore = false); void drawDDClip(DrawData type, const Common::Rect &r, const Common::Rect &clippingRect, uint32 dynamic = 0,
void queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg, bool forceRestore = false);
bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0)); void drawDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg,
void queueDDTextClip(TextData type, TextColor color, const Common::Rect &r, const Common::Rect &clippingRect, const Common::String &text, bool restoreBg, bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft,
bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0)); TextAlignVertical alignV = kTextAlignVTop, int deltax = 0,
void queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha); const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
void queueBitmapClip(const Graphics::Surface *bitmap, const Common::Rect &clippingRect, const Common::Rect &r, bool alpha); void drawDDTextClip(TextData type, TextColor color, const Common::Rect &r, const Common::Rect &clippingRect,
void queueABitmap(Graphics::TransparentSurface *bitmap, const Common::Rect &r, AutoScaleMode autoscale, int alpha); const Common::String &text, bool restoreBg,
bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft,
TextAlignVertical alignV = kTextAlignVTop, int deltax = 0,
const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0));
void drawBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha);
void drawBitmapClip(const Graphics::Surface *bitmap, const Common::Rect &clippingRect, const Common::Rect &r,
bool alpha);
void drawABitmap(Graphics::TransparentSurface *bitmap, const Common::Rect &r, AutoScaleMode autoscale, int alpha);
/** /**
* DEBUG: Draws a white square and writes some text next to it. * DEBUG: Draws a white square and writes some text next to it.
@ -695,9 +717,13 @@ protected:
/** Backbuffer surface. Stores previous states of the screen to blit back */ /** Backbuffer surface. Stores previous states of the screen to blit back */
Graphics::TransparentSurface _backBuffer; Graphics::TransparentSurface _backBuffer;
/** Sets whether the current drawing is being buffered (stored for later /**
processing) or drawn directly to the screen. */ * Filter the submitted DrawData descriptors according to their layer attribute
bool _buffering; *
* This is used to selectively draw the background or foreground layer
* of the dialogs.
*/
DrawLayer _layerToDraw;
/** Bytes per pixel of the Active Drawing Surface (i.e. the screen) */ /** Bytes per pixel of the Active Drawing Surface (i.e. the screen) */
int _bytesPerPixel; int _bytesPerPixel;
@ -731,12 +757,6 @@ protected:
/** List of all the dirty screens that must be blitted to the overlay. */ /** List of all the dirty screens that must be blitted to the overlay. */
Common::List<Common::Rect> _dirtyScreen; Common::List<Common::Rect> _dirtyScreen;
/** Queue with all the drawing that must be done to the Back Buffer */
Common::List<ThemeItem *> _bufferQueue;
/** Queue with all the drawing that must be done to the screen */
Common::List<ThemeItem *> _screenQueue;
bool _initOk; ///< Class and renderer properly initialized bool _initOk; ///< Class and renderer properly initialized
bool _themeOk; ///< Theme data successfully loaded. bool _themeOk; ///< Theme data successfully loaded.
bool _enabled; ///< Whether the Theme is currently shown on the overlay bool _enabled; ///< Whether the Theme is currently shown on the overlay

View file

@ -56,11 +56,11 @@ void Tooltip::setup(Dialog *parent, Widget *widget, int x, int y) {
_y = MIN<int16>(parent->_y + y + _ydelta, g_gui.getHeight() - _h - 3); _y = MIN<int16>(parent->_y + y + _ydelta, g_gui.getHeight() - _h - 3);
} }
void Tooltip::drawDialog() { void Tooltip::drawDialog(DrawLayer layerToDraw) {
int num = 0; int num = 0;
int h = g_gui.theme()->getFontHeight(ThemeEngine::kFontStyleTooltip) + 2; int h = g_gui.theme()->getFontHeight(ThemeEngine::kFontStyleTooltip) + 2;
Dialog::drawDialog(); Dialog::drawDialog(layerToDraw);
for (Common::StringArray::const_iterator i = _wrappedLines.begin(); i != _wrappedLines.end(); ++i, ++num) { for (Common::StringArray::const_iterator i = _wrappedLines.begin(); i != _wrappedLines.end(); ++i, ++num) {
g_gui.theme()->drawText( g_gui.theme()->drawText(

View file

@ -40,7 +40,7 @@ public:
void setup(Dialog *parent, Widget *widget, int x, int y); void setup(Dialog *parent, Widget *widget, int x, int y);
void drawDialog(); void drawDialog(DrawLayer layerToDraw) override;
virtual void receivedFocus(int x = -1, int y = -1) {} virtual void receivedFocus(int x = -1, int y = -1) {}
protected: protected:

View file

@ -110,16 +110,16 @@ AboutDialog::AboutDialog()
engines += _("Available engines:"); engines += _("Available engines:");
addLine(engines.c_str()); addLine(engines.c_str());
const EnginePlugin::List &plugins = EngineMan.getPlugins(); const PluginList &plugins = EngineMan.getPlugins();
EnginePlugin::List::const_iterator iter = plugins.begin(); PluginList::const_iterator iter = plugins.begin();
for (; iter != plugins.end(); ++iter) { for (; iter != plugins.end(); ++iter) {
Common::String str; Common::String str;
str = "C0"; str = "C0";
str += (**iter).getName(); str += (*iter)->getName();
addLine(str.c_str()); addLine(str.c_str());
str = "C2"; str = "C2";
str += (**iter)->getOriginalCopyright(); str += (*iter)->get<MetaEngine>().getOriginalCopyright();
addLine(str.c_str()); addLine(str.c_str());
//addLine(""); //addLine("");
@ -180,8 +180,8 @@ void AboutDialog::close() {
Dialog::close(); Dialog::close();
} }
void AboutDialog::drawDialog() { void AboutDialog::drawDialog(DrawLayer layerToDraw) {
Dialog::drawDialog(); Dialog::drawDialog(layerToDraw);
setTextDrawableArea(Common::Rect(_x, _y, _x + _w, _y + _h)); setTextDrawableArea(Common::Rect(_x, _y, _x + _w, _y + _h));
@ -268,7 +268,7 @@ void AboutDialog::handleTickle() {
_scrollPos = 0; _scrollPos = 0;
_scrollTime += kScrollStartDelay; _scrollTime += kScrollStartDelay;
} }
drawDialog(); drawDialog(kDrawLayerForeground);
} }
} }

View file

@ -48,7 +48,7 @@ public:
void open(); void open();
void close(); void close();
void drawDialog(); void drawDialog(DrawLayer layerToDraw) override;
void handleTickle(); void handleTickle();
void handleMouseUp(int x, int y, int button, int clickCount); void handleMouseUp(int x, int y, int button, int clickCount);
void handleKeyDown(Common::KeyState state); void handleKeyDown(Common::KeyState state);

View file

@ -21,6 +21,7 @@
*/ */
#include "gui/browser.h" #include "gui/browser.h"
#include "gui/gui-manager.h"
#include "gui/widgets/list.h" #include "gui/widgets/list.h"
#include "common/config-manager.h" #include "common/config-manager.h"
@ -191,7 +192,7 @@ void BrowserDialog::updateListing() {
_fileList->scrollTo(0); _fileList->scrollTo(0);
// Finally, redraw // Finally, redraw
draw(); g_gui.scheduleTopDialogRedraw();
} }
} // End of namespace GUI } // End of namespace GUI

View file

@ -64,7 +64,7 @@ void ChooserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
break; break;
case kListSelectionChangedCmd: case kListSelectionChangedCmd:
_chooseButton->setEnabled(item >= 0); _chooseButton->setEnabled(item >= 0);
_chooseButton->draw(); _chooseButton->markAsDirty();
break; break;
case kCloseCmd: case kCloseCmd:
setResult(-1); setResult(-1);

View file

@ -163,17 +163,11 @@ void ConsoleDialog::close() {
Dialog::close(); Dialog::close();
} }
void ConsoleDialog::drawDialog() { void ConsoleDialog::drawDialog(DrawLayer layerToDraw) {
g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x + _w, _y + _h), ThemeEngine::kDialogBackgroundPlain/*_backgroundType*/); Dialog::drawDialog(layerToDraw);
// FIXME: for the old theme the frame around the console vanishes
// when any action is processed if we enable this
// _drawingHints &= ~THEME_HINT_FIRST_DRAW;
for (int line = 0; line < _linesPerPage; line++) for (int line = 0; line < _linesPerPage; line++)
drawLine(line, false); drawLine(line, false);
// Draw the scrollbar
_scrollBar->draw();
} }
void ConsoleDialog::drawLine(int line, bool restoreBg) { void ConsoleDialog::drawLine(int line, bool restoreBg) {
@ -187,7 +181,6 @@ void ConsoleDialog::drawLine(int line, bool restoreBg) {
if (restoreBg) { if (restoreBg) {
Common::Rect r(_x, y - 2, _x + _pageWidth * kConsoleCharWidth, y+kConsoleLineHeight); Common::Rect r(_x, y - 2, _x + _pageWidth * kConsoleCharWidth, y+kConsoleLineHeight);
g_gui.theme()->restoreBackground(r); g_gui.theme()->restoreBackground(r);
g_gui.theme()->addDirtyRect(r);
} }
for (int column = 0; column < limit; column++) { for (int column = 0; column < limit; column++) {
@ -200,8 +193,6 @@ void ConsoleDialog::drawLine(int line, bool restoreBg) {
g_gui.theme()->drawChar(Common::Rect(x, y, x+kConsoleCharWidth, y+kConsoleLineHeight), c, _font); g_gui.theme()->drawChar(Common::Rect(x, y, x+kConsoleCharWidth, y+kConsoleLineHeight), c, _font);
x += kConsoleCharWidth; x += kConsoleCharWidth;
} }
g_gui.theme()->updateScreen();
} }
void ConsoleDialog::reflowLayout() { void ConsoleDialog::reflowLayout() {
@ -213,7 +204,7 @@ void ConsoleDialog::reflowLayout() {
updateScrollBuffer(); updateScrollBuffer();
Dialog::reflowLayout(); Dialog::reflowLayout();
draw(); g_gui.scheduleTopDialogRedraw();
} }
void ConsoleDialog::handleTickle() { void ConsoleDialog::handleTickle() {
@ -236,13 +227,13 @@ void ConsoleDialog::handleTickle() {
// End the slide // End the slide
_slideMode = kNoSlideMode; _slideMode = kNoSlideMode;
_y = 0; _y = 0;
draw(); g_gui.scheduleTopDialogRedraw();
} else if (_slideMode == kUpSlideMode && _y <= -_h) { } else if (_slideMode == kUpSlideMode && _y <= -_h) {
// End the slide // End the slide
//_slideMode = kNoSlideMode; //_slideMode = kNoSlideMode;
close(); close();
} else } else
draw(); g_gui.scheduleTopDialogRedraw();
} }
_scrollBar->handleTickle(); _scrollBar->handleTickle();
@ -291,7 +282,7 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) {
print(PROMPT); print(PROMPT);
_promptStartPos = _promptEndPos = _currentPos; _promptStartPos = _promptEndPos = _currentPos;
draw(); g_gui.scheduleTopDialogRedraw();
if (!keepRunning) if (!keepRunning)
slideUpAndClose(); slideUpAndClose();
break; break;
@ -376,7 +367,7 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) {
} else { } else {
_currentPos = _promptEndPos; _currentPos = _promptEndPos;
} }
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case Common::KEYCODE_KP2: case Common::KEYCODE_KP2:
@ -404,7 +395,7 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) {
_scrollLine = _firstLineInBuffer + _linesPerPage - 1; _scrollLine = _firstLineInBuffer + _linesPerPage - 1;
} }
updateScrollBuffer(); updateScrollBuffer();
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
@ -445,7 +436,7 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) {
} else { } else {
_currentPos = _promptStartPos; _currentPos = _promptStartPos;
} }
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case Common::KEYCODE_KP8: case Common::KEYCODE_KP8:
@ -470,7 +461,7 @@ void ConsoleDialog::handleKeyDown(Common::KeyState state) {
if (_scrollLine < _firstLineInBuffer + _linesPerPage - 1) if (_scrollLine < _firstLineInBuffer + _linesPerPage - 1)
_scrollLine = _firstLineInBuffer + _linesPerPage - 1; _scrollLine = _firstLineInBuffer + _linesPerPage - 1;
updateScrollBuffer(); updateScrollBuffer();
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
@ -507,7 +498,7 @@ void ConsoleDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
int newPos = (int)data + _linesPerPage - 1 + _firstLineInBuffer; int newPos = (int)data + _linesPerPage - 1 + _firstLineInBuffer;
if (newPos != _scrollLine) { if (newPos != _scrollLine) {
_scrollLine = newPos; _scrollLine = newPos;
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
} }
@ -517,25 +508,25 @@ void ConsoleDialog::specialKeys(int keycode) {
switch (keycode) { switch (keycode) {
case Common::KEYCODE_a: case Common::KEYCODE_a:
_currentPos = _promptStartPos; _currentPos = _promptStartPos;
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case Common::KEYCODE_d: case Common::KEYCODE_d:
if (_currentPos < _promptEndPos) { if (_currentPos < _promptEndPos) {
killChar(); killChar();
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
case Common::KEYCODE_e: case Common::KEYCODE_e:
_currentPos = _promptEndPos; _currentPos = _promptEndPos;
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case Common::KEYCODE_k: case Common::KEYCODE_k:
killLine(); killLine();
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case Common::KEYCODE_w: case Common::KEYCODE_w:
killLastWord(); killLastWord();
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
} }
} }
@ -625,7 +616,7 @@ void ConsoleDialog::historyScroll(int direction) {
// Ensure once more the caret is visible (in case of very long history entries) // Ensure once more the caret is visible (in case of very long history entries)
scrollToCurrent(); scrollToCurrent();
draw(); g_gui.scheduleTopDialogRedraw();
} }
void ConsoleDialog::nextLine() { void ConsoleDialog::nextLine() {
@ -703,7 +694,7 @@ void ConsoleDialog::print(const char *str) {
while (*str) while (*str)
printCharIntern(*str++); printCharIntern(*str++);
draw(); g_gui.scheduleTopDialogRedraw();
} }
void ConsoleDialog::drawCaret(bool erase) { void ConsoleDialog::drawCaret(bool erase) {
@ -732,7 +723,7 @@ void ConsoleDialog::scrollToCurrent() {
} else if (line > _scrollLine) { } else if (line > _scrollLine) {
_scrollLine = line; _scrollLine = line;
updateScrollBuffer(); updateScrollBuffer();
draw(); g_gui.scheduleTopDialogRedraw();
} }
} }

View file

@ -132,7 +132,7 @@ public:
void open(); void open();
void close(); void close();
void drawDialog(); void drawDialog(DrawLayer layerToDraw) override;
void handleTickle(); void handleTickle();
void reflowLayout(); void reflowLayout();

View file

@ -153,21 +153,31 @@ void Dialog::releaseFocus() {
} }
} }
void Dialog::draw() { void Dialog::markWidgetsAsDirty() {
//TANOKU - FIXME when is this enabled? what does this do? Widget *w = _firstWidget;
// Update: called on tab drawing, mainly... while (w) {
// we can pass this as open a new dialog or something w->markAsDirty();
// g_gui._needRedraw = true; w = w->_next;
g_gui._redrawStatus = GUI::GuiManager::kRedrawTopDialog; }
} }
void Dialog::drawDialog() { void Dialog::drawDialog(DrawLayer layerToDraw) {
if (!isVisible()) if (!isVisible())
return; return;
g_gui.theme()->_layerToDraw = layerToDraw;
g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _backgroundType); g_gui.theme()->drawDialogBackground(Common::Rect(_x, _y, _x+_w, _y+_h), _backgroundType);
markWidgetsAsDirty();
drawWidgets();
}
void Dialog::drawWidgets() {
if (!isVisible())
return;
// Draw all children // Draw all children
Widget *w = _firstWidget; Widget *w = _firstWidget;
while (w) { while (w) {

View file

@ -88,8 +88,14 @@ protected:
virtual void open(); virtual void open();
virtual void close(); virtual void close();
virtual void draw(); /** Recursively mark all the widgets in this dialog as dirty so they are redrawn */
virtual void drawDialog(); void markWidgetsAsDirty();
/** Draw the dialog in its entirety (background and widgets) */
virtual void drawDialog(DrawLayer layerToDraw);
/** Draw only the dialog's widgets */
void drawWidgets();
virtual void handleTickle(); // Called periodically (in every guiloop() ) virtual void handleTickle(); // Called periodically (in every guiloop() )
virtual void handleMouseDown(int x, int y, int button, int clickCount); virtual void handleMouseDown(int x, int y, int button, int clickCount);

View file

@ -29,6 +29,7 @@
#include "gui/browser.h" #include "gui/browser.h"
#include "gui/chooser.h" #include "gui/chooser.h"
#include "gui/editgamedialog.h" #include "gui/editgamedialog.h"
#include "gui/gui-manager.h"
#include "gui/launcher.h" #include "gui/launcher.h"
#include "gui/message.h" #include "gui/message.h"
#include "gui/remotebrowser.h" #include "gui/remotebrowser.h"
@ -81,7 +82,7 @@ void DownloadDialog::open() {
if (!selectDirectories()) if (!selectDirectories())
close(); close();
reflowLayout(); reflowLayout();
draw(); g_gui.scheduleTopDialogRedraw();
} }
void DownloadDialog::close() { void DownloadDialog::close() {
@ -101,7 +102,7 @@ void DownloadDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
case kDownloadProgressCmd: case kDownloadProgressCmd:
if (!_close) { if (!_close) {
refreshWidgets(); refreshWidgets();
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
case kDownloadEndedCmd: case kDownloadEndedCmd:
@ -196,7 +197,7 @@ void DownloadDialog::handleTickle() {
int32 progress = (int32)(100 * CloudMan.getDownloadingProgress()); int32 progress = (int32)(100 * CloudMan.getDownloadingProgress());
if (_progressBar->getValue() != progress) { if (_progressBar->getValue() != progress) {
refreshWidgets(); refreshWidgets();
draw(); g_gui.scheduleTopDialogRedraw();
} }
Dialog::handleTickle(); Dialog::handleTickle();

View file

@ -28,6 +28,7 @@
#include "common/system.h" #include "common/system.h"
#include "gui/browser.h" #include "gui/browser.h"
#include "gui/gui-manager.h"
#include "gui/message.h" #include "gui/message.h"
#ifdef ENABLE_EVENTRECORDER #ifdef ENABLE_EVENTRECORDER
#include "gui/onscreendialog.h" #include "gui/onscreendialog.h"
@ -97,7 +98,7 @@ protected:
EditGameDialog::EditGameDialog(const String &domain, const String &desc) EditGameDialog::EditGameDialog(const String &domain, const String &desc)
: OptionsDialog(domain, "GameOptions") { : OptionsDialog(domain, "GameOptions") {
// Retrieve all game specific options. // Retrieve all game specific options.
const EnginePlugin *plugin = 0; const Plugin *plugin = nullptr;
// To allow for game domains without a gameid. // To allow for game domains without a gameid.
// TODO: Is it intentional that this is still supported? // TODO: Is it intentional that this is still supported?
String gameId(ConfMan.get("gameid", domain)); String gameId(ConfMan.get("gameid", domain));
@ -107,7 +108,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
// implementation. // implementation.
EngineMan.findGame(gameId, &plugin); EngineMan.findGame(gameId, &plugin);
if (plugin) { if (plugin) {
_engineOptions = (*plugin)->getExtraGuiOptions(domain); _engineOptions = plugin->get<MetaEngine>().getExtraGuiOptions(domain);
} else { } else {
warning("Plugin for target \"%s\" not found! Game specific settings might be missing", domain.c_str()); warning("Plugin for target \"%s\" not found! Game specific settings might be missing", domain.c_str());
} }
@ -424,26 +425,26 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
switch (cmd) { switch (cmd) {
case kCmdGlobalGraphicsOverride: case kCmdGlobalGraphicsOverride:
setGraphicSettingsState(data != 0); setGraphicSettingsState(data != 0);
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case kCmdGlobalAudioOverride: case kCmdGlobalAudioOverride:
setAudioSettingsState(data != 0); setAudioSettingsState(data != 0);
setSubtitleSettingsState(data != 0); setSubtitleSettingsState(data != 0);
if (_globalVolumeOverride == NULL) if (_globalVolumeOverride == NULL)
setVolumeSettingsState(data != 0); setVolumeSettingsState(data != 0);
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case kCmdGlobalMIDIOverride: case kCmdGlobalMIDIOverride:
setMIDISettingsState(data != 0); setMIDISettingsState(data != 0);
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case kCmdGlobalMT32Override: case kCmdGlobalMT32Override:
setMT32SettingsState(data != 0); setMT32SettingsState(data != 0);
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case kCmdGlobalVolumeOverride: case kCmdGlobalVolumeOverride:
setVolumeSettingsState(data != 0); setVolumeSettingsState(data != 0);
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case kCmdChooseSoundFontCmd: case kCmdChooseSoundFontCmd:
{ {
@ -459,7 +460,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
else else
_soundFontClearButton->setEnabled(false); _soundFontClearButton->setEnabled(false);
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
} }
@ -477,9 +478,9 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
// FSList files = dir.listDir(FSNode::kListFilesOnly); // FSList files = dir.listDir(FSNode::kListFilesOnly);
_gamePathWidget->setLabel(dir.getPath()); _gamePathWidget->setLabel(dir.getPath());
draw(); g_gui.scheduleTopDialogRedraw();
} }
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
} }
@ -491,9 +492,9 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
// User made his choice... // User made his choice...
Common::FSNode dir(browser.getResult()); Common::FSNode dir(browser.getResult());
_extraPathWidget->setLabel(dir.getPath()); _extraPathWidget->setLabel(dir.getPath());
draw(); g_gui.scheduleTopDialogRedraw();
} }
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
} }
// Change path for stored save game (perm and temp) data // Change path for stored save game (perm and temp) data
@ -508,9 +509,9 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
MessageDialog warningMessage(_("Saved games sync feature doesn't work with non-default directories. If you want your saved games to sync, use default directory.")); MessageDialog warningMessage(_("Saved games sync feature doesn't work with non-default directories. If you want your saved games to sync, use default directory."));
warningMessage.runModal(); warningMessage.runModal();
#endif #endif
draw(); g_gui.scheduleTopDialogRedraw();
} }
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
} }

View file

@ -30,6 +30,7 @@
#include "common/translation.h" #include "common/translation.h"
#include "gui/widgets/list.h" #include "gui/widgets/list.h"
#include "gui/gui-manager.h"
#include "gui/message.h" #include "gui/message.h"
namespace GUI { namespace GUI {
@ -88,7 +89,7 @@ void FileBrowserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32
break; break;
case kListSelectionChangedCmd: case kListSelectionChangedCmd:
_fileName->setEditString(_fileList->getList().operator[](_fileList->getSelected()).c_str()); _fileName->setEditString(_fileList->getList().operator[](_fileList->getSelected()).c_str());
_fileName->draw(); _fileName->markAsDirty();
break; break;
case kListItemActivatedCmd: case kListItemActivatedCmd:
case kListItemDoubleClickedCmd: case kListItemDoubleClickedCmd:
@ -154,7 +155,7 @@ void FileBrowserDialog::updateListing() {
_fileList->scrollTo(0); _fileList->scrollTo(0);
// Finally, redraw // Finally, redraw
draw(); g_gui.scheduleTopDialogRedraw();
} }
} // End of namespace GUI } // End of namespace GUI

View file

@ -21,6 +21,7 @@
*/ */
#include "gui/fluidsynth-dialog.h" #include "gui/fluidsynth-dialog.h"
#include "gui/gui-manager.h"
#include "gui/message.h" #include "gui/message.h"
#include "gui/widgets/tab.h" #include "gui/widgets/tab.h"
#include "gui/widgets/popup.h" #include "gui/widgets/popup.h"
@ -180,45 +181,45 @@ void FluidSynthSettingsDialog::handleCommand(CommandSender *sender, uint32 cmd,
break; break;
case kChorusVoiceCountChangedCmd: case kChorusVoiceCountChangedCmd:
_chorusVoiceCountLabel->setLabel(Common::String::format("%d", _chorusVoiceCountSlider->getValue())); _chorusVoiceCountLabel->setLabel(Common::String::format("%d", _chorusVoiceCountSlider->getValue()));
_chorusVoiceCountLabel->draw(); _chorusVoiceCountLabel->markAsDirty();
break; break;
case kChorusLevelChangedCmd: case kChorusLevelChangedCmd:
_chorusLevelLabel->setLabel(Common::String::format("%d", _chorusLevelSlider->getValue())); _chorusLevelLabel->setLabel(Common::String::format("%d", _chorusLevelSlider->getValue()));
_chorusLevelLabel->draw(); _chorusLevelLabel->markAsDirty();
break; break;
case kChorusSpeedChangedCmd: case kChorusSpeedChangedCmd:
_chorusSpeedLabel->setLabel(Common::String::format("%d", _chorusSpeedSlider->getValue())); _chorusSpeedLabel->setLabel(Common::String::format("%d", _chorusSpeedSlider->getValue()));
_chorusSpeedLabel->draw(); _chorusSpeedLabel->markAsDirty();
break; break;
case kChorusDepthChangedCmd: case kChorusDepthChangedCmd:
_chorusDepthLabel->setLabel(Common::String::format("%d", _chorusDepthSlider->getValue())); _chorusDepthLabel->setLabel(Common::String::format("%d", _chorusDepthSlider->getValue()));
_chorusDepthLabel->draw(); _chorusDepthLabel->markAsDirty();
break; break;
case kActivateReverbCmd: case kActivateReverbCmd:
setReverbSettingsState(data); setReverbSettingsState(data);
break; break;
case kReverbRoomSizeChangedCmd: case kReverbRoomSizeChangedCmd:
_reverbRoomSizeLabel->setLabel(Common::String::format("%d", _reverbRoomSizeSlider->getValue())); _reverbRoomSizeLabel->setLabel(Common::String::format("%d", _reverbRoomSizeSlider->getValue()));
_reverbRoomSizeLabel->draw(); _reverbRoomSizeLabel->markAsDirty();
break; break;
case kReverbDampingChangedCmd: case kReverbDampingChangedCmd:
_reverbDampingLabel->setLabel(Common::String::format("%d", _reverbDampingSlider->getValue())); _reverbDampingLabel->setLabel(Common::String::format("%d", _reverbDampingSlider->getValue()));
_reverbDampingLabel->draw(); _reverbDampingLabel->markAsDirty();
break; break;
case kReverbWidthChangedCmd: case kReverbWidthChangedCmd:
_reverbWidthLabel->setLabel(Common::String::format("%d", _reverbWidthSlider->getValue())); _reverbWidthLabel->setLabel(Common::String::format("%d", _reverbWidthSlider->getValue()));
_reverbWidthLabel->draw(); _reverbWidthLabel->markAsDirty();
break; break;
case kReverbLevelChangedCmd: case kReverbLevelChangedCmd:
_reverbLevelLabel->setLabel(Common::String::format("%d", _reverbLevelSlider->getValue())); _reverbLevelLabel->setLabel(Common::String::format("%d", _reverbLevelSlider->getValue()));
_reverbLevelLabel->draw(); _reverbLevelLabel->markAsDirty();
break; break;
case kResetSettingsCmd: { case kResetSettingsCmd: {
MessageDialog alert(_("Do you really want to reset all FluidSynth settings to their default values?"), _("Yes"), _("No")); MessageDialog alert(_("Do you really want to reset all FluidSynth settings to their default values?"), _("Yes"), _("No"));
if (alert.runModal() == GUI::kMessageOK) { if (alert.runModal() == GUI::kMessageOK) {
resetSettings(); resetSettings();
readSettings(); readSettings();
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
} }

View file

@ -208,7 +208,7 @@ bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx,
void GuiManager::redraw() { void GuiManager::redraw() {
ThemeEngine::ShadingStyle shading; ThemeEngine::ShadingStyle shading;
if (_redrawStatus == kRedrawDisabled || _dialogStack.empty()) if (_dialogStack.empty())
return; return;
shading = (ThemeEngine::ShadingStyle)xmlEval()->getVar("Dialog." + _dialogStack.top()->_name + ".Shading", 0); shading = (ThemeEngine::ShadingStyle)xmlEval()->getVar("Dialog." + _dialogStack.top()->_name + ".Shading", 0);
@ -224,26 +224,43 @@ void GuiManager::redraw() {
case kRedrawFull: case kRedrawFull:
case kRedrawTopDialog: case kRedrawTopDialog:
_theme->clearAll(); _theme->clearAll();
_theme->openDialog(true, ThemeEngine::kShadingNone); _theme->drawToBackbuffer();
for (DialogStack::size_type i = 0; i < _dialogStack.size() - 1; i++) for (DialogStack::size_type i = 0; i < _dialogStack.size() - 1; i++) {
_dialogStack[i]->drawDialog(); _dialogStack[i]->drawDialog(kDrawLayerBackground);
_dialogStack[i]->drawDialog(kDrawLayerForeground);
_theme->finishBuffering(); }
// fall through // fall through
case kRedrawOpenDialog: case kRedrawOpenDialog:
_theme->updateScreen(false); // This case is an optimization to avoid redrawing the whole dialog
_theme->openDialog(true, shading); // stack when opening a new dialog.
_dialogStack.top()->drawDialog();
_theme->finishBuffering(); _theme->drawToBackbuffer();
if (_redrawStatus == kRedrawOpenDialog && _dialogStack.size() > 1) {
Dialog *previousDialog = _dialogStack[_dialogStack.size() - 2];
previousDialog->drawDialog(kDrawLayerForeground);
}
_theme->applyScreenShading(shading);
_dialogStack.top()->drawDialog(kDrawLayerBackground);
_theme->drawToScreen();
_theme->copyBackBufferToScreen();
_dialogStack.top()->drawDialog(kDrawLayerForeground);
break; break;
default: default:
return; break;
} }
// Redraw the widgets that are marked as dirty
_theme->drawToScreen();
_dialogStack.top()->drawWidgets();
_theme->updateScreen(); _theme->updateScreen();
_redrawStatus = kRedrawDisabled; _redrawStatus = kRedrawDisabled;
} }
@ -299,11 +316,10 @@ void GuiManager::runLoop() {
} }
Common::EventManager *eventMan = _system->getEventManager(); Common::EventManager *eventMan = _system->getEventManager();
uint32 lastRedraw = 0; const uint32 targetFrameDuration = 1000 / 60;
const uint32 waitTime = 1000 / 60;
while (!_dialogStack.empty() && activeDialog == getTopDialog() && !eventMan->shouldQuit()) { while (!_dialogStack.empty() && activeDialog == getTopDialog() && !eventMan->shouldQuit()) {
redraw(); uint32 frameStartTime = _system->getMillis(true);
// Don't "tickle" the dialog until the theme has had a chance // Don't "tickle" the dialog until the theme has had a chance
// to re-allocate buffers in case of a scaler change. // to re-allocate buffers in case of a scaler change.
@ -312,14 +328,6 @@ void GuiManager::runLoop() {
if (_useStdCursor) if (_useStdCursor)
animateCursor(); animateCursor();
// _theme->updateScreen();
// _system->updateScreen();
if (lastRedraw + waitTime < _system->getMillis(true)) {
lastRedraw = _system->getMillis(true);
_theme->updateScreen();
_system->updateScreen();
}
Common::Event event; Common::Event event;
@ -349,13 +357,6 @@ void GuiManager::runLoop() {
} }
processEvent(event, activeDialog); processEvent(event, activeDialog);
if (lastRedraw + waitTime < _system->getMillis(true)) {
lastRedraw = _system->getMillis(true);
_theme->updateScreen();
_system->updateScreen();
}
} }
// Delete GuiObject that have been added to the trash for a delayed deletion // Delete GuiObject that have been added to the trash for a delayed deletion
@ -379,8 +380,14 @@ void GuiManager::runLoop() {
} }
} }
// Delay for a moment redraw();
_system->delayMillis(10);
// Delay until the allocated frame time is elapsed to match the target frame rate
uint32 actualFrameDuration = _system->getMillis(true) - frameStartTime;
if (actualFrameDuration < targetFrameDuration) {
_system->delayMillis(targetFrameDuration - actualFrameDuration);
}
_system->updateScreen();
} }
// WORKAROUND: When quitting we might not properly close the dialogs on // WORKAROUND: When quitting we might not properly close the dialogs on
@ -597,10 +604,8 @@ void GuiManager::processEvent(const Common::Event &event, Dialog *const activeDi
} }
} }
void GuiManager::doFullRedraw() { void GuiManager::scheduleTopDialogRedraw() {
_redrawStatus = kRedrawFull; _redrawStatus = kRedrawTopDialog;
redraw();
_system->updateScreen();
} }
void GuiManager::giveFocusToDialog(Dialog *dialog) { void GuiManager::giveFocusToDialog(Dialog *dialog) {

View file

@ -75,7 +75,7 @@ public:
void runLoop(); void runLoop();
void processEvent(const Common::Event &event, Dialog *const activeDialog); void processEvent(const Common::Event &event, Dialog *const activeDialog);
void doFullRedraw(); void scheduleTopDialogRedraw();
bool isActive() const { return ! _dialogStack.empty(); } bool isActive() const { return ! _dialogStack.empty(); }

View file

@ -323,7 +323,7 @@ void LauncherDialog::addGame() {
selectTarget(newTarget); selectTarget(newTarget);
} }
draw(); g_gui.scheduleTopDialogRedraw();
} }
// We need to update the buttons here, so "Mass add" will revert to "Add game" // We need to update the buttons here, so "Mass add" will revert to "Add game"
@ -427,7 +427,7 @@ void LauncherDialog::removeGame(int item) {
// Update the ListWidget and force a redraw // Update the ListWidget and force a redraw
updateListing(); updateListing();
draw(); g_gui.scheduleTopDialogRedraw();
} }
} }
@ -452,7 +452,7 @@ void LauncherDialog::editGame(int item) {
// Update the ListWidget, reselect the edited game and force a redraw // Update the ListWidget, reselect the edited game and force a redraw
updateListing(); updateListing();
selectTarget(editDialog.getDomain()); selectTarget(editDialog.getDomain());
draw(); g_gui.scheduleTopDialogRedraw();
} }
} }
@ -504,7 +504,7 @@ void LauncherDialog::loadGame(int item) {
if (gameId.empty()) if (gameId.empty())
gameId = _domains[item]; gameId = _domains[item];
const EnginePlugin *plugin = 0; const Plugin *plugin = nullptr;
EngineMan.findGame(gameId, &plugin); EngineMan.findGame(gameId, &plugin);
@ -512,8 +512,9 @@ void LauncherDialog::loadGame(int item) {
target.toLowercase(); target.toLowercase();
if (plugin) { if (plugin) {
if ((*plugin)->hasFeature(MetaEngine::kSupportsListSaves) && const MetaEngine &metaEngine = plugin->get<MetaEngine>();
(*plugin)->hasFeature(MetaEngine::kSupportsLoadingDuringStartup)) { if (metaEngine.hasFeature(MetaEngine::kSupportsListSaves) &&
metaEngine.hasFeature(MetaEngine::kSupportsLoadingDuringStartup)) {
int slot = _loadDialog->runModalWithPluginAndTarget(plugin, target); int slot = _loadDialog->runModalWithPluginAndTarget(plugin, target);
if (slot >= 0) { if (slot >= 0) {
ConfMan.setActiveDomain(_domains[item]); ConfMan.setActiveDomain(_domains[item]);
@ -613,7 +614,7 @@ bool LauncherDialog::doGameDetection(const Common::String &path) {
// Update the ListWidget, select the new item, and force a redraw // Update the ListWidget, select the new item, and force a redraw
updateListing(); updateListing();
selectTarget(editDialog.getDomain()); selectTarget(editDialog.getDomain());
draw(); g_gui.scheduleTopDialogRedraw();
} else { } else {
// User aborted, remove the the new domain again // User aborted, remove the the new domain again
ConfMan.removeGameDomain(domain); ConfMan.removeGameDomain(domain);
@ -687,15 +688,15 @@ void LauncherDialog::updateButtons() {
bool enable = (_list->getSelected() >= 0); bool enable = (_list->getSelected() >= 0);
if (enable != _startButton->isEnabled()) { if (enable != _startButton->isEnabled()) {
_startButton->setEnabled(enable); _startButton->setEnabled(enable);
_startButton->draw(); _startButton->markAsDirty();
} }
if (enable != _editButton->isEnabled()) { if (enable != _editButton->isEnabled()) {
_editButton->setEnabled(enable); _editButton->setEnabled(enable);
_editButton->draw(); _editButton->markAsDirty();
} }
if (enable != _removeButton->isEnabled()) { if (enable != _removeButton->isEnabled()) {
_removeButton->setEnabled(enable); _removeButton->setEnabled(enable);
_removeButton->draw(); _removeButton->markAsDirty();
} }
int item = _list->getSelected(); int item = _list->getSelected();
@ -706,7 +707,7 @@ void LauncherDialog::updateButtons() {
if (en != _loadButton->isEnabled()) { if (en != _loadButton->isEnabled()) {
_loadButton->setEnabled(en); _loadButton->setEnabled(en);
_loadButton->draw(); _loadButton->markAsDirty();
} }
switchButtonsText(_addButton, "~A~dd Game...", _s("Mass Add...")); switchButtonsText(_addButton, "~A~dd Game...", _s("Mass Add..."));
#ifdef ENABLE_EVENTRECORDER #ifdef ENABLE_EVENTRECORDER

View file

@ -274,7 +274,7 @@ void MassAddDialog::handleTickle() {
_list->scrollToEnd(); _list->scrollToEnd();
} }
drawDialog(); drawDialog(kDrawLayerForeground);
} }

View file

@ -30,7 +30,7 @@
namespace GUI { namespace GUI {
GuiObject::GuiObject(const Common::String &name) GuiObject::GuiObject(const Common::String &name)
: _x(-1000), _y(-1000), _w(0), _h(0), _name(name), _firstWidget(0), _textDrawableArea(Common::Rect(0, 0, 0, 0)) { : _x(-1000), _y(-1000), _w(0), _h(0), _name(name), _firstWidget(nullptr) {
reflowLayout(); reflowLayout();
} }

View file

@ -70,7 +70,7 @@ protected:
Widget *_firstWidget; Widget *_firstWidget;
public: public:
GuiObject(int x, int y, int w, int h) : _x(x), _y(y), _w(w), _h(h), _firstWidget(0), _textDrawableArea(Common::Rect(0, 0, 0, 0)) { } GuiObject(int x, int y, int w, int h) : _x(x), _y(y), _w(w), _h(h), _firstWidget(nullptr) { }
GuiObject(const Common::String &name); GuiObject(const Common::String &name);
~GuiObject(); ~GuiObject();
@ -87,8 +87,6 @@ public:
virtual bool isVisible() const = 0; virtual bool isVisible() const = 0;
virtual void draw() = 0;
virtual void reflowLayout(); virtual void reflowLayout();
virtual void removeWidget(Widget *widget); virtual void removeWidget(Widget *widget);

View file

@ -246,21 +246,17 @@ void OptionsDialog::build() {
} }
} }
if (g_system->hasFeature(OSystem::kFeatureKbdMouseSpeed)) { if (g_system->hasFeature(OSystem::kFeatureKbdMouseSpeed)) {
if (ConfMan.hasKey("kbdmouse_speed", _domain)) { int value = ConfMan.getInt("kbdmouse_speed", _domain);
int value = ConfMan.getInt("kbdmouse_speed", _domain); if (_kbdMouseSpeedSlider && value < ARRAYSIZE(kbdMouseSpeedLabels) - 1 && value >= 0) {
if (_kbdMouseSpeedSlider && value < ARRAYSIZE(kbdMouseSpeedLabels) - 1 && value >= 0) { _kbdMouseSpeedSlider->setValue(value);
_kbdMouseSpeedSlider->setValue(value); _kbdMouseSpeedLabel->setLabel(_(kbdMouseSpeedLabels[value]));
_kbdMouseSpeedLabel->setLabel(_(kbdMouseSpeedLabels[value]));
}
} }
} }
if (g_system->hasFeature(OSystem::kFeatureJoystickDeadzone)) { if (g_system->hasFeature(OSystem::kFeatureJoystickDeadzone)) {
if (ConfMan.hasKey("joystick_deadzone", _domain)) { int value = ConfMan.getInt("joystick_deadzone", _domain);
int value = ConfMan.getInt("joystick_deadzone", _domain); if (_joystickDeadzoneSlider != 0) {
if (_joystickDeadzoneSlider != 0) { _joystickDeadzoneSlider->setValue(value);
_joystickDeadzoneSlider->setValue(value); _joystickDeadzoneLabel->setValue(value);
_joystickDeadzoneLabel->setValue(value);
}
} }
} }
@ -743,12 +739,12 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
switch (cmd) { switch (cmd) {
case kMidiGainChanged: case kMidiGainChanged:
_midiGainLabel->setLabel(Common::String::format("%.2f", (double)_midiGainSlider->getValue() / 100.0)); _midiGainLabel->setLabel(Common::String::format("%.2f", (double)_midiGainSlider->getValue() / 100.0));
_midiGainLabel->draw(); _midiGainLabel->markAsDirty();
break; break;
case kMusicVolumeChanged: { case kMusicVolumeChanged: {
const int newValue = _musicVolumeSlider->getValue(); const int newValue = _musicVolumeSlider->getValue();
_musicVolumeLabel->setValue(newValue); _musicVolumeLabel->setValue(newValue);
_musicVolumeLabel->draw(); _musicVolumeLabel->markAsDirty();
if (_guioptions.contains(GUIO_LINKMUSICTOSFX)) { if (_guioptions.contains(GUIO_LINKMUSICTOSFX)) {
updateSfxVolume(newValue); updateSfxVolume(newValue);
@ -763,7 +759,7 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
case kSfxVolumeChanged: { case kSfxVolumeChanged: {
const int newValue = _sfxVolumeSlider->getValue(); const int newValue = _sfxVolumeSlider->getValue();
_sfxVolumeLabel->setValue(_sfxVolumeSlider->getValue()); _sfxVolumeLabel->setValue(_sfxVolumeSlider->getValue());
_sfxVolumeLabel->draw(); _sfxVolumeLabel->markAsDirty();
if (_guioptions.contains(GUIO_LINKMUSICTOSFX)) { if (_guioptions.contains(GUIO_LINKMUSICTOSFX)) {
updateMusicVolume(newValue); updateMusicVolume(newValue);
@ -778,7 +774,7 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
case kSpeechVolumeChanged: { case kSpeechVolumeChanged: {
const int newValue = _speechVolumeSlider->getValue(); const int newValue = _speechVolumeSlider->getValue();
_speechVolumeLabel->setValue(newValue); _speechVolumeLabel->setValue(newValue);
_speechVolumeLabel->draw(); _speechVolumeLabel->markAsDirty();
if (_guioptions.contains(GUIO_LINKSPEECHTOSFX)) { if (_guioptions.contains(GUIO_LINKSPEECHTOSFX)) {
updateSfxVolume(newValue); updateSfxVolume(newValue);
@ -802,25 +798,25 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
break; break;
case kSubtitleSpeedChanged: case kSubtitleSpeedChanged:
_subSpeedLabel->setValue(_subSpeedSlider->getValue()); _subSpeedLabel->setValue(_subSpeedSlider->getValue());
_subSpeedLabel->draw(); _subSpeedLabel->markAsDirty();
break; break;
case kClearSoundFontCmd: case kClearSoundFontCmd:
_soundFont->setLabel(_c("None", "soundfont")); _soundFont->setLabel(_c("None", "soundfont"));
_soundFontClearButton->setEnabled(false); _soundFontClearButton->setEnabled(false);
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case kKbdMouseSpeedChanged: case kKbdMouseSpeedChanged:
_kbdMouseSpeedLabel->setLabel(_(kbdMouseSpeedLabels[_kbdMouseSpeedSlider->getValue()])); _kbdMouseSpeedLabel->setLabel(_(kbdMouseSpeedLabels[_kbdMouseSpeedSlider->getValue()]));
_kbdMouseSpeedLabel->draw(); _kbdMouseSpeedLabel->markAsDirty();
break; break;
case kJoystickDeadzoneChanged: case kJoystickDeadzoneChanged:
_joystickDeadzoneLabel->setValue(_joystickDeadzoneSlider->getValue()); _joystickDeadzoneLabel->setValue(_joystickDeadzoneSlider->getValue());
_joystickDeadzoneLabel->draw(); _joystickDeadzoneLabel->markAsDirty();
break; break;
// ResidualVM specific // ResidualVM specific
case kFullscreenToggled: case kFullscreenToggled:
_aspectCheckbox->setEnabled(_fullscreenCheckbox->getState()); _aspectCheckbox->setEnabled(_fullscreenCheckbox->getState());
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case kApplyCmd: case kApplyCmd:
apply(); apply();
@ -848,12 +844,14 @@ void OptionsDialog::setGraphicSettingsState(bool enabled) {
_filteringCheckbox->setEnabled(enabled); _filteringCheckbox->setEnabled(enabled);
#endif #endif
#ifndef GUI_ENABLE_KEYSDIALOG #ifndef GUI_ENABLE_KEYSDIALOG
#ifndef GUI_ONLY_FULLSCREEN
_fullscreenCheckbox->setEnabled(enabled); _fullscreenCheckbox->setEnabled(enabled);
if (_guioptions.contains(GUIO_NOASPECT) || !_fullscreenCheckbox->getState()) if (_guioptions.contains(GUIO_NOASPECT) || !_fullscreenCheckbox->getState())
#endif // !GUI_ONLY_FULLSCREEN
_aspectCheckbox->setEnabled(false); _aspectCheckbox->setEnabled(false);
else else
_aspectCheckbox->setEnabled(enabled); _aspectCheckbox->setEnabled(enabled);
#endif #endif // !GUI_ENABLE_KEYSDIALOG
// ResidualVM specific: // ResidualVM specific:
_vsyncCheckbox->setEnabled(enabled); _vsyncCheckbox->setEnabled(enabled);
_rendererTypePopUp->setEnabled(enabled); _rendererTypePopUp->setEnabled(enabled);
@ -1096,9 +1094,9 @@ void OptionsDialog::addAudioControls(GuiObject *boss, const Common::String &pref
const Common::String allFlags = MidiDriver::musicType2GUIO((uint32)-1); const Common::String allFlags = MidiDriver::musicType2GUIO((uint32)-1);
bool hasMidiDefined = (strpbrk(_guioptions.c_str(), allFlags.c_str()) != NULL); bool hasMidiDefined = (strpbrk(_guioptions.c_str(), allFlags.c_str()) != NULL);
const MusicPlugin::List p = MusicMan.getPlugins(); const PluginList p = MusicMan.getPlugins();
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
Common::String deviceGuiOption = MidiDriver::musicType2GUIO(d->getMusicType()); Common::String deviceGuiOption = MidiDriver::musicType2GUIO(d->getMusicType());
@ -1135,19 +1133,19 @@ void OptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefi
_gmDevicePopUp = new PopUpWidget(boss, prefix + "auPrefGmPopup"); _gmDevicePopUp = new PopUpWidget(boss, prefix + "auPrefGmPopup");
// Populate // Populate
const MusicPlugin::List p = MusicMan.getPlugins(); const PluginList p = MusicMan.getPlugins();
// Make sure the null device is the first one in the list to avoid undesired // Make sure the null device is the first one in the list to avoid undesired
// auto detection for users who don't have a saved setting yet. // auto detection for users who don't have a saved setting yet.
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
if (d->getMusicDriverId() == "null") if (d->getMusicDriverId() == "null")
_gmDevicePopUp->appendEntry(_("Don't use General MIDI music"), d->getHandle()); _gmDevicePopUp->appendEntry(_("Don't use General MIDI music"), d->getHandle());
} }
} }
// Now we add the other devices. // Now we add the other devices.
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
if (d->getMusicType() >= MT_GM) { if (d->getMusicType() >= MT_GM) {
if (d->getMusicType() != MT_MT32) if (d->getMusicType() != MT_MT32)
@ -1199,19 +1197,19 @@ void OptionsDialog::addMT32Controls(GuiObject *boss, const Common::String &prefi
// GS Extensions setting // GS Extensions setting
_enableGSCheckbox = new CheckboxWidget(boss, prefix + "mcGSCheckbox", _("Roland GS Device (enable MT-32 mappings)"), _("Check if you want to enable patch mappings to emulate an MT-32 on a Roland GS device")); _enableGSCheckbox = new CheckboxWidget(boss, prefix + "mcGSCheckbox", _("Roland GS Device (enable MT-32 mappings)"), _("Check if you want to enable patch mappings to emulate an MT-32 on a Roland GS device"));
const MusicPlugin::List p = MusicMan.getPlugins(); const PluginList p = MusicMan.getPlugins();
// Make sure the null device is the first one in the list to avoid undesired // Make sure the null device is the first one in the list to avoid undesired
// auto detection for users who don't have a saved setting yet. // auto detection for users who don't have a saved setting yet.
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
if (d->getMusicDriverId() == "null") if (d->getMusicDriverId() == "null")
_mt32DevicePopUp->appendEntry(_("Don't use Roland MT-32 music"), d->getHandle()); _mt32DevicePopUp->appendEntry(_("Don't use Roland MT-32 music"), d->getHandle());
} }
} }
// Now we add the other devices. // Now we add the other devices.
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
if (d->getMusicType() >= MT_GM) if (d->getMusicType() >= MT_GM)
_mt32DevicePopUp->appendEntry(d->getCompleteName(), d->getHandle()); _mt32DevicePopUp->appendEntry(d->getCompleteName(), d->getHandle());
@ -1323,10 +1321,10 @@ bool OptionsDialog::loadMusicDeviceSetting(PopUpWidget *popup, Common::String se
if (_domain != Common::ConfigManager::kApplicationDomain || ConfMan.hasKey(setting, _domain) || preferredType) { if (_domain != Common::ConfigManager::kApplicationDomain || ConfMan.hasKey(setting, _domain) || preferredType) {
const Common::String drv = ConfMan.get(setting, (_domain != Common::ConfigManager::kApplicationDomain && !ConfMan.hasKey(setting, _domain)) ? Common::ConfigManager::kApplicationDomain : _domain); const Common::String drv = ConfMan.get(setting, (_domain != Common::ConfigManager::kApplicationDomain && !ConfMan.hasKey(setting, _domain)) ? Common::ConfigManager::kApplicationDomain : _domain);
const MusicPlugin::List p = MusicMan.getPlugins(); const PluginList p = MusicMan.getPlugins();
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
if (setting.empty() ? (preferredType == d->getMusicType()) : (drv == d->getCompleteId())) { if (setting.empty() ? (preferredType == d->getMusicType()) : (drv == d->getCompleteId())) {
popup->setSelectedTag(d->getHandle()); popup->setSelectedTag(d->getHandle());
@ -1343,10 +1341,10 @@ void OptionsDialog::saveMusicDeviceSetting(PopUpWidget *popup, Common::String se
if (!popup || !_enableAudioSettings) if (!popup || !_enableAudioSettings)
return; return;
const MusicPlugin::List p = MusicMan.getPlugins(); const PluginList p = MusicMan.getPlugins();
bool found = false; bool found = false;
for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end() && !found; ++m) { for (PluginList::const_iterator m = p.begin(); m != p.end() && !found; ++m) {
MusicDevices i = (**m)->getDevices(); MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
if (d->getHandle() == popup->getSelectedTag()) { if (d->getHandle() == popup->getSelectedTag()) {
ConfMan.set(setting, d->getCompleteId(), _domain); ConfMan.set(setting, d->getCompleteId(), _domain);
@ -1380,22 +1378,22 @@ int OptionsDialog::getSubtitleMode(bool subtitles, bool speech_mute) {
void OptionsDialog::updateMusicVolume(const int newValue) const { void OptionsDialog::updateMusicVolume(const int newValue) const {
_musicVolumeLabel->setValue(newValue); _musicVolumeLabel->setValue(newValue);
_musicVolumeSlider->setValue(newValue); _musicVolumeSlider->setValue(newValue);
_musicVolumeLabel->draw(); _musicVolumeLabel->markAsDirty();
_musicVolumeSlider->draw(); _musicVolumeSlider->markAsDirty();
} }
void OptionsDialog::updateSfxVolume(const int newValue) const { void OptionsDialog::updateSfxVolume(const int newValue) const {
_sfxVolumeLabel->setValue(newValue); _sfxVolumeLabel->setValue(newValue);
_sfxVolumeSlider->setValue(newValue); _sfxVolumeSlider->setValue(newValue);
_sfxVolumeLabel->draw(); _sfxVolumeLabel->markAsDirty();
_sfxVolumeSlider->draw(); _sfxVolumeSlider->markAsDirty();
} }
void OptionsDialog::updateSpeechVolume(const int newValue) const { void OptionsDialog::updateSpeechVolume(const int newValue) const {
_speechVolumeLabel->setValue(newValue); _speechVolumeLabel->setValue(newValue);
_speechVolumeSlider->setValue(newValue); _speechVolumeSlider->setValue(newValue);
_speechVolumeLabel->draw(); _speechVolumeLabel->markAsDirty();
_speechVolumeSlider->draw(); _speechVolumeSlider->markAsDirty();
} }
void OptionsDialog::reflowLayout() { void OptionsDialog::reflowLayout() {
@ -1998,7 +1996,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
error.runModal(); error.runModal();
return; return;
} }
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
} }
@ -2008,7 +2006,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
// User made his choice... // User made his choice...
Common::FSNode dir(browser.getResult()); Common::FSNode dir(browser.getResult());
_themePath->setLabel(dir.getPath()); _themePath->setLabel(dir.getPath());
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
} }
@ -2018,7 +2016,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
// User made his choice... // User made his choice...
Common::FSNode dir(browser.getResult()); Common::FSNode dir(browser.getResult());
_extraPath->setLabel(dir.getPath()); _extraPath->setLabel(dir.getPath());
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
} }
@ -2029,7 +2027,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
// User made his choice... // User made his choice...
Common::FSNode dir(browser.getResult()); Common::FSNode dir(browser.getResult());
_pluginsPath->setLabel(dir.getPath()); _pluginsPath->setLabel(dir.getPath());
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
} }
@ -2044,7 +2042,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
if (path.empty()) if (path.empty())
path = "/"; // absolute root path = "/"; // absolute root
_rootPath->setLabel(path); _rootPath->setLabel(path);
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
} }
@ -2075,7 +2073,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
else else
_soundFontClearButton->setEnabled(false); _soundFontClearButton->setEnabled(false);
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
} }
@ -2169,7 +2167,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
if (_serverPort) { if (_serverPort) {
_serverPort->setEditString(Common::String::format("%u", Networking::LocalWebserver::DEFAULT_SERVER_PORT)); _serverPort->setEditString(Common::String::format("%u", Networking::LocalWebserver::DEFAULT_SERVER_PORT));
} }
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
} }
#endif // USE_SDL_NET #endif // USE_SDL_NET
@ -2206,7 +2204,7 @@ void GlobalOptionsDialog::handleTickle() {
#endif #endif
if (_redrawCloudTab) { if (_redrawCloudTab) {
setupCloudTab(); setupCloudTab();
draw(); g_gui.scheduleTopDialogRedraw();
_redrawCloudTab = false; _redrawCloudTab = false;
} }
#endif #endif

View file

@ -995,7 +995,7 @@ void PredictiveDialog::pressEditText() {
Common::strlcat(_predictiveResult, _currentWord.c_str(), sizeof(_predictiveResult)); Common::strlcat(_predictiveResult, _currentWord.c_str(), sizeof(_predictiveResult));
_editText->setEditString(_predictiveResult); _editText->setEditString(_predictiveResult);
//_editText->setCaretPos(_prefix.size() + _currentWord.size()); //_editText->setCaretPos(_prefix.size() + _currentWord.size());
_editText->draw(); _editText->markAsDirty();
} }
} // namespace GUI } // namespace GUI

View file

@ -167,8 +167,7 @@ void RecorderDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
case kRecordCmd: { case kRecordCmd: {
TimeDate t; TimeDate t;
Common::String gameId = ConfMan.get("gameid", _target); Common::String gameId = ConfMan.get("gameid", _target);
const EnginePlugin *plugin = 0; GameDescriptor desc = EngineMan.findGame(gameId);
GameDescriptor desc = EngineMan.findGame(gameId, &plugin);
g_system->getTimeAndDate(t); g_system->getTimeAndDate(t);
EditRecordDialog editDlg(_("Unknown Author"), Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description(), ""); EditRecordDialog editDlg(_("Unknown Author"), Common::String::format("%.2d.%.2d.%.4d ", t.tm_mday, t.tm_mon, 1900 + t.tm_year) + desc.description(), "");
if (editDlg.runModal() != kOKCmd) { if (editDlg.runModal() != kOKCmd) {
@ -212,7 +211,7 @@ void RecorderDialog::updateList() {
file.close(); file.close();
} }
_list->setList(namesList); _list->setList(namesList);
_list->draw(); _list->markAsDirty();
} }
int RecorderDialog::runModal(Common::String &target) { int RecorderDialog::runModal(Common::String &target) {
@ -254,7 +253,7 @@ void RecorderDialog::updateSelection(bool redraw) {
_screenShotsCount = -1; _screenShotsCount = -1;
_currentScreenshot = 0; _currentScreenshot = 0;
_gfxWidget->setGfx(-1, -1, 0, 0, 0); _gfxWidget->setGfx(-1, -1, 0, 0, 0);
_gfxWidget->draw(); _gfxWidget->markAsDirty();
updateScreenShotsText(); updateScreenShotsText();
} }
} }
@ -284,7 +283,7 @@ void RecorderDialog::updateScreenshot() {
} else { } else {
_gfxWidget->setGfx(-1, -1, 0, 0, 0); _gfxWidget->setGfx(-1, -1, 0, 0, 0);
} }
_gfxWidget->draw(); _gfxWidget->markAsDirty();
} }
void RecorderDialog::updateScreenShotsText() { void RecorderDialog::updateScreenShotsText() {

View file

@ -21,6 +21,7 @@
*/ */
#include "gui/remotebrowser.h" #include "gui/remotebrowser.h"
#include "gui/gui-manager.h"
#include "gui/widgets/list.h" #include "gui/widgets/list.h"
#include "common/config-manager.h" #include "common/config-manager.h"
@ -28,9 +29,9 @@
#include "common/algorithm.h" #include "common/algorithm.h"
#include "common/translation.h" #include "common/translation.h"
#include <backends/networking/curl/request.h> #include "backends/networking/curl/request.h"
#include <backends/cloud/storage.h> #include "backends/cloud/storage.h"
#include <backends/cloud/cloudmanager.h> #include "backends/cloud/cloudmanager.h"
#include "message.h" #include "message.h"
namespace GUI { namespace GUI {
@ -162,7 +163,7 @@ void RemoteBrowserDialog::updateListing() {
_fileList->setEnabled(!_navigationLocked); _fileList->setEnabled(!_navigationLocked);
// Finally, redraw // Finally, redraw
draw(); g_gui.scheduleTopDialogRedraw();
} }
void RemoteBrowserDialog::goUp() { void RemoteBrowserDialog::goUp() {

View file

@ -60,7 +60,7 @@ SaveLoadCloudSyncProgressDialog::SaveLoadCloudSyncProgressDialog(bool canRunInBa
new ButtonWidget(this, "SaveLoadCloudSyncProgress.Cancel", "Cancel", 0, kCancelSyncCmd, Common::ASCII_ESCAPE); // Cancel dialog new ButtonWidget(this, "SaveLoadCloudSyncProgress.Cancel", "Cancel", 0, kCancelSyncCmd, Common::ASCII_ESCAPE); // Cancel dialog
ButtonWidget *backgroundButton = new ButtonWidget(this, "SaveLoadCloudSyncProgress.Background", "Run in background", 0, kBackgroundSyncCmd, Common::ASCII_RETURN); // Confirm dialog ButtonWidget *backgroundButton = new ButtonWidget(this, "SaveLoadCloudSyncProgress.Background", "Run in background", 0, kBackgroundSyncCmd, Common::ASCII_RETURN); // Confirm dialog
backgroundButton->setEnabled(canRunInBackground); backgroundButton->setEnabled(canRunInBackground);
draw(); g_gui.scheduleTopDialogRedraw();
} }
SaveLoadCloudSyncProgressDialog::~SaveLoadCloudSyncProgressDialog() { SaveLoadCloudSyncProgressDialog::~SaveLoadCloudSyncProgressDialog() {
@ -72,7 +72,7 @@ void SaveLoadCloudSyncProgressDialog::handleCommand(CommandSender *sender, uint3
case kSavesSyncProgressCmd: case kSavesSyncProgressCmd:
_percentLabel->setLabel(Common::String::format("%u%%", data)); _percentLabel->setLabel(Common::String::format("%u%%", data));
_progressBar->setValue(data); _progressBar->setValue(data);
_progressBar->draw(); _progressBar->markAsDirty();
break; break;
case kCancelSyncCmd: case kCancelSyncCmd:
@ -594,14 +594,14 @@ void SaveLoadChooserSimple::updateSelection(bool redraw) {
_deleteButton->setEnabled(isDeletable && !isLocked && (selItem >= 0) && (!_list->getSelectedString().empty())); _deleteButton->setEnabled(isDeletable && !isLocked && (selItem >= 0) && (!_list->getSelectedString().empty()));
if (redraw) { if (redraw) {
_gfxWidget->draw(); _gfxWidget->markAsDirty();
_date->draw(); _date->markAsDirty();
_time->draw(); _time->markAsDirty();
_playtime->draw(); _playtime->markAsDirty();
_chooseButton->draw(); _chooseButton->markAsDirty();
_deleteButton->draw(); _deleteButton->markAsDirty();
draw(); g_gui.scheduleTopDialogRedraw();
} }
} }
@ -703,7 +703,7 @@ void SaveLoadChooserSimple::updateSaveList() {
else else
_chooseButton->setEnabled(false); _chooseButton->setEnabled(false);
draw(); g_gui.scheduleTopDialogRedraw();
} }
// SaveLoadChooserGrid implementation // SaveLoadChooserGrid implementation
@ -761,13 +761,13 @@ void SaveLoadChooserGrid::handleCommand(CommandSender *sender, uint32 cmd, uint3
case kNextCmd: case kNextCmd:
++_curPage; ++_curPage;
updateSaves(); updateSaves();
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case kPrevCmd: case kPrevCmd:
--_curPage; --_curPage;
updateSaves(); updateSaves();
draw(); g_gui.scheduleTopDialogRedraw();
break; break;
case kNewSaveCmd: case kNewSaveCmd:
@ -788,13 +788,13 @@ void SaveLoadChooserGrid::handleMouseWheel(int x, int y, int direction) {
if (_nextButton->isEnabled()) { if (_nextButton->isEnabled()) {
++_curPage; ++_curPage;
updateSaves(); updateSaves();
draw(); g_gui.scheduleTopDialogRedraw();
} }
} else { } else {
if (_prevButton->isEnabled()) { if (_prevButton->isEnabled()) {
--_curPage; --_curPage;
updateSaves(); updateSaves();
draw(); g_gui.scheduleTopDialogRedraw();
} }
} }
} }
@ -802,7 +802,7 @@ void SaveLoadChooserGrid::handleMouseWheel(int x, int y, int direction) {
void SaveLoadChooserGrid::updateSaveList() { void SaveLoadChooserGrid::updateSaveList() {
SaveLoadChooserDialog::updateSaveList(); SaveLoadChooserDialog::updateSaveList();
updateSaves(); updateSaves();
draw(); g_gui.scheduleTopDialogRedraw();
} }
void SaveLoadChooserGrid::open() { void SaveLoadChooserGrid::open() {

View file

@ -76,14 +76,14 @@ Common::String SaveLoadChooser::createDefaultSaveDescription(const int slot) con
int SaveLoadChooser::runModalWithCurrentTarget() { int SaveLoadChooser::runModalWithCurrentTarget() {
const Common::String gameId = ConfMan.get("gameid"); const Common::String gameId = ConfMan.get("gameid");
const EnginePlugin *plugin = 0; const Plugin *plugin = 0;
EngineMan.findGame(gameId, &plugin); EngineMan.findGame(gameId, &plugin);
return runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName()); return runModalWithPluginAndTarget(plugin, ConfMan.getActiveDomainName());
} }
int SaveLoadChooser::runModalWithPluginAndTarget(const EnginePlugin *plugin, const String &target) { int SaveLoadChooser::runModalWithPluginAndTarget(const Plugin *plugin, const String &target) {
selectChooser(**plugin); selectChooser(plugin->get<MetaEngine>());
if (!_impl) if (!_impl)
return -1; return -1;
@ -98,10 +98,10 @@ int SaveLoadChooser::runModalWithPluginAndTarget(const EnginePlugin *plugin, con
int ret; int ret;
do { do {
ret = _impl->run(target, &(**plugin)); ret = _impl->run(target, &plugin->get<MetaEngine>());
#ifndef DISABLE_SAVELOADCHOOSER_GRID #ifndef DISABLE_SAVELOADCHOOSER_GRID
if (ret == kSwitchSaveLoadDialog) { if (ret == kSwitchSaveLoadDialog) {
selectChooser(**plugin); selectChooser(plugin->get<MetaEngine>());
} }
#endif // !DISABLE_SAVELOADCHOOSER_GRID #endif // !DISABLE_SAVELOADCHOOSER_GRID
} while (ret < -1); } while (ret < -1);

View file

@ -51,7 +51,7 @@ public:
* @return The selcted save slot. -1 in case none is selected. * @return The selcted save slot. -1 in case none is selected.
*/ */
int runModalWithCurrentTarget(); int runModalWithCurrentTarget();
int runModalWithPluginAndTarget(const EnginePlugin *plugin, const String &target); int runModalWithPluginAndTarget(const Plugin *plugin, const String &target);
const Common::String &getResultString() const; const Common::String &getResultString() const;

View file

@ -231,7 +231,7 @@ void StorageWizardDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
_codeWidget[i]->setEditString(subcode); _codeWidget[i]->setEditString(subcode);
} }
handleCommand(sender, kCodeBoxCmd, data); handleCommand(sender, kCodeBoxCmd, data);
draw(); g_gui.scheduleTopDialogRedraw();
} }
break; break;
} }

View file

@ -115,7 +115,7 @@ void ThemeBrowser::updateListing() {
_fileList->setSelected(currentThemeIndex); _fileList->setSelected(currentThemeIndex);
// Finally, redraw // Finally, redraw
draw(); g_gui.scheduleTopDialogRedraw();
} }
} // End of namespace GUI } // End of namespace GUI

Binary file not shown.

View file

@ -366,14 +366,6 @@
type = 'PopUp' type = 'PopUp'
/> />
</layout> </layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
<widget name = 'auSampleRatePopupDesc'
type = 'OptionsLabel'
/>
<widget name = 'auSampleRatePopup'
type = 'PopUp'
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
<widget name = 'subToggleDesc' <widget name = 'subToggleDesc'
type = 'OptionsLabel' type = 'OptionsLabel'

View file

@ -347,14 +347,6 @@
type = 'PopUp' type = 'PopUp'
/> />
</layout> </layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
<widget name = 'auSampleRatePopupDesc'
type = 'OptionsLabel'
/>
<widget name = 'auSampleRatePopup'
type = 'PopUp'
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '3' center = 'true'> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '3' center = 'true'>
<widget name = 'subToggleDesc' <widget name = 'subToggleDesc'
type = 'OptionsLabel' type = 'OptionsLabel'

View file

@ -51,6 +51,7 @@ void Widget::init() {
// Insert into the widget list of the boss // Insert into the widget list of the boss
_next = _boss->_firstWidget; _next = _boss->_firstWidget;
_boss->_firstWidget = this; _boss->_firstWidget = this;
_needsRedraw = true;
} }
Common::Rect Widget::getBossClipRect() const { Common::Rect Widget::getBossClipRect() const {
@ -112,39 +113,53 @@ void Widget::updateState(int oldFlags, int newFlags) {
} }
} }
void Widget::markAsDirty() {
_needsRedraw = true;
Widget *w = _firstWidget;
while (w) {
w->markAsDirty();
w = w->next();
}
}
void Widget::draw() { void Widget::draw() {
if (!isVisible() || !_boss->isVisible()) if (!isVisible() || !_boss->isVisible())
return; return;
int oldX = _x, oldY = _y; if (_needsRedraw) {
int oldX = _x, oldY = _y;
// Account for our relative position in the dialog // Account for our relative position in the dialog
_x = getAbsX(); _x = getAbsX();
_y = getAbsY(); _y = getAbsY();
// Draw border // Draw border
if (_flags & WIDGET_BORDER) { if (_flags & WIDGET_BORDER) {
g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder); g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x+_w, _y+_h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder);
_x += 4; _x += 4;
_y += 4; _y += 4;
_w -= 8; _w -= 8;
_h -= 8; _h -= 8;
}
// Now perform the actual widget draw
drawWidget();
// Restore x/y
if (_flags & WIDGET_BORDER) {
_x -= 4;
_y -= 4;
_w += 8;
_h += 8;
}
_x = oldX;
_y = oldY;
_needsRedraw = false;
} }
// Now perform the actual widget draw
drawWidget();
// Restore x/y
if (_flags & WIDGET_BORDER) {
_x -= 4;
_y -= 4;
_w += 8;
_h += 8;
}
_x = oldX;
_y = oldY;
// Draw all children // Draw all children
Widget *w = _firstWidget; Widget *w = _firstWidget;
while (w) { while (w) {
@ -191,7 +206,7 @@ void Widget::setEnabled(bool e) {
else else
clearFlags(WIDGET_ENABLED); clearFlags(WIDGET_ENABLED);
_boss->draw(); g_gui.scheduleTopDialogRedraw();
} }
} }
@ -273,7 +288,7 @@ StaticTextWidget::StaticTextWidget(GuiObject *boss, int x, int y, int w, int h,
StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip, ThemeEngine::FontStyle font) StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip, ThemeEngine::FontStyle font)
: Widget(boss, name, tooltip) { : Widget(boss, name, tooltip) {
setFlags(WIDGET_ENABLED); setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
_type = kStaticTextWidget; _type = kStaticTextWidget;
_label = text; _label = text;
@ -289,12 +304,7 @@ void StaticTextWidget::setLabel(const Common::String &label) {
if (_label != label) { if (_label != label) {
_label = label; _label = label;
// when changing the label, add the CLEARBG flag markAsDirty();
// so the widget is completely redrawn, otherwise
// the new text is drawn on top of the old one.
setFlags(WIDGET_CLEARBG);
draw();
clearFlags(WIDGET_CLEARBG);
} }
} }
@ -302,14 +312,8 @@ void StaticTextWidget::setAlign(Graphics::TextAlign align) {
if (_align != align){ if (_align != align){
_align = align; _align = align;
// same as setLabel() actually, the text markAsDirty();
// would be redrawn on top of the old one so
// we add the CLEARBG flag
setFlags(WIDGET_CLEARBG);
draw();
clearFlags(WIDGET_CLEARBG);
} }
} }
@ -389,18 +393,18 @@ ButtonWidget *addClearButton(GuiObject *boss, const Common::String &name, uint32
void ButtonWidget::setHighLighted(bool enable) { void ButtonWidget::setHighLighted(bool enable) {
(enable) ? setFlags(WIDGET_HILITED) : clearFlags(WIDGET_HILITED); (enable) ? setFlags(WIDGET_HILITED) : clearFlags(WIDGET_HILITED);
draw(); markAsDirty();
} }
void ButtonWidget::setPressedState() { void ButtonWidget::setPressedState() {
setFlags(WIDGET_PRESSED); setFlags(WIDGET_PRESSED);
clearFlags(WIDGET_HILITED); clearFlags(WIDGET_HILITED);
draw(); markAsDirty();
} }
void ButtonWidget::setUnpressedState() { void ButtonWidget::setUnpressedState() {
clearFlags(WIDGET_PRESSED); clearFlags(WIDGET_PRESSED);
draw(); markAsDirty();
} }
#pragma mark - #pragma mark -
@ -563,7 +567,7 @@ void CheckboxWidget::setState(bool state) {
if (_state != state) { if (_state != state) {
_state = state; _state = state;
//_flags ^= WIDGET_INV_BORDER; //_flags ^= WIDGET_INV_BORDER;
draw(); markAsDirty();
} }
sendCommand(_cmd, _state); sendCommand(_cmd, _state);
} }
@ -632,7 +636,7 @@ void RadiobuttonWidget::setState(bool state, bool setGroup) {
if (_state != state) { if (_state != state) {
_state = state; _state = state;
//_flags ^= WIDGET_INV_BORDER; //_flags ^= WIDGET_INV_BORDER;
draw(); markAsDirty();
} }
sendCommand(_cmd, _state); sendCommand(_cmd, _state);
} }
@ -667,7 +671,7 @@ void SliderWidget::handleMouseMoved(int x, int y, int button) {
if (newValue != _value) { if (newValue != _value) {
_value = newValue; _value = newValue;
draw(); markAsDirty();
sendCommand(_cmd, _value); // FIXME - hack to allow for "live update" in sound dialog sendCommand(_cmd, _value); // FIXME - hack to allow for "live update" in sound dialog
} }
} }
@ -699,7 +703,7 @@ void SliderWidget::handleMouseWheel(int x, int y, int direction) {
if (newValue != _value) { if (newValue != _value) {
_value = newValue; _value = newValue;
draw(); markAsDirty();
sendCommand(_cmd, _value); // FIXME - hack to allow for "live update" in sound dialog sendCommand(_cmd, _value); // FIXME - hack to allow for "live update" in sound dialog
} }
} }

View file

@ -103,6 +103,7 @@ protected:
private: private:
uint16 _flags; uint16 _flags;
bool _needsRedraw;
public: public:
static Widget *findWidgetInChain(Widget *start, int x, int y); static Widget *findWidgetInChain(Widget *start, int x, int y);
@ -137,7 +138,12 @@ public:
virtual bool handleKeyUp(Common::KeyState state) { return false; } // Return true if the event was handled virtual bool handleKeyUp(Common::KeyState state) { return false; } // Return true if the event was handled
virtual void handleTickle() {} virtual void handleTickle() {}
void draw(); /** Mark the widget and its children as dirty so they are redrawn on the next screen update */
virtual void markAsDirty();
/** Redraw the widget if it was marked as dirty, and recursively proceed with its children */
virtual void draw();
void receivedFocus() { _hasFocus = true; receivedFocusWidget(); } void receivedFocus() { _hasFocus = true; receivedFocusWidget(); }
void lostFocus() { _hasFocus = false; lostFocusWidget(); } void lostFocus() { _hasFocus = false; lostFocusWidget(); }
virtual bool wantsFocus() { return false; } virtual bool wantsFocus() { return false; }
@ -213,8 +219,8 @@ public:
void handleMouseUp(int x, int y, int button, int clickCount); void handleMouseUp(int x, int y, int button, int clickCount);
void handleMouseDown(int x, int y, int button, int clickCount); void handleMouseDown(int x, int y, int button, int clickCount);
void handleMouseEntered(int button) { if (_duringPress) { setFlags(WIDGET_PRESSED); } else { setFlags(WIDGET_HILITED); } draw(); } void handleMouseEntered(int button) { if (_duringPress) { setFlags(WIDGET_PRESSED); } else { setFlags(WIDGET_HILITED); } markAsDirty(); }
void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED | WIDGET_PRESSED); draw(); } void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED | WIDGET_PRESSED); markAsDirty(); }
void setHighLighted(bool enable); void setHighLighted(bool enable);
void setPressedState(); void setPressedState();
@ -262,8 +268,8 @@ public:
CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0);
void handleMouseUp(int x, int y, int button, int clickCount); void handleMouseUp(int x, int y, int button, int clickCount);
virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); markAsDirty(); }
virtual void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } virtual void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); markAsDirty(); }
void setState(bool state); void setState(bool state);
void toggleState() { setState(!_state); } void toggleState() { setState(!_state); }
@ -308,8 +314,8 @@ public:
RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip = 0, uint8 hotkey = 0); RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip = 0, uint8 hotkey = 0);
void handleMouseUp(int x, int y, int button, int clickCount); void handleMouseUp(int x, int y, int button, int clickCount);
virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); markAsDirty(); }
virtual void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } virtual void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); markAsDirty(); }
void setState(bool state, bool setGroup = true); void setState(bool state, bool setGroup = true);
void toggleState() { setState(!_state); } void toggleState() { setState(!_state); }
@ -348,8 +354,8 @@ public:
void handleMouseMoved(int x, int y, int button); void handleMouseMoved(int x, int y, int button);
void handleMouseDown(int x, int y, int button, int clickCount); void handleMouseDown(int x, int y, int button, int clickCount);
void handleMouseUp(int x, int y, int button, int clickCount); void handleMouseUp(int x, int y, int button, int clickCount);
void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); markAsDirty(); }
void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); markAsDirty(); }
void handleMouseWheel(int x, int y, int direction); void handleMouseWheel(int x, int y, int direction);
protected: protected:

View file

@ -235,7 +235,7 @@ bool EditableWidget::handleKeyDown(Common::KeyState state) {
} }
if (dirty) if (dirty)
draw(); markAsDirty();
if (forcecaret) if (forcecaret)
makeCaretVisible(); makeCaretVisible();

View file

@ -87,7 +87,7 @@ void EditTextWidget::handleMouseDown(int x, int y, int button, int clickCount) {
last = cur; last = cur;
} }
if (setCaretPos(i)) if (setCaretPos(i))
draw(); markAsDirty();
#ifdef TIZEN #ifdef TIZEN
// Display the virtual keypad to allow text entry. Samsung app-store testers expected // Display the virtual keypad to allow text entry. Samsung app-store testers expected

View file

@ -37,7 +37,6 @@ ListWidget::ListWidget(Dialog *boss, const String &name, const char *tooltip, ui
: EditableWidget(boss, name, tooltip), _cmd(cmd) { : EditableWidget(boss, name, tooltip), _cmd(cmd) {
_scrollBar = NULL; _scrollBar = NULL;
_textWidth = NULL;
// This ensures that _entriesPerPage is properly initialized. // This ensures that _entriesPerPage is properly initialized.
reflowLayout(); reflowLayout();
@ -69,7 +68,6 @@ ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, const char *too
: EditableWidget(boss, x, y, w, h, tooltip), _cmd(cmd) { : EditableWidget(boss, x, y, w, h, tooltip), _cmd(cmd) {
_scrollBar = NULL; _scrollBar = NULL;
_textWidth = NULL;
// This ensures that _entriesPerPage is properly initialized. // This ensures that _entriesPerPage is properly initialized.
reflowLayout(); reflowLayout();
@ -97,10 +95,6 @@ ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, const char *too
_editColor = ThemeEngine::kFontColorNormal; _editColor = ThemeEngine::kFontColorNormal;
} }
ListWidget::~ListWidget() {
delete[] _textWidth;
}
bool ListWidget::containsWidget(Widget *w) const { bool ListWidget::containsWidget(Widget *w) const {
if (w == _scrollBar || _scrollBar->containsWidget(w)) if (w == _scrollBar || _scrollBar->containsWidget(w))
return true; return true;
@ -145,7 +139,7 @@ void ListWidget::setSelected(int item) {
_currentPos = _selectedItem - _entriesPerPage / 2; _currentPos = _selectedItem - _entriesPerPage / 2;
scrollToCurrent(); scrollToCurrent();
draw(); markAsDirty();
} }
} }
@ -251,7 +245,7 @@ void ListWidget::handleMouseDown(int x, int y, int button, int clickCount) {
// TODO: Determine where inside the string the user clicked and place the // TODO: Determine where inside the string the user clicked and place the
// caret accordingly. // caret accordingly.
// See _editScrollOffset and EditTextWidget::handleMouseDown. // See _editScrollOffset and EditTextWidget::handleMouseDown.
draw(); markAsDirty();
} }
@ -446,12 +440,12 @@ bool ListWidget::handleKeyDown(Common::KeyState state) {
} }
if (dirty || _selectedItem != oldSelectedItem) if (dirty || _selectedItem != oldSelectedItem)
draw(); markAsDirty();
if (_selectedItem != oldSelectedItem) { if (_selectedItem != oldSelectedItem) {
sendCommand(kListSelectionChangedCmd, _selectedItem); sendCommand(kListSelectionChangedCmd, _selectedItem);
// also draw scrollbar // also draw scrollbar
_scrollBar->draw(); _scrollBar->markAsDirty();
} }
return handled; return handled;
@ -467,7 +461,7 @@ void ListWidget::receivedFocusWidget() {
_inversion = ThemeEngine::kTextInversionFocus; _inversion = ThemeEngine::kTextInversionFocus;
// Redraw the widget so the selection color will change // Redraw the widget so the selection color will change
draw(); markAsDirty();
} }
void ListWidget::lostFocusWidget() { void ListWidget::lostFocusWidget() {
@ -477,7 +471,7 @@ void ListWidget::lostFocusWidget() {
_editMode = false; _editMode = false;
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
drawCaret(true); drawCaret(true);
draw(); markAsDirty();
} }
void ListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { void ListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
@ -486,7 +480,7 @@ void ListWidget::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
if (_currentPos != (int)data) { if (_currentPos != (int)data) {
_currentPos = data; _currentPos = data;
checkBounds(); checkBounds();
draw(); markAsDirty();
// Scrollbar actions cause list focus (which triggers a redraw) // Scrollbar actions cause list focus (which triggers a redraw)
// NOTE: ListWidget's boss is always GUI::Dialog // NOTE: ListWidget's boss is always GUI::Dialog
@ -502,7 +496,6 @@ void ListWidget::drawWidget() {
// Draw a thin frame around the list. // Draw a thin frame around the list.
g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder); g_gui.theme()->drawWidgetBackgroundClip(Common::Rect(_x, _y, _x + _w, _y + _h), getBossClipRect(), 0, ThemeEngine::kWidgetBackgroundBorder);
const int scrollbarW = (_scrollBar && _scrollBar->isVisible()) ? _scrollBarWidth : 0;
// Draw the list items // Draw the list items
for (i = 0, pos = _currentPos; i < _entriesPerPage && pos < len; i++, pos++) { for (i = 0, pos = _currentPos; i < _entriesPerPage && pos < len; i++, pos++) {
@ -520,13 +513,11 @@ void ListWidget::drawWidget() {
// If in numbering mode, we first print a number prefix // If in numbering mode, we first print a number prefix
if (_numberingMode != kListNumberingOff) { if (_numberingMode != kListNumberingOff) {
buffer = Common::String::format("%2d. ", (pos + _numberingMode)); buffer = Common::String::format("%2d. ", (pos + _numberingMode));
g_gui.theme()->drawTextClip(Common::Rect(_x, y, _x + r.left + _leftPadding, y + fontHeight - 2), getBossClipRect(), g_gui.theme()->drawTextClip(Common::Rect(_x + _hlLeftPadding, y, _x + r.left + _leftPadding, y + fontHeight - 2),
buffer, _state, Graphics::kTextAlignLeft, inverted, _leftPadding, true); getBossClipRect(), buffer, _state, Graphics::kTextAlignLeft, inverted, _leftPadding, true);
pad = 0; pad = 0;
} }
int width;
ThemeEngine::FontColor color = ThemeEngine::kFontColorNormal; ThemeEngine::FontColor color = ThemeEngine::kFontColorNormal;
if (!_listColors.empty()) { if (!_listColors.empty()) {
@ -540,22 +531,21 @@ void ListWidget::drawWidget() {
buffer = _editString; buffer = _editString;
color = _editColor; color = _editColor;
adjustOffset(); adjustOffset();
width = _w - r.left - _hlRightPadding - _leftPadding - scrollbarW; g_gui.theme()->drawTextClip(Common::Rect(_x + r.left, y, _x + r.right, y + fontHeight - 2),
g_gui.theme()->drawTextClip(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2), getBossClipRect(), buffer, _state, getBossClipRect(), buffer, _state,
Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color); Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
} else { } else {
buffer = _list[pos]; buffer = _list[pos];
width = _w - r.left - scrollbarW; g_gui.theme()->drawTextClip(Common::Rect(_x + r.left, y, _x + r.right, y + fontHeight - 2),
g_gui.theme()->drawTextClip(Common::Rect(_x + r.left, y, _x + r.left + width, y + fontHeight - 2), getBossClipRect(), buffer, _state, getBossClipRect(), buffer, _state,
Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color); Graphics::kTextAlignLeft, inverted, pad, true, ThemeEngine::kFontStyleBold, color);
} }
_textWidth[i] = width;
} }
} }
Common::Rect ListWidget::getEditRect() const { Common::Rect ListWidget::getEditRect() const {
Common::Rect r(_hlLeftPadding, 0, _w - _hlLeftPadding - _hlRightPadding, kLineHeight - 2); const int scrollbarW = (_scrollBar && _scrollBar->isVisible()) ? _scrollBarWidth : 0;
Common::Rect r(_hlLeftPadding, 0, _w - _hlRightPadding - scrollbarW, kLineHeight - 2);
const int offset = (_selectedItem - _currentPos) * kLineHeight + _topPadding; const int offset = (_selectedItem - _currentPos) * kLineHeight + _topPadding;
r.top += offset; r.top += offset;
r.bottom += offset; r.bottom += offset;
@ -600,7 +590,7 @@ void ListWidget::scrollToEnd() {
_scrollBar->_currentPos = _currentPos; _scrollBar->_currentPos = _currentPos;
_scrollBar->recalc(); _scrollBar->recalc();
_scrollBar->draw(); _scrollBar->markAsDirty();
} }
void ListWidget::startEditMode() { void ListWidget::startEditMode() {
@ -616,7 +606,7 @@ void ListWidget::startEditMode() {
else else
_editColor = _listColors[_listIndex[_selectedItem]]; _editColor = _listColors[_listIndex[_selectedItem]];
} }
draw(); markAsDirty();
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
} }
} }
@ -636,7 +626,7 @@ void ListWidget::abortEditMode() {
assert(_selectedItem >= 0); assert(_selectedItem >= 0);
_editMode = false; _editMode = false;
//drawCaret(true); //drawCaret(true);
//draw(); //markAsDirty();
g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false);
} }
@ -668,12 +658,6 @@ void ListWidget::reflowLayout() {
_entriesPerPage = fracToInt(entriesPerPage); _entriesPerPage = fracToInt(entriesPerPage);
assert(_entriesPerPage > 0); assert(_entriesPerPage > 0);
delete[] _textWidth;
_textWidth = new int[_entriesPerPage];
for (int i = 0; i < _entriesPerPage; i++)
_textWidth[i] = 0;
if (_scrollBar) { if (_scrollBar) {
_scrollBar->resize(_w - _scrollBarWidth + 1, 0, _scrollBarWidth, _h); _scrollBar->resize(_w - _scrollBarWidth + 1, 0, _scrollBarWidth, _h);
scrollBarRecalc(); scrollBarRecalc();
@ -744,7 +728,7 @@ void ListWidget::setFilter(const String &filter, bool redraw) {
// Such a widget could also (optionally) draw a border (or even different // Such a widget could also (optionally) draw a border (or even different
// kinds of borders) around the objects it groups; and also a 'title' // kinds of borders) around the objects it groups; and also a 'title'
// (I am borrowing these "ideas" from the NSBox class in Cocoa :). // (I am borrowing these "ideas" from the NSBox class in Cocoa :).
_boss->draw(); g_gui.scheduleTopDialogRedraw();
} }
} }

View file

@ -87,7 +87,6 @@ protected:
public: public:
ListWidget(Dialog *boss, const String &name, const char *tooltip = 0, uint32 cmd = 0); ListWidget(Dialog *boss, const String &name, const char *tooltip = 0, uint32 cmd = 0);
ListWidget(Dialog *boss, int x, int y, int w, int h, const char *tooltip = 0, uint32 cmd = 0); ListWidget(Dialog *boss, int x, int y, int w, int h, const char *tooltip = 0, uint32 cmd = 0);
virtual ~ListWidget();
virtual bool containsWidget(Widget *) const; virtual bool containsWidget(Widget *) const;
virtual Widget *findWidget(int x, int y); virtual Widget *findWidget(int x, int y);
@ -149,8 +148,6 @@ protected:
void lostFocusWidget(); void lostFocusWidget();
void checkBounds(); void checkBounds();
void scrollToCurrent(); void scrollToCurrent();
int *_textWidth;
}; };
} // End of namespace GUI } // End of namespace GUI

View file

@ -37,7 +37,6 @@ class PopUpDialog : public Dialog {
protected: protected:
PopUpWidget *_popUpBoss; PopUpWidget *_popUpBoss;
int _clickX, _clickY; int _clickX, _clickY;
byte *_buffer;
int _selection; int _selection;
uint32 _openTime; uint32 _openTime;
bool _twoColumns; bool _twoColumns;
@ -49,7 +48,7 @@ protected:
public: public:
PopUpDialog(PopUpWidget *boss, int clickX, int clickY); PopUpDialog(PopUpWidget *boss, int clickX, int clickY);
void drawDialog(); void drawDialog(DrawLayer layerToDraw) override;
void handleMouseUp(int x, int y, int button, int clickCount); void handleMouseUp(int x, int y, int button, int clickCount);
void handleMouseWheel(int x, int y, int direction); // Scroll through entries with scroll wheel void handleMouseWheel(int x, int y, int direction); // Scroll through entries with scroll wheel
@ -70,9 +69,9 @@ protected:
PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY) PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY)
: Dialog(0, 0, 16, 16), : Dialog(0, 0, 16, 16),
_popUpBoss(boss) { _popUpBoss(boss) {
_backgroundType = ThemeEngine::kDialogBackgroundNone;
_openTime = 0; _openTime = 0;
_buffer = nullptr;
_entriesPerColumn = 1; _entriesPerColumn = 1;
// Copy the selection index // Copy the selection index
@ -148,7 +147,9 @@ PopUpDialog::PopUpDialog(PopUpWidget *boss, int clickX, int clickY)
_clickY = clickY - _y; _clickY = clickY - _y;
} }
void PopUpDialog::drawDialog() { void PopUpDialog::drawDialog(DrawLayer layerToDraw) {
Dialog::drawDialog(layerToDraw);
// Draw the menu border // Draw the menu border
g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0); g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x+_w, _y+_h), 0);
@ -409,7 +410,7 @@ void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount) {
if (newSel != -1 && _selectedItem != newSel) { if (newSel != -1 && _selectedItem != newSel) {
_selectedItem = newSel; _selectedItem = newSel;
sendCommand(kPopUpItemSelectedCmd, _entries[_selectedItem].tag); sendCommand(kPopUpItemSelectedCmd, _entries[_selectedItem].tag);
draw(); markAsDirty();
} }
} }
} }
@ -429,7 +430,7 @@ void PopUpWidget::handleMouseWheel(int x, int y, int direction) {
(newSelection != _selectedItem)) { (newSelection != _selectedItem)) {
_selectedItem = newSelection; _selectedItem = newSelection;
sendCommand(kPopUpItemSelectedCmd, _entries[_selectedItem].tag); sendCommand(kPopUpItemSelectedCmd, _entries[_selectedItem].tag);
draw(); markAsDirty();
} }
} }
} }

View file

@ -77,8 +77,8 @@ public:
uint32 getSelectedTag() const { return (_selectedItem >= 0) ? _entries[_selectedItem].tag : (uint32)-1; } uint32 getSelectedTag() const { return (_selectedItem >= 0) ? _entries[_selectedItem].tag : (uint32)-1; }
// const String& getSelectedString() const { return (_selectedItem >= 0) ? _entries[_selectedItem].name : String::emptyString; } // const String& getSelectedString() const { return (_selectedItem >= 0) ? _entries[_selectedItem].name : String::emptyString; }
void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); markAsDirty(); }
void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); markAsDirty(); }
virtual void reflowLayout(); virtual void reflowLayout();
protected: protected:

View file

@ -135,7 +135,7 @@ void ScrollBarWidget::handleMouseMoved(int x, int y, int button) {
_part = kSliderPart; _part = kSliderPart;
if (old_part != _part) if (old_part != _part)
draw(); markAsDirty();
} }
} }
@ -165,7 +165,7 @@ void ScrollBarWidget::checkBounds(int old_pos) {
if (old_pos != _currentPos) { if (old_pos != _currentPos) {
recalc(); recalc();
draw(); markAsDirty();
sendCommand(kSetPositionCmd, _currentPos); sendCommand(kSetPositionCmd, _currentPos);
} }
} }

View file

@ -69,7 +69,7 @@ public:
void handleMouseWheel(int x, int y, int direction); void handleMouseWheel(int x, int y, int direction);
void handleMouseMoved(int x, int y, int button); void handleMouseMoved(int x, int y, int button);
void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); } void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); }
void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); _part = kNoPart; draw(); } void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); _part = kNoPart; markAsDirty(); }
void handleTickle(); void handleTickle();
// FIXME - this should be private, but then we also have to add accessors // FIXME - this should be private, but then we also have to add accessors

View file

@ -102,8 +102,7 @@ void ScrollContainerWidget::handleCommand(CommandSender *sender, uint32 cmd, uin
case kSetPositionCmd: case kSetPositionCmd:
_scrolledY = _verticalScroll->_currentPos; _scrolledY = _verticalScroll->_currentPos;
reflowLayout(); reflowLayout();
draw(); g_gui.scheduleTopDialogRedraw();
g_gui.doFullRedraw();
break; break;
} }
} }

View file

@ -154,7 +154,7 @@ void TabWidget::removeTab(int tabID) {
} }
// Finally trigger a redraw // Finally trigger a redraw
_boss->draw(); g_gui.scheduleTopDialogRedraw();
} }
void TabWidget::setActiveTab(int tabID) { void TabWidget::setActiveTab(int tabID) {
@ -174,7 +174,7 @@ void TabWidget::setActiveTab(int tabID) {
while (_lastVisibleTab < tabID) while (_lastVisibleTab < tabID)
setFirstVisible(_firstVisibleTab + 1, false); setFirstVisible(_firstVisibleTab + 1, false);
_boss->draw(); g_gui.scheduleTopDialogRedraw();
} }
} }
@ -246,7 +246,7 @@ void TabWidget::setFirstVisible(int tabID, bool adjustIfRoom) {
computeLastVisibleTab(adjustIfRoom); computeLastVisibleTab(adjustIfRoom);
_boss->draw(); // TODO: Necessary? g_gui.scheduleTopDialogRedraw(); // TODO: Necessary?
} }
void TabWidget::reflowLayout() { void TabWidget::reflowLayout() {
@ -334,6 +334,15 @@ void TabWidget::draw() {
} }
} }
void TabWidget::markAsDirty() {
Widget::markAsDirty();
if (_navButtonsVisible) {
_navLeft->markAsDirty();
_navRight->markAsDirty();
}
}
bool TabWidget::containsWidget(Widget *w) const { bool TabWidget::containsWidget(Widget *w) const {
if (w == _navLeft || w == _navRight || _navLeft->containsWidget(w) || _navRight->containsWidget(w)) if (w == _navLeft || w == _navRight || _navLeft->containsWidget(w) || _navRight->containsWidget(w))
return true; return true;

View file

@ -111,7 +111,8 @@ public:
virtual void reflowLayout(); virtual void reflowLayout();
virtual void draw(); void draw() override;
void markAsDirty() override;
protected: protected:
// We overload getChildY to make sure child widgets are positioned correctly. // We overload getChildY to make sure child widgets are positioned correctly.

View file

@ -550,6 +550,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
*cur_lp = FROM_LE_32(((READ_LE_UINT32(ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1); *cur_lp = FROM_LE_32(((READ_LE_UINT32(ref_lp) >> 1) + correction_lp[lp2 & 0x01][k]) << 1);
lp2++; lp2++;
break; break;
case 1: case 1:
if (correction_type_sp[0][*buf1] != 1) { if (correction_type_sp[0][*buf1] != 1) {
// both correction types must be DYAD. If it's not the case // both correction types must be DYAD. If it's not the case
@ -568,6 +569,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
buf1++; buf1++;
lp2++; lp2++;
break; break;
case 2: case 2:
if (lp2 == 0) { if (lp2 == 0) {
for (i = 0, j = 0; i < 2; i++, j += width_tbl[1]) for (i = 0, j = 0; i < 2; i++, j += width_tbl[1])
@ -575,6 +577,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
lp2 += 2; lp2 += 2;
} }
break; break;
case 3: case 3:
if (lp2 < 2) { if (lp2 < 2) {
for (i = 0, j = 0; i < (3 - lp2); i++, j += width_tbl[1]) for (i = 0, j = 0; i < (3 - lp2); i++, j += width_tbl[1])
@ -582,6 +585,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
lp2 = 3; lp2 = 3;
} }
break; break;
case 8: case 8:
if (lp2 == 0) { if (lp2 == 0) {
RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3) RLE_V3_CHECK(buf1,rle_v1,rle_v2,rle_v3)
@ -597,8 +601,10 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
rle_v1 = 1; rle_v1 = 1;
rle_v2 = *buf1 - 1; rle_v2 = *buf1 - 1;
} }
// fall through
case 5: case 5:
LP2_CHECK(buf1,rle_v3,lp2) LP2_CHECK(buf1,rle_v3,lp2)
// fall through
case 4: case 4:
for (i = 0, j = 0; i < (4 - lp2); i++, j += width_tbl[1]) for (i = 0, j = 0; i < (4 - lp2); i++, j += width_tbl[1])
cur_lp[j] = READ_UINT32(ref_lp+j); cur_lp[j] = READ_UINT32(ref_lp+j);
@ -612,6 +618,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
buf1--; buf1--;
rle_v3 = 1; rle_v3 = 1;
} }
// fall through
case 6: case 6:
if (lp2 > 0) { if (lp2 > 0) {
//This case can't happen either. //This case can't happen either.
@ -636,6 +643,7 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
LV1_CHECK(buf1,rle_v3,lv1,lp2) LV1_CHECK(buf1,rle_v3,lv1,lp2)
break; break;
default: default:
return; return;
} }
@ -733,8 +741,10 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
rle_v2 = (*buf1) - 1; rle_v2 = (*buf1) - 1;
rle_v1 = 1; rle_v1 = 1;
} }
// fall through
case 5: case 5:
LP2_CHECK(buf1,rle_v3,lp2) LP2_CHECK(buf1,rle_v3,lp2)
// fall through
case 4: case 4:
for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1]) for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1])
cur_lp[j] = READ_UINT32(ref_lp); cur_lp[j] = READ_UINT32(ref_lp);
@ -888,8 +898,10 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
rle_v1 = 1; rle_v1 = 1;
rle_v2 = (*buf1) - 1; rle_v2 = (*buf1) - 1;
} }
// fall through
case 5: case 5:
LP2_CHECK(buf1,rle_v3,lp2) LP2_CHECK(buf1,rle_v3,lp2)
// fall through
case 4: case 4:
if (lp2 == 0 && flag1 != 0) { if (lp2 == 0 && flag1 != 0) {
for (i = 0, j = width_tbl[1]; i < 7; i++, j += width_tbl[1]) { for (i = 0, j = width_tbl[1]; i < 7; i++, j += width_tbl[1]) {
@ -1007,9 +1019,11 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
rle_v1 = 1; rle_v1 = 1;
rle_v2 = (*buf1) - 1; rle_v2 = (*buf1) - 1;
} }
// fall through
case 5: case 5:
case 7: case 7:
LP2_CHECK(buf1,rle_v3,lp2) LP2_CHECK(buf1,rle_v3,lp2)
// fall through
case 6: case 6:
case 4: case 4:
for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1]) { for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1]) {
@ -1112,9 +1126,11 @@ void Indeo3Decoder::decodeChunk(byte *cur, byte *ref, int width, int height,
rle_v1 = 1; rle_v1 = 1;
rle_v2 = (*buf1) - 1; rle_v2 = (*buf1) - 1;
} }
// fall through
case 5: case 5:
case 7: case 7:
LP2_CHECK(buf1,rle_v3,lp2) LP2_CHECK(buf1,rle_v3,lp2)
// fall through
case 4: case 4:
case 6: case 6:
for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1]) for (i = 0, j = 0; i < 8 - (lp2 * 2); i++, j += width_tbl[1])

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

715
po/eu.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more