mirror of https://github.com/stella-emu/stella.git
First pass at fixing superfluous re-draws in the UI.
- This addresses issue 158, and reduces CPU usage to near 0% when no changes are happening - This returns the code to the same performance levels as version 3.x.
This commit is contained in:
parent
a20bb6e95d
commit
e691853f0e
|
@ -125,20 +125,13 @@ void FBSurfaceSDL2::translateCoords(Int32& x, Int32& y) const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FBSurfaceSDL2::render()
|
||||
{
|
||||
if(mySurfaceIsDirty && myIsVisible)
|
||||
if(myIsVisible)
|
||||
{
|
||||
//cerr << "src: x=" << mySrcR.x << ", y=" << mySrcR.y << ", w=" << mySrcR.w << ", h=" << mySrcR.h << endl;
|
||||
//cerr << "dst: x=" << myDstR.x << ", y=" << myDstR.y << ", w=" << myDstR.w << ", h=" << myDstR.h << endl;
|
||||
|
||||
//cerr << "render()\n";
|
||||
if(myTexAccess == SDL_TEXTUREACCESS_STREAMING)
|
||||
SDL_UpdateTexture(myTexture, &mySrcR, mySurface->pixels, mySurface->pitch);
|
||||
SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrcR, &myDstR);
|
||||
|
||||
mySurfaceIsDirty = false;
|
||||
|
||||
// Let postFrameUpdate() know that a change has been made
|
||||
return myFB.myDirtyFlag = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -32,8 +32,7 @@
|
|||
FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
||||
: FrameBuffer(osystem),
|
||||
myWindow(nullptr),
|
||||
myRenderer(nullptr),
|
||||
myDirtyFlag(true)
|
||||
myRenderer(nullptr)
|
||||
{
|
||||
// Initialize SDL2 context
|
||||
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK) < 0)
|
||||
|
@ -275,7 +274,6 @@ string FrameBufferSDL2::about() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::invalidate()
|
||||
{
|
||||
myDirtyFlag = true;
|
||||
SDL_RenderClear(myRenderer);
|
||||
}
|
||||
|
||||
|
@ -302,14 +300,10 @@ bool FrameBufferSDL2::fullScreen() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::postFrameUpdate()
|
||||
void FrameBufferSDL2::renderToScreen()
|
||||
{
|
||||
if(myDirtyFlag)
|
||||
{
|
||||
// Now show all changes made to the renderer
|
||||
SDL_RenderPresent(myRenderer);
|
||||
myDirtyFlag = false;
|
||||
}
|
||||
// Show all changes made to the renderer
|
||||
SDL_RenderPresent(myRenderer);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -347,5 +341,5 @@ void FrameBufferSDL2::readPixels(uInt8* pixels, uInt32 pitch,
|
|||
void FrameBufferSDL2::clear()
|
||||
{
|
||||
invalidate();
|
||||
postFrameUpdate();
|
||||
renderToScreen();
|
||||
}
|
||||
|
|
|
@ -164,9 +164,10 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
string about() const override;
|
||||
|
||||
/**
|
||||
This method is called after any drawing is done (per-frame).
|
||||
This method must be called after all drawing is done, and indicates
|
||||
that the buffers should be pushed to the physical screen.
|
||||
*/
|
||||
void postFrameUpdate() override;
|
||||
void renderToScreen() override;
|
||||
|
||||
private:
|
||||
// The SDL video buffer
|
||||
|
@ -176,9 +177,6 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
// Used by mapRGB (when palettes are created)
|
||||
SDL_PixelFormat* myPixelFormat;
|
||||
|
||||
// Indicates that the renderer has been modified, and should be redrawn
|
||||
bool myDirtyFlag;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
FrameBufferSDL2() = delete;
|
||||
|
|
|
@ -793,7 +793,7 @@ void Debugger::unlockSystem()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Debugger::canExit() const
|
||||
{
|
||||
return myDialogStack.top() == baseDialog();
|
||||
return !myDialogStack.empty() && myDialogStack.top() == baseDialog();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -221,72 +221,84 @@ void DebuggerDialog::handleCommand(CommandSender* sender, int cmd,
|
|||
void DebuggerDialog::doStep()
|
||||
{
|
||||
instance().debugger().parser().run("step");
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::doTrace()
|
||||
{
|
||||
instance().debugger().parser().run("trace");
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::doAdvance()
|
||||
{
|
||||
instance().debugger().parser().run("frame #1");
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::doScanlineAdvance()
|
||||
{
|
||||
instance().debugger().parser().run("scanline #1");
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::doRewind()
|
||||
{
|
||||
instance().debugger().parser().run("rewind");
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::doUnwind()
|
||||
{
|
||||
instance().debugger().parser().run("unwind");
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::doRewind10()
|
||||
{
|
||||
instance().debugger().parser().run("rewind #10");
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::doUnwind10()
|
||||
{
|
||||
instance().debugger().parser().run("unwind #10");
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::doRewindAll()
|
||||
{
|
||||
instance().debugger().parser().run("rewind #1000");
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::doUnwindAll()
|
||||
{
|
||||
instance().debugger().parser().run("unwind #1000");
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::doExitDebugger()
|
||||
{
|
||||
instance().debugger().parser().run("run");
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerDialog::doExitRom()
|
||||
{
|
||||
instance().debugger().parser().run("exitrom");
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -130,8 +130,6 @@ class DebuggerDialog : public Dialog
|
|||
ButtonWidget* myRewindButton;
|
||||
ButtonWidget* myUnwindButton;
|
||||
|
||||
//ButtonWidget* myOptionsButton;
|
||||
|
||||
unique_ptr<GUI::MessageBox> myFatalError;
|
||||
unique_ptr<OptionsDialog> myOptions;
|
||||
|
||||
|
|
|
@ -283,7 +283,8 @@ void EventHandler::handleSystemEvent(SystemEvent e, int, int)
|
|||
switch(e)
|
||||
{
|
||||
case SystemEvent::WINDOW_EXPOSED:
|
||||
myOSystem.frameBuffer().update();
|
||||
case SystemEvent::WINDOW_RESIZED:
|
||||
myOSystem.frameBuffer().update(true); // force full update
|
||||
break;
|
||||
|
||||
case SystemEvent::WINDOW_FOCUS_GAINED:
|
||||
|
|
|
@ -219,12 +219,6 @@ class FBSurface
|
|||
uInt32 color, TextAlign align = TextAlign::Left,
|
||||
int deltax = 0, bool useEllipsis = true, uInt32 shadowColor = 0);
|
||||
|
||||
/**
|
||||
This method should be called to indicate that the surface has been
|
||||
modified, and should be redrawn at the next interval.
|
||||
*/
|
||||
virtual void setDirty() { }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Note: The following methods are FBSurface-specific, and must be
|
||||
// implemented in child classes.
|
||||
|
@ -331,6 +325,13 @@ class FBSurface
|
|||
|
||||
static void setPalette(const uInt32* palette) { myPalette = palette; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
This method must be called to indicate that the surface has been
|
||||
modified, and should be redrawn at the next interval.
|
||||
*/
|
||||
virtual void setDirty() = 0;
|
||||
|
||||
protected:
|
||||
static const uInt32* myPalette;
|
||||
uInt32* myPixels;
|
||||
|
|
|
@ -50,7 +50,8 @@ FrameBuffer::FrameBuffer(OSystem& osystem)
|
|||
myLastScanlines(0),
|
||||
myGrabMouse(false),
|
||||
myCurrentModeList(nullptr)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FrameBuffer::~FrameBuffer()
|
||||
|
@ -258,85 +259,116 @@ FBInitStatus FrameBuffer::createDisplay(const string& title,
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::update()
|
||||
void FrameBuffer::update(bool force)
|
||||
{
|
||||
// Determine which mode we are in (from the EventHandler)
|
||||
// Take care of S_EMULATE mode here, otherwise let the GUI
|
||||
// figure out what to draw
|
||||
// Onscreen messages are a special case and require different handling than
|
||||
// other objects; they aren't UI dialogs in the normal sense nor are they
|
||||
// TIA images, and they need to be rendered on top of everything
|
||||
// The logic is split in two pieces:
|
||||
// - at the top of ::update(), to determine whether underlying dialogs
|
||||
// need to be force-redrawn
|
||||
// - at the bottom of ::update(), to actually draw them (this must come
|
||||
// last, since they are always drawn on top of everything else).
|
||||
|
||||
// Full rendering is required when messages are enabled
|
||||
force |= myMsg.counter >= 0;
|
||||
|
||||
// Detect when a message has been turned off; one last redraw is required
|
||||
// in this case, to draw over the area that the message occupied
|
||||
if(myMsg.counter == 0)
|
||||
myMsg.counter = -1;
|
||||
|
||||
invalidate();
|
||||
switch(myOSystem.eventHandler().state())
|
||||
{
|
||||
case EventHandlerState::NONE:
|
||||
case EventHandlerState::EMULATION:
|
||||
// Do nothing; emulation mode is handled separately (see below)
|
||||
break;
|
||||
return;
|
||||
|
||||
case EventHandlerState::PAUSE:
|
||||
{
|
||||
myTIASurface->render();
|
||||
|
||||
// Show a pause message immediately and then every 7 seconds
|
||||
if (myPausedCount-- <= 0)
|
||||
if(myPausedCount-- <= 0)
|
||||
{
|
||||
myPausedCount = uInt32(7 * myOSystem.frameRate());
|
||||
showMessage("Paused", MessagePosition::MiddleCenter);
|
||||
}
|
||||
if(force)
|
||||
myTIASurface->render();
|
||||
|
||||
break; // EventHandlerState::PAUSE
|
||||
}
|
||||
|
||||
case EventHandlerState::OPTIONSMENU:
|
||||
{
|
||||
myTIASurface->render();
|
||||
myOSystem.menu().draw(true);
|
||||
force |= myOSystem.menu().needsRedraw();
|
||||
if(force)
|
||||
{
|
||||
myTIASurface->render();
|
||||
myOSystem.menu().draw(force);
|
||||
}
|
||||
break; // EventHandlerState::OPTIONSMENU
|
||||
}
|
||||
|
||||
case EventHandlerState::CMDMENU:
|
||||
{
|
||||
myTIASurface->render();
|
||||
myOSystem.commandMenu().draw(true);
|
||||
force |= myOSystem.commandMenu().needsRedraw();
|
||||
if(force)
|
||||
{
|
||||
myTIASurface->render();
|
||||
myOSystem.commandMenu().draw(force);
|
||||
}
|
||||
break; // EventHandlerState::CMDMENU
|
||||
}
|
||||
|
||||
case EventHandlerState::TIMEMACHINE:
|
||||
{
|
||||
myTIASurface->render();
|
||||
myOSystem.timeMachine().draw(true);
|
||||
force |= myOSystem.timeMachine().needsRedraw();
|
||||
if(force)
|
||||
{
|
||||
myTIASurface->render();
|
||||
myOSystem.timeMachine().draw(force);
|
||||
}
|
||||
break; // EventHandlerState::TIMEMACHINE
|
||||
}
|
||||
|
||||
case EventHandlerState::LAUNCHER:
|
||||
{
|
||||
myOSystem.launcher().draw(true);
|
||||
force |= myOSystem.launcher().draw(force);
|
||||
break; // EventHandlerState::LAUNCHER
|
||||
}
|
||||
|
||||
case EventHandlerState::DEBUGGER:
|
||||
{
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
myOSystem.debugger().draw(true);
|
||||
force |= myOSystem.debugger().draw(force);
|
||||
#endif
|
||||
break; // EventHandlerState::DEBUGGER
|
||||
}
|
||||
|
||||
case EventHandlerState::NONE:
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw any pending messages
|
||||
// The logic here determines whether to draw the message
|
||||
// If the message is to be disabled, logic inside the draw method
|
||||
// indicates that, and then the code at the top of this method sees
|
||||
// the change and redraws everything
|
||||
if(myMsg.enabled)
|
||||
drawMessage();
|
||||
force |= drawMessage();
|
||||
|
||||
// Do any post-frame stuff
|
||||
postFrameUpdate();
|
||||
// Push buffers to screen only when necessary
|
||||
if(force)
|
||||
renderToScreen();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::updateInEmulationMode()
|
||||
{
|
||||
// Determine which mode we are in (from the EventHandler)
|
||||
// Take care of S_EMULATE mode here, otherwise let the GUI
|
||||
// figure out what to draw
|
||||
// Update method that is specifically tailored to emulation mode
|
||||
// Typically called from a thread, so it needs to be separate from
|
||||
// the normal update() method
|
||||
//
|
||||
// We don't worry about selective rendering here; the rendering
|
||||
// always happens at the full framerate
|
||||
|
||||
myTIASurface->render();
|
||||
|
||||
|
@ -351,8 +383,8 @@ void FrameBuffer::updateInEmulationMode()
|
|||
if(myMsg.enabled)
|
||||
drawMessage();
|
||||
|
||||
// Do any post-frame stuff
|
||||
postFrameUpdate();
|
||||
// Push buffers to screen
|
||||
renderToScreen();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -413,7 +445,6 @@ void FrameBuffer::drawFrameStats()
|
|||
myStatsMsg.surface->drawString(font(), bsinfo, XPOS, YPOS + font().getFontHeight(),
|
||||
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
|
||||
|
||||
myStatsMsg.surface->setDirty();
|
||||
myStatsMsg.surface->setDstPos(myImageRect.x() + 10, myImageRect.y() + 8);
|
||||
myStatsMsg.surface->render();
|
||||
}
|
||||
|
@ -448,13 +479,26 @@ void FrameBuffer::enableMessages(bool enable)
|
|||
// Erase old messages on the screen
|
||||
myMsg.enabled = false;
|
||||
myMsg.counter = 0;
|
||||
update(); // Force update immediately
|
||||
update(true); // Force update immediately
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
inline void FrameBuffer::drawMessage()
|
||||
inline bool FrameBuffer::drawMessage()
|
||||
{
|
||||
// Either erase the entire message (when time is reached),
|
||||
// or show again this frame
|
||||
if(myMsg.counter == 0)
|
||||
{
|
||||
myMsg.enabled = false;
|
||||
return true;
|
||||
}
|
||||
else if(myMsg.counter < 0)
|
||||
{
|
||||
myMsg.enabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Draw the bounded box and text
|
||||
const GUI::Rect& dst = myMsg.surface->dstRect();
|
||||
|
||||
|
@ -511,16 +555,10 @@ inline void FrameBuffer::drawMessage()
|
|||
myMsg.surface->frameRect(0, 0, myMsg.w, myMsg.h, kColor);
|
||||
myMsg.surface->drawString(font(), myMsg.text, 5, 4,
|
||||
myMsg.w, myMsg.color, TextAlign::Left);
|
||||
myMsg.surface->render();
|
||||
myMsg.counter--;
|
||||
|
||||
// Either erase the entire message (when time is reached),
|
||||
// or show again this frame
|
||||
if(myMsg.counter-- > 0)
|
||||
{
|
||||
myMsg.surface->setDirty();
|
||||
myMsg.surface->render();
|
||||
}
|
||||
else
|
||||
myMsg.enabled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -564,6 +602,8 @@ void FrameBuffer::resetSurfaces()
|
|||
|
||||
freeSurfaces();
|
||||
reloadSurfaces();
|
||||
|
||||
update(true); // force full update
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -589,6 +629,8 @@ void FrameBuffer::stateChanged(EventHandlerState state)
|
|||
// Make sure any onscreen messages are removed
|
||||
myMsg.enabled = false;
|
||||
myMsg.counter = 0;
|
||||
|
||||
update(true); // force full update
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -113,10 +113,9 @@ class FrameBuffer
|
|||
|
||||
/**
|
||||
Updates the display, which depending on the current mode could mean
|
||||
drawing the TIA, any pending menus, etc. Returns the numbers of CPU cycles
|
||||
spent during emulation, or -1 if not applicable.
|
||||
drawing the TIA, any pending menus, etc.
|
||||
*/
|
||||
void update();
|
||||
void update(bool force = false);
|
||||
|
||||
/**
|
||||
There is a dedicated update method for emulation mode.
|
||||
|
@ -379,9 +378,10 @@ class FrameBuffer
|
|||
virtual void setWindowIcon() = 0;
|
||||
|
||||
/**
|
||||
This method is called after any drawing is done (per-frame).
|
||||
This method must be called after all drawing is done, and indicates
|
||||
that the buffers should be pushed to the physical screen.
|
||||
*/
|
||||
virtual void postFrameUpdate() = 0;
|
||||
virtual void renderToScreen() = 0;
|
||||
|
||||
/**
|
||||
This method is called to provide information about the FrameBuffer.
|
||||
|
@ -398,8 +398,10 @@ class FrameBuffer
|
|||
private:
|
||||
/**
|
||||
Draw pending messages.
|
||||
|
||||
@return Indicates whether any changes actually occurred.
|
||||
*/
|
||||
void drawMessage();
|
||||
bool drawMessage();
|
||||
|
||||
/**
|
||||
Frees and reloads all surfaces that the framebuffer knows about.
|
||||
|
@ -521,7 +523,7 @@ class FrameBuffer
|
|||
bool enabled;
|
||||
|
||||
Message()
|
||||
: counter(0), x(0), y(0), w(0), h(0), position(MessagePosition::BottomCenter),
|
||||
: counter(-1), x(0), y(0), w(0), h(0), position(MessagePosition::BottomCenter),
|
||||
color(0), enabled(false) { }
|
||||
};
|
||||
Message myMsg;
|
||||
|
|
|
@ -704,8 +704,8 @@ void OSystem::mainLoop()
|
|||
// Dispatch emulation and render frame (if applicable)
|
||||
timesliceSeconds = dispatchEmulation(emulationWorker);
|
||||
else {
|
||||
// Render the GUI with 30 Hz in all other modes
|
||||
timesliceSeconds = 1. / 30.;
|
||||
// Render the GUI with 60 Hz in all other modes
|
||||
timesliceSeconds = 1. / 60.;
|
||||
myFrameBuffer->update();
|
||||
}
|
||||
|
||||
|
|
|
@ -206,7 +206,6 @@ uInt32 TIASurface::enableScanlines(int relative, int absolute)
|
|||
attr.blendalpha = std::min(100u, attr.blendalpha);
|
||||
|
||||
mySLineSurface->applyAttributes();
|
||||
mySLineSurface->setDirty();
|
||||
|
||||
return attr.blendalpha;
|
||||
}
|
||||
|
@ -217,7 +216,6 @@ void TIASurface::enableScanlineInterpolation(bool enable)
|
|||
FBSurface::Attributes& attr = mySLineSurface->attributes();
|
||||
attr.smoothing = enable;
|
||||
mySLineSurface->applyAttributes();
|
||||
mySLineSurface->setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -231,8 +229,6 @@ void TIASurface::enablePhosphor(bool enable, int blend)
|
|||
myPhosphorPercent = blend / 100.0;
|
||||
myFilter = Filter(enable ? uInt8(myFilter) | 0x01 : uInt8(myFilter) & 0x10);
|
||||
|
||||
myTiaSurface->setDirty();
|
||||
mySLineSurface->setDirty();
|
||||
memset(myRGBFramebuffer, 0, sizeof(myRGBFramebuffer));
|
||||
|
||||
// Precalculate the average colors for the 'phosphor' effect
|
||||
|
@ -283,8 +279,6 @@ void TIASurface::enableNTSC(bool enable)
|
|||
sl_attr.blendalpha = myOSystem.settings().getInt("tv.scanlines");
|
||||
mySLineSurface->applyAttributes();
|
||||
|
||||
myTiaSurface->setDirty();
|
||||
mySLineSurface->setDirty();
|
||||
memset(myRGBFramebuffer, 0, sizeof(myRGBFramebuffer));
|
||||
}
|
||||
|
||||
|
@ -379,15 +373,11 @@ void TIASurface::render()
|
|||
}
|
||||
|
||||
// Draw TIA image
|
||||
myTiaSurface->setDirty();
|
||||
myTiaSurface->render();
|
||||
|
||||
// Draw overlaying scanlines
|
||||
if(myScanlinesEnabled)
|
||||
{
|
||||
mySLineSurface->setDirty();
|
||||
mySLineSurface->render();
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -424,14 +414,10 @@ void TIASurface::reRender()
|
|||
if (myUsePhosphor)
|
||||
{
|
||||
// Draw TIA image
|
||||
myTiaSurface->setDirty();
|
||||
myTiaSurface->render();
|
||||
|
||||
// Draw overlaying scanlines
|
||||
if (myScanlinesEnabled)
|
||||
{
|
||||
mySLineSurface->setDirty();
|
||||
mySLineSurface->render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@ void AboutDialog::displayInfo()
|
|||
}
|
||||
|
||||
// Redraw entire dialog
|
||||
_dirty = true;
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -186,7 +186,6 @@ void AudioDialog::updateSettingsWithPreset(AudioSettings& audioSettings)
|
|||
myResamplingPopup->setSelected(static_cast<int>(audioSettings.resamplingQuality()));
|
||||
}
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AudioDialog::saveConfig()
|
||||
{
|
||||
|
@ -235,8 +234,6 @@ void AudioDialog::setDefaults()
|
|||
else updatePreset();
|
||||
|
||||
updateEnabledState();
|
||||
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -118,7 +118,7 @@ void ComboDialog::setDefaults()
|
|||
for(int i = 0; i < 8; ++i)
|
||||
myEvents[i]->setSelected("None", "-1");
|
||||
|
||||
_dirty = true;
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -546,45 +546,38 @@ void ContextMenu::drawDialog()
|
|||
// by the ScummVM guys, so I'm not going to mess with it.
|
||||
FBSurface& s = surface();
|
||||
|
||||
if(_dirty)
|
||||
// Draw menu border and background
|
||||
s.fillRect(_x+1, _y+1, _w-2, _h-2, kWidColor);
|
||||
s.frameRect(_x, _y, _w, _h, kTextColor);
|
||||
|
||||
// Draw the entries, taking scroll buttons into account
|
||||
int x = _x + 1, y = _y + 1, w = _w - 2;
|
||||
|
||||
// Show top scroll area
|
||||
int offset = _selectedOffset;
|
||||
if(_showScroll)
|
||||
{
|
||||
// Draw menu border and background
|
||||
s.fillRect(_x+1, _y+1, _w-2, _h-2, kWidColor);
|
||||
s.frameRect(_x, _y, _w, _h, kTextColor);
|
||||
|
||||
// Draw the entries, taking scroll buttons into account
|
||||
int x = _x + 1, y = _y + 1, w = _w - 2;
|
||||
|
||||
// Show top scroll area
|
||||
int offset = _selectedOffset;
|
||||
if(_showScroll)
|
||||
{
|
||||
s.hLine(x, y+_rowHeight-1, w+2, kColor);
|
||||
s.drawBitmap(up_arrow, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollUpColor, 8);
|
||||
y += _rowHeight;
|
||||
offset--;
|
||||
}
|
||||
|
||||
for(int i = _firstEntry, current = 0; i < _firstEntry + _numEntries; ++i, ++current)
|
||||
{
|
||||
bool hilite = offset == current;
|
||||
if(hilite) s.fillRect(x, y, w, _rowHeight, kTextColorHi);
|
||||
s.drawString(_font, _entries[i].first, x + 1, y + 2, w,
|
||||
!hilite ? kTextColor : kTextColorInv);
|
||||
y += _rowHeight;
|
||||
}
|
||||
|
||||
// Show bottom scroll area
|
||||
if(_showScroll)
|
||||
{
|
||||
s.hLine(x, y, w+2, kColor);
|
||||
s.drawBitmap(down_arrow, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollDnColor, 8);
|
||||
}
|
||||
|
||||
s.setDirty();
|
||||
_dirty = false;
|
||||
s.hLine(x, y+_rowHeight-1, w+2, kColor);
|
||||
s.drawBitmap(up_arrow, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollUpColor, 8);
|
||||
y += _rowHeight;
|
||||
offset--;
|
||||
}
|
||||
|
||||
// Commit surface changes to screen
|
||||
s.render();
|
||||
for(int i = _firstEntry, current = 0; i < _firstEntry + _numEntries; ++i, ++current)
|
||||
{
|
||||
bool hilite = offset == current;
|
||||
if(hilite) s.fillRect(x, y, w, _rowHeight, kTextColorHi);
|
||||
s.drawString(_font, _entries[i].first, x + 1, y + 2, w,
|
||||
!hilite ? kTextColor : kTextColorInv);
|
||||
y += _rowHeight;
|
||||
}
|
||||
|
||||
// Show bottom scroll area
|
||||
if(_showScroll)
|
||||
{
|
||||
s.hLine(x, y, w+2, kColor);
|
||||
s.drawBitmap(down_arrow, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollDnColor, 8);
|
||||
}
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ Dialog::Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font
|
|||
_flags(WIDGET_ENABLED | WIDGET_BORDER | WIDGET_CLEARBG)
|
||||
{
|
||||
setTitle(title);
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -86,7 +87,7 @@ Dialog::~Dialog()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Dialog::open(bool refresh)
|
||||
void Dialog::open()
|
||||
{
|
||||
// Make sure we have a valid surface to draw into
|
||||
// Technically, this shouldn't be needed until drawDialog(), but some
|
||||
|
@ -103,10 +104,12 @@ void Dialog::open(bool refresh)
|
|||
buildCurrentFocusList();
|
||||
|
||||
_visible = true;
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Dialog::close(bool refresh)
|
||||
void Dialog::close()
|
||||
{
|
||||
if (_mouseWidget)
|
||||
{
|
||||
|
@ -119,6 +122,7 @@ void Dialog::close(bool refresh)
|
|||
_visible = false;
|
||||
|
||||
parent().removeDialog();
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -131,6 +135,8 @@ void Dialog::setTitle(const string& title)
|
|||
else
|
||||
_th = _font.getLineHeight() + 4;
|
||||
_h += _th;
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -144,6 +150,29 @@ void Dialog::center()
|
|||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Dialog::render()
|
||||
{
|
||||
if(!_dirty)
|
||||
return false;
|
||||
|
||||
// Draw this dialog
|
||||
center();
|
||||
drawDialog();
|
||||
|
||||
// Update dialog surface; also render any extra surfaces
|
||||
// Extra surfaces must be rendered afterwards, so they are drawn on top
|
||||
if(_surface->render())
|
||||
{
|
||||
mySurfaceStack.applyAll([](shared_ptr<FBSurface>& surface){
|
||||
surface->render();
|
||||
});
|
||||
}
|
||||
_dirty = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Dialog::releaseFocus()
|
||||
{
|
||||
|
@ -291,6 +320,7 @@ void Dialog::addSurface(shared_ptr<FBSurface> surface)
|
|||
mySurfaceStack.push(surface);
|
||||
}
|
||||
|
||||
static int COUNT = 1;
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Dialog::drawDialog()
|
||||
{
|
||||
|
@ -299,63 +329,46 @@ void Dialog::drawDialog()
|
|||
|
||||
FBSurface& s = surface();
|
||||
|
||||
if(_dirty)
|
||||
cerr << COUNT++ << " Dialog::drawDialog()\n";
|
||||
// Dialog is still on top if e.g a ContextMenu is opened
|
||||
bool onTop = parent().myDialogStack.top() == this
|
||||
|| (parent().myDialogStack.get(parent().myDialogStack.size() - 2) == this
|
||||
&& !parent().myDialogStack.top()->hasTitle());
|
||||
|
||||
if(_flags & WIDGET_CLEARBG)
|
||||
{
|
||||
// dialog is still on top if e.g a ContextMenu is opened
|
||||
bool onTop = parent().myDialogStack.top() == this
|
||||
|| (parent().myDialogStack.get(parent().myDialogStack.size() - 2) == this
|
||||
&& !parent().myDialogStack.top()->hasTitle());
|
||||
|
||||
if(_flags & WIDGET_CLEARBG)
|
||||
// cerr << "Dialog::drawDialog(): w = " << _w << ", h = " << _h << " @ " << &s << endl << endl;
|
||||
s.fillRect(_x, _y + _th, _w, _h - _th, onTop ? kDlgColor : kBGColorLo);
|
||||
if(_th)
|
||||
{
|
||||
// cerr << "Dialog::drawDialog(): w = " << _w << ", h = " << _h << " @ " << &s << endl << endl;
|
||||
s.fillRect(_x, _y + _th, _w, _h - _th, onTop ? kDlgColor : kBGColorLo);
|
||||
if(_th)
|
||||
{
|
||||
s.fillRect(_x, _y, _w, _th, onTop ? kColorTitleBar : kColorTitleBarLo);
|
||||
s.drawString(_font, _title, _x + 10, _y + 2 + 1, _font.getStringWidth(_title),
|
||||
onTop ? kColorTitleText : kColorTitleTextLo);
|
||||
}
|
||||
s.fillRect(_x, _y, _w, _th, onTop ? kColorTitleBar : kColorTitleBarLo);
|
||||
s.drawString(_font, _title, _x + 10, _y + 2 + 1, _font.getStringWidth(_title),
|
||||
onTop ? kColorTitleText : kColorTitleTextLo);
|
||||
}
|
||||
else
|
||||
s.invalidate();
|
||||
if(_flags & WIDGET_BORDER)
|
||||
s.frameRect(_x, _y, _w, _h, onTop ? kColor : kShadowColor);
|
||||
}
|
||||
else
|
||||
s.invalidate();
|
||||
if(_flags & WIDGET_BORDER)
|
||||
s.frameRect(_x, _y, _w, _h, onTop ? kColor : kShadowColor);
|
||||
|
||||
// Make all child widget dirty
|
||||
Widget* w = _firstWidget;
|
||||
Widget::setDirtyInChain(w);
|
||||
// Make all child widget dirty
|
||||
Widget* w = _firstWidget;
|
||||
Widget::setDirtyInChain(w);
|
||||
|
||||
// Draw all children
|
||||
w = _firstWidget;
|
||||
while(w)
|
||||
{
|
||||
w->draw();
|
||||
w = w->_next;
|
||||
}
|
||||
|
||||
// Draw outlines for focused widgets
|
||||
// Don't change focus, since this will trigger lost and received
|
||||
// focus events
|
||||
if(_focusedWidget)
|
||||
_focusedWidget = Widget::setFocusForChain(this, getFocusList(),
|
||||
_focusedWidget, 0, false);
|
||||
|
||||
// Tell the surface(s) this area is dirty
|
||||
s.setDirty();
|
||||
|
||||
_dirty = false;
|
||||
// Draw all children
|
||||
w = _firstWidget;
|
||||
while(w)
|
||||
{
|
||||
w->draw();
|
||||
w = w->_next;
|
||||
}
|
||||
|
||||
// Commit surface changes to screen; also render any extra surfaces
|
||||
// Extra surfaces must be rendered afterwards, so they are drawn on top
|
||||
if(s.render())
|
||||
{
|
||||
mySurfaceStack.applyAll([](shared_ptr<FBSurface>& surface){
|
||||
surface->setDirty();
|
||||
surface->render();
|
||||
});
|
||||
}
|
||||
// Draw outlines for focused widgets
|
||||
// Don't change focus, since this will trigger lost and received
|
||||
// focus events
|
||||
if(_focusedWidget)
|
||||
_focusedWidget = Widget::setFocusForChain(this, getFocusList(),
|
||||
_focusedWidget, 0, false);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -51,8 +51,8 @@ class Dialog : public GuiObject
|
|||
|
||||
virtual ~Dialog();
|
||||
|
||||
void open(bool refresh = true);
|
||||
void close(bool refresh = true);
|
||||
void open();
|
||||
void close();
|
||||
|
||||
bool isVisible() const override { return _visible; }
|
||||
|
||||
|
@ -62,6 +62,12 @@ class Dialog : public GuiObject
|
|||
virtual void saveConfig() { }
|
||||
virtual void setDefaults() { }
|
||||
|
||||
// A dialog being dirty indicates that its underlying surface needs to be
|
||||
// redrawn and then re-rendered; this is taken care of in ::render()
|
||||
void setDirty() override { _dirty = true; }
|
||||
bool isDirty() const { return _dirty; }
|
||||
bool render();
|
||||
|
||||
void addFocusWidget(Widget* w) override;
|
||||
void addToFocusList(WidgetArray& list) override;
|
||||
void addToFocusList(WidgetArray& list, TabWidget* w, int tabId);
|
||||
|
@ -190,6 +196,7 @@ class Dialog : public GuiObject
|
|||
|
||||
int _tabID;
|
||||
int _flags;
|
||||
bool _dirty;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -48,12 +48,12 @@ DialogContainer::~DialogContainer()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DialogContainer::updateTime(uInt64 time)
|
||||
{
|
||||
// We only need millisecond precision
|
||||
myTime = time / 1000;
|
||||
|
||||
if(myDialogStack.empty())
|
||||
return;
|
||||
|
||||
// We only need millisecond precision
|
||||
myTime = time / 1000;
|
||||
|
||||
// Check for pending continuous events and send them to the active dialog box
|
||||
Dialog* activeDialog = myDialogStack.top();
|
||||
|
||||
|
@ -98,19 +98,31 @@ void DialogContainer::updateTime(uInt64 time)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DialogContainer::draw(bool full)
|
||||
bool DialogContainer::draw(bool full)
|
||||
{
|
||||
// Draw all the dialogs on the stack when we want a full refresh
|
||||
if(myDialogStack.empty())
|
||||
return false;
|
||||
|
||||
// Make the top dialog dirty if a full redraw is requested
|
||||
if(full)
|
||||
{
|
||||
myDialogStack.applyAll([](Dialog*& d){
|
||||
d->center();
|
||||
myDialogStack.top()->setDirty();
|
||||
|
||||
// If the top dialog is dirty, then all below it must be redrawn too
|
||||
bool dirty = needsRedraw();
|
||||
|
||||
myDialogStack.applyAll([&](Dialog*& d){
|
||||
if(dirty)
|
||||
d->setDirty();
|
||||
d->drawDialog();
|
||||
});
|
||||
}
|
||||
else if(!myDialogStack.empty())
|
||||
myDialogStack.top()->drawDialog();
|
||||
full |= d->render();
|
||||
});
|
||||
|
||||
return full;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool DialogContainer::needsRedraw() const
|
||||
{
|
||||
return !myDialogStack.empty() ? myDialogStack.top()->isDirty() : false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -121,14 +133,21 @@ void DialogContainer::addDialog(Dialog* d)
|
|||
myOSystem.frameBuffer().showMessage(
|
||||
"Unable to show dialog box; FIX THE CODE");
|
||||
else
|
||||
{
|
||||
d->setDirty();
|
||||
myDialogStack.push(d);
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DialogContainer::removeDialog()
|
||||
{
|
||||
if(!myDialogStack.empty())
|
||||
{
|
||||
myDialogStack.pop();
|
||||
if(!myDialogStack.empty())
|
||||
myDialogStack.top()->setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -136,9 +155,9 @@ void DialogContainer::reStack()
|
|||
{
|
||||
// Pop all items from the stack, and then add the base menu
|
||||
while(!myDialogStack.empty())
|
||||
myDialogStack.top()->close(false); // don't force a refresh
|
||||
myDialogStack.top()->close();
|
||||
|
||||
myBaseDialog->open(false); // don't force a refresh
|
||||
myBaseDialog->open();
|
||||
|
||||
// Reset all continuous events
|
||||
reset();
|
||||
|
|
|
@ -121,8 +121,15 @@ class DialogContainer
|
|||
|
||||
/**
|
||||
Draw the stack of menus (full indicates to redraw all items).
|
||||
|
||||
@return Answers whether any drawing actually occurred.
|
||||
*/
|
||||
void draw(bool full = false);
|
||||
bool draw(bool full = false);
|
||||
|
||||
/**
|
||||
Answers whether a full redraw is required.
|
||||
*/
|
||||
bool needsRedraw() const;
|
||||
|
||||
/**
|
||||
Reset dialog stack to the main configuration menu.
|
||||
|
|
|
@ -274,8 +274,6 @@ void GlobalPropsDialog::setDefaults()
|
|||
|
||||
myHoldSelect->setState(false);
|
||||
myHoldReset->setState(false);
|
||||
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -60,7 +60,6 @@ class GuiObject : public CommandReceiver
|
|||
myParent(parent),
|
||||
myDialog(dialog),
|
||||
_x(x), _y(y), _w(w), _h(h),
|
||||
_dirty(false),
|
||||
_firstWidget(nullptr) { }
|
||||
|
||||
virtual ~GuiObject() = default;
|
||||
|
@ -69,8 +68,6 @@ class GuiObject : public CommandReceiver
|
|||
DialogContainer& parent() const { return myParent; }
|
||||
Dialog& dialog() const { return myDialog; }
|
||||
|
||||
void setDirty() { _dirty = true; }
|
||||
|
||||
virtual int getAbsX() const { return _x; }
|
||||
virtual int getAbsY() const { return _y; }
|
||||
virtual int getChildX() const { return getAbsX(); }
|
||||
|
@ -82,6 +79,7 @@ class GuiObject : public CommandReceiver
|
|||
virtual void setHeight(int h) { _h = h; }
|
||||
|
||||
virtual bool isVisible() const = 0;
|
||||
virtual void setDirty() = 0;
|
||||
|
||||
/** Add given widget(s) to the focus list */
|
||||
virtual void addFocusWidget(Widget* w) = 0;
|
||||
|
@ -107,7 +105,6 @@ class GuiObject : public CommandReceiver
|
|||
|
||||
protected:
|
||||
int _x, _y, _w, _h;
|
||||
bool _dirty;
|
||||
|
||||
Widget* _firstWidget;
|
||||
WidgetArray _focusList;
|
||||
|
|
|
@ -185,8 +185,6 @@ void HelpDialog::displayInfo()
|
|||
myKey[i]->setLabel(myKeyStr[i]);
|
||||
myDesc[i]->setLabel(myDescStr[i]);
|
||||
}
|
||||
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -399,8 +399,6 @@ void InputDialog::setDefaults()
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -178,8 +178,6 @@ void LauncherFilterDialog::saveConfig()
|
|||
void LauncherFilterDialog::setDefaults()
|
||||
{
|
||||
handleFileTypeChange("allroms");
|
||||
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -62,11 +62,10 @@ ListWidget::ListWidget(GuiObject* boss, const GUI::Font& font,
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void ListWidget::setSelected(int item)
|
||||
{
|
||||
setDirty();
|
||||
|
||||
if(item < 0 || item >= int(_list.size()))
|
||||
{
|
||||
setDirty(); // Simply redraw and exit
|
||||
return;
|
||||
}
|
||||
|
||||
if(isEnabled())
|
||||
{
|
||||
|
@ -180,6 +179,8 @@ void ListWidget::recalc()
|
|||
|
||||
// Reset to normal data entry
|
||||
abortEditMode();
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -279,8 +279,6 @@ void UIDialog::setDefaults()
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -551,8 +551,6 @@ void VideoDialog::setDefaults()
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -580,8 +578,6 @@ void VideoDialog::handleTVModeChange(NTSCFilter::Preset preset)
|
|||
myTVScanLabel->setEnabled(scanenable);
|
||||
myTVScanIntense->setEnabled(scanenable);
|
||||
myTVScanInterpolate->setEnabled(scanenable);
|
||||
|
||||
_dirty = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -48,6 +48,8 @@ Widget::Widget(GuiObject* boss, const GUI::Font& font,
|
|||
|
||||
_fontWidth = _font.getMaxCharWidth();
|
||||
_fontHeight = _font.getLineHeight();
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -59,14 +61,20 @@ Widget::~Widget()
|
|||
_focusList.clear();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Widget::setDirty()
|
||||
{
|
||||
// A widget being dirty indicates that its parent dialog is dirty
|
||||
// So we inform the parent about it
|
||||
_boss->dialog().setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Widget::draw()
|
||||
{
|
||||
if(!_dirty || !isVisible() || !_boss->isVisible())
|
||||
if(!isVisible() || !_boss->isVisible())
|
||||
return;
|
||||
|
||||
_dirty = false;
|
||||
|
||||
FBSurface& s = _boss->dialog().surface();
|
||||
|
||||
bool hasBorder = _flags & WIDGET_BORDER;
|
||||
|
@ -119,9 +127,6 @@ void Widget::draw()
|
|||
w->draw();
|
||||
w = w->_next;
|
||||
}
|
||||
|
||||
// Tell the framebuffer this area is dirty
|
||||
s.setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -224,7 +229,6 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr,
|
|||
s.frameRect(x, y, w, h, kDlgColor);
|
||||
|
||||
tmp->setDirty();
|
||||
s.setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,7 +282,6 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr,
|
|||
s.frameRect(x, y, w, h, kWidFrameColor, FrameStyle::Dashed);
|
||||
|
||||
tmp->setDirty();
|
||||
s.setDirty();
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
@ -346,6 +349,8 @@ void StaticTextWidget::drawWidget(bool hilite)
|
|||
FBSurface& s = _boss->dialog().surface();
|
||||
s.drawString(_font, _label, _x, _y, _w,
|
||||
isEnabled() ? _textcolor : uInt32(kColor), _align, 0, true, _shadowcolor);
|
||||
|
||||
_boss->dialog().setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -402,14 +407,12 @@ ButtonWidget::ButtonWidget(GuiObject* boss, const GUI::Font& font,
|
|||
void ButtonWidget::handleMouseEntered()
|
||||
{
|
||||
setFlags(WIDGET_HILITED);
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void ButtonWidget::handleMouseLeft()
|
||||
{
|
||||
clearFlags(WIDGET_HILITED);
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -446,6 +449,8 @@ void ButtonWidget::setBitmap(uInt32* bitmap, int bmw, int bmh)
|
|||
_bmh = bmh;
|
||||
_bmw = bmw;
|
||||
_useBitmap = true;
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -464,6 +469,8 @@ void ButtonWidget::drawWidget(bool hilite)
|
|||
!isEnabled() ? /*hilite ? uInt32(kColor) :*/ uInt32(kBGColorLo) :
|
||||
hilite ? _textcolorhi : _textcolor,
|
||||
_bmw, _bmh);
|
||||
|
||||
_boss->dialog().setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -584,6 +591,7 @@ void CheckboxWidget::setEditable(bool editable)
|
|||
_bgcolor = kBGColorHi;
|
||||
setFill(CheckboxWidget::Inactive);
|
||||
}
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -604,6 +612,7 @@ void CheckboxWidget::setFill(FillType type)
|
|||
_drawBox = false;
|
||||
break;
|
||||
}
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -634,6 +643,8 @@ void CheckboxWidget::drawWidget(bool hilite)
|
|||
// Finally draw the label
|
||||
s.drawString(_font, _label, _x + 20, _y + _textY, _w,
|
||||
isEnabled() ? kTextColor : kColor);
|
||||
|
||||
_boss->dialog().setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -697,18 +708,21 @@ void SliderWidget::setValue(int value)
|
|||
void SliderWidget::setMinValue(int value)
|
||||
{
|
||||
_valueMin = value;
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SliderWidget::setMaxValue(int value)
|
||||
{
|
||||
_valueMax = value;
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SliderWidget::setStepValue(int value)
|
||||
{
|
||||
_stepValue = value;
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -868,10 +882,12 @@ void SliderWidget::drawWidget(bool hilite)
|
|||
if(_valueLabelWidth > 0)
|
||||
s.drawString(_font, _valueLabel + _valueUnit, _x + _w - _valueLabelWidth, _y + 2,
|
||||
_valueLabelWidth, isEnabled() ? kTextColor : kColor);
|
||||
|
||||
_boss->dialog().setDirty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int SliderWidget::valueToPos(int value)
|
||||
int SliderWidget::valueToPos(int value) const
|
||||
{
|
||||
if(value < _valueMin) value = _valueMin;
|
||||
else if(value > _valueMax) value = _valueMax;
|
||||
|
@ -881,7 +897,7 @@ int SliderWidget::valueToPos(int value)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int SliderWidget::posToValue(int pos)
|
||||
int SliderWidget::posToValue(int pos) const
|
||||
{
|
||||
int value = (pos) * (_valueMax - _valueMin) / (_w - _labelWidth - _valueLabelGap - _valueLabelWidth - 4) + _valueMin;
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ class Widget : public GuiObject
|
|||
virtual bool handleJoyHat(int stick, int hat, JoyHat value) { return false; }
|
||||
virtual bool handleEvent(Event::Type event) { return false; }
|
||||
|
||||
void setDirty() override;
|
||||
void draw() override;
|
||||
void receivedFocus();
|
||||
void lostFocus();
|
||||
|
@ -108,11 +109,11 @@ class Widget : public GuiObject
|
|||
|
||||
virtual const GUI::Font& font() const { return _font; }
|
||||
|
||||
void setTextColor(uInt32 color) { _textcolor = color; }
|
||||
void setTextColorHi(uInt32 color) { _textcolorhi = color; }
|
||||
void setBGColor(uInt32 color) { _bgcolor = color; }
|
||||
void setBGColorHi(uInt32 color) { _bgcolorhi = color; }
|
||||
void setShadowColor(uInt32 color) { _shadowcolor = color; }
|
||||
void setTextColor(uInt32 color) { _textcolor = color; setDirty(); }
|
||||
void setTextColorHi(uInt32 color) { _textcolorhi = color; setDirty(); }
|
||||
void setBGColor(uInt32 color) { _bgcolor = color; setDirty(); }
|
||||
void setBGColorHi(uInt32 color) { _bgcolorhi = color; setDirty(); }
|
||||
void setShadowColor(uInt32 color) { _shadowcolor = color; setDirty(); }
|
||||
|
||||
virtual void loadConfig() { }
|
||||
|
||||
|
@ -187,7 +188,7 @@ class StaticTextWidget : public Widget
|
|||
uInt32 shadowColor = 0);
|
||||
void setValue(int value);
|
||||
void setLabel(const string& label);
|
||||
void setAlign(TextAlign align) { _align = align; }
|
||||
void setAlign(TextAlign align) { _align = align; setDirty(); }
|
||||
const string& getLabel() const { return _label; }
|
||||
bool isEditable() const { return _editable; }
|
||||
|
||||
|
@ -341,8 +342,8 @@ class SliderWidget : public ButtonWidget
|
|||
|
||||
void drawWidget(bool hilite) override;
|
||||
|
||||
int valueToPos(int value);
|
||||
int posToValue(int pos);
|
||||
int valueToPos(int value) const;
|
||||
int posToValue(int pos) const;
|
||||
|
||||
protected:
|
||||
int _value, _stepValue;
|
||||
|
|
Loading…
Reference in New Issue