Skip to content

Commit

Permalink
Fixed ui bug when moving window to another screen.
Browse files Browse the repository at this point in the history
  • Loading branch information
Matias Hyry committed Mar 5, 2014
1 parent 76e98d2 commit 2ed7fa6
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/Core/OgreRenderingModule/OgreModuleFwd.h
Expand Up @@ -41,6 +41,7 @@ typedef shared_ptr<Ogre::Root> OgreRootPtr;
namespace OgreRenderer
{
class OgreRenderingModule;
class OgreRenderSystemListener;
class Renderer;
typedef shared_ptr<Renderer> RendererPtr;
typedef weak_ptr<Renderer> RendererWeakPtr;
Expand Down
54 changes: 54 additions & 0 deletions src/Core/OgreRenderingModule/OgreRenderingModule.cpp
Expand Up @@ -202,6 +202,12 @@ void OgreRenderingModule::Initialize()
#endif
framework_->Console()->RegisterCommand("setMaterialAttribute", "Sets an attribute on a material asset",
this, SLOT(SetMaterialAttribute(const QStringList &)));

// Create and add Ogre rendersystem listener.
renderSystemListener = new OgreRenderSystemListener(this);
if(!renderSystemListener)

This comment has been minimized.

Copy link
@Stinkfist0

Stinkfist0 Mar 5, 2014

How can this be null? Assuming we don't run out of memory, in which case we probably gonna crash anyways.

return;
Ogre::Root::getSingleton().getRenderSystem()->addListener(renderSystemListener);
}

void OgreRenderingModule::Uninitialize()
Expand All @@ -212,6 +218,12 @@ void OgreRenderingModule::Uninitialize()

// Clear up the renderer object, so that it will not be left dangling.
framework_->RegisterRenderer(0);

// Destroy Ogre rendersystem listener.
if(!renderSystemListener)
return;
Ogre::Root::getSingleton().getRenderSystem()->removeListener(renderSystemListener);
delete renderSystemListener;
}

void OgreRenderingModule::ConsoleStats()
Expand Down Expand Up @@ -286,6 +298,48 @@ void OgreRenderingModule::SetMaterialAttribute(const QStringList &params)
matAsset->SetAttribute(params[1], params[2]);
}

void OgreRenderingModule::EmitDeviceLost()
{
emit DeviceLost();
}

void OgreRenderingModule::EmitDeviceRestored()
{
emit DeviceRestored();
}

void OgreRenderingModule::EmitDeviceCreated()
{
emit DeviceCreated();
}

void OgreRenderingModule::EmitDeviceReleased()
{
emit DeviceReleased();
}

OgreRenderSystemListener::OgreRenderSystemListener(OgreRenderingModule* renderingModule) :
_renderingModule(renderingModule)
{}

OgreRenderSystemListener::~OgreRenderSystemListener()
{}

void OgreRenderSystemListener::eventOccurred(const Ogre::String& eventName, const Ogre::NameValuePairList* parameters)
{
if (!_renderingModule)
return;

if (eventName == "DeviceLost")
_renderingModule->EmitDeviceLost();
else if (eventName == "DeviceRestored")
_renderingModule->EmitDeviceRestored();
else if(eventName == "DeviceCreated")
_renderingModule->EmitDeviceCreated();
else if(eventName == "DeviceReleased")
_renderingModule->EmitDeviceReleased();
}

} // ~namespace OgreRenderer

extern "C"
Expand Down
36 changes: 36 additions & 0 deletions src/Core/OgreRenderingModule/OgreRenderingModule.h
Expand Up @@ -6,6 +6,7 @@
#include "OgreModuleApi.h"
#include "OgreModuleFwd.h"
#include "SceneFwd.h"
#include <OgreRenderSystem.h>

namespace OgreRenderer
{
Expand Down Expand Up @@ -40,6 +41,16 @@ namespace OgreRenderer
const RendererPtr &GetRenderer() const { return Renderer(); } /**< @deprecated Use Renderer() instead. @todo Remove. */
/// @endcond

signals:

This comment has been minimized.

Copy link
@Stinkfist0

Stinkfist0 Mar 5, 2014

The signals feel weird in OgreRenderingModule, RenderWindow would be more natural place for them IMO.

/// DirectX device lost signal.
void DeviceLost();
/// DirectX device restored signal.
void DeviceRestored();
/// DirectX device created signal.
void DeviceCreated();
/// DirectX device released signal.
void DeviceReleased();

public slots:
/// Prints renderer stats to console.
void ConsoleStats();
Expand All @@ -57,7 +68,32 @@ namespace OgreRenderer
/// Removes OgreWorld from a Scene.
void RemoveOgreWorld(Scene *scene);

protected:

This comment has been minimized.

Copy link
@Stinkfist0

Stinkfist0 Mar 5, 2014

Can be just simply private too (nothing's gonna inherit OgreRenderingModule, ever).

This comment has been minimized.

Copy link
@jonnenauha

jonnenauha Mar 5, 2014

Member

Friend class cannot access private afaik. The other class below calls these.

This comment has been minimized.

Copy link
@Stinkfist0

Stinkfist0 Mar 5, 2014

Better get your "afaik" up-to-date ;)

This comment has been minimized.

Copy link
@jonnenauha

jonnenauha via email Mar 5, 2014

Member
/// Emit DeviceLost signal.
void EmitDeviceLost();
/// Emit DeviceRestored signal.
void EmitDeviceRestored();
/// Emit DeviceCreated signal.
void EmitDeviceCreated();
/// Emit DeviceReleased signal.
void EmitDeviceReleased();

private:
RendererPtr renderer; ///< Renderer

OgreRenderSystemListener* renderSystemListener;
friend class OgreRenderSystemListener;
};

class OgreRenderSystemListener : public Ogre::RenderSystem::Listener
{
public:
OgreRenderSystemListener(OgreRenderer::OgreRenderingModule* renderingModule);
~OgreRenderSystemListener();

void eventOccurred(const Ogre::String& eventName, const Ogre::NameValuePairList* parameters = 0);

private:
OgreRenderer::OgreRenderingModule* _renderingModule;
};
}
30 changes: 28 additions & 2 deletions src/Core/OgreRenderingModule/RenderWindow.cpp
Expand Up @@ -7,6 +7,7 @@
#include "RenderWindow.h"
#include "CoreStringUtils.h"
#include "ConfigAPI.h"
#include "OgreRenderingModule.h"

#include <QWidget>
#include <QImage>
Expand Down Expand Up @@ -199,18 +200,31 @@ void RenderWindow::CreateRenderWindow(QWidget *targetWindow, const QString &name
#ifndef ANDROID
CreateRenderTargetOverlay(width, height);
#endif

// Hook to DeviceRestored signal
OgreRenderer::OgreRenderingModule* ogreRenderingModule = fw->GetModule<OgreRenderer::OgreRenderingModule>();
if(!ogreRenderingModule)
return;
connect(ogreRenderingModule, SIGNAL(DeviceReleased()), this, SLOT(OnDeviceReleased()));
}

void RenderWindow::CreateRenderTargetOverlay(int width, int height)
{
width = max(1, width);
height = max(1, height);

Ogre::TexturePtr renderTarget = Ogre::TextureManager::getSingleton().createManual(
Ogre::TexturePtr renderTarget = Ogre::TextureManager::getSingleton().getByName(rttTextureName);
if(renderTarget.get())
Ogre::TextureManager::getSingleton().remove(renderTarget->getName());

renderTarget = Ogre::TextureManager::getSingleton().createManual(
rttTextureName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D, width, height, 0, Ogre::PF_A8R8G8B8, Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);

Ogre::MaterialPtr rttMaterial = Ogre::MaterialManager::getSingleton().create(
Ogre::MaterialPtr rttMaterial = Ogre::MaterialManager::getSingleton().getByName(rttMaterialName);
if(rttMaterial.get())
Ogre::MaterialManager::getSingleton().remove(rttMaterial->getName());
rttMaterial = Ogre::MaterialManager::getSingleton().create(
rttMaterialName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

Ogre::TextureUnitState *rttTuState = rttMaterial->getTechnique(0)->getPass(0)->createTextureUnitState();
Expand All @@ -230,13 +244,18 @@ void RenderWindow::CreateRenderTargetOverlay(int width, int height)
rttMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
rttMaterial->getTechnique(0)->getPass(0)->setCullingMode(Ogre::CULL_NONE);

if(Ogre::OverlayManager::getSingleton().hasOverlayElement("MainWindow Overlay Panel"))
Ogre::OverlayManager::getSingleton().destroyOverlayElement("MainWindow Overlay Panel");
overlayContainer = Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "MainWindow Overlay Panel");
overlayContainer->setMaterialName(rttMaterialName);
overlayContainer->setMetricsMode(Ogre::GMM_PIXELS);
overlayContainer->setPosition(0, 0);
overlayContainer->setDimensions((Ogre::Real)width, (Ogre::Real)height);
overlayContainer->setPosition(0,0);

overlay = Ogre::OverlayManager::getSingleton().getByName("MainWindow Overlay");
if(overlay)
Ogre::OverlayManager::getSingleton().destroy(overlay);
overlay = Ogre::OverlayManager::getSingleton().create("MainWindow Overlay");
overlay->add2D(static_cast<Ogre::OverlayContainer *>(overlayContainer));
overlay->setZOrder(500);
Expand Down Expand Up @@ -347,6 +366,13 @@ int RenderWindow::Height() const
return renderWindow->getHeight();
}

void RenderWindow::OnDeviceReleased()
{
int width = renderWindow->getWidth();
int height = renderWindow->getHeight();
CreateRenderTargetOverlay(width, height);
}

#ifdef ANDROID
extern "C" {

Expand Down
4 changes: 4 additions & 0 deletions src/Core/OgreRenderingModule/RenderWindow.h
Expand Up @@ -55,6 +55,10 @@ public slots:

int Height() const;

private slots:
/// Recreate resources when DirectX device is released.
void OnDeviceReleased();

private:
void CreateRenderTargetOverlay(int width, int height);
Ogre::RenderWindow *renderWindow;
Expand Down

2 comments on commit 2ed7fa6

@Stinkfist0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit fixes realXtend#457? How about realXtend#545?

@jonnenauha
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes should fix the first one at least. Only the overlay is now recreted, there might be other places where manual textures need to be recreated (listening to the same signal).

Please sign in to comment.