diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 5ecd1b1b9..f56313ba3 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -273,6 +273,7 @@ namespace MWBase virtual void renderPlayer() = 0; virtual void updateCharacterPreview(int sizeX, int sizeY) = 0; + virtual void updateRaceSelectionPreview(float angle) = 0; }; } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 9ccf5cfe1..9df6d893d 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -106,6 +106,7 @@ namespace MWGui MWBase::Environment::get().getWorld()->updateCharacterPreview (size.width, size.height); mAvatarImage->setSize(MyGUI::IntSize(std::max(mAvatar->getSize().width, 512), std::max(mAvatar->getSize().height, 1024))); + mAvatarImage->setImageTexture("CharacterPreview"); } void InventoryWindow::onFilterChanged(MyGUI::Widget* _sender) @@ -270,6 +271,7 @@ namespace MWGui MWBase::Environment::get().getWorld()->updateCharacterPreview (size.width, size.height); mAvatarImage->setSize(MyGUI::IntSize(512, 1024)); + mAvatarImage->setImageTexture("CharacterPreview"); } void InventoryWindow::pickUpObject (MWWorld::Ptr object) diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 370b30733..e1dc4af1a 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -25,15 +25,17 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) , mHairIndex(0) , mFaceCount(10) , mHairCount(14) + , mCurrentAngle(0) { // Centre dialog center(); - // These are just demo values, you should replace these with - // real calls from outside the class later. - setText("AppearanceT", mWindowManager.getGameSettingString("sRaceMenu1", "Appearance")); - getWidget(mAppearanceBox, "AppearanceBox"); + getWidget(mPreviewImage, "PreviewImage"); + + MWBase::Environment::get().getWorld ()->updateRaceSelectionPreview (0); + + mPreviewImage->setImageTexture ("CharacterHeadPreview"); getWidget(mHeadRotate, "HeadRotate"); mHeadRotate->setScrollRange(50); @@ -149,7 +151,10 @@ void RaceDialog::onBackClicked(MyGUI::Widget* _sender) void RaceDialog::onHeadRotate(MyGUI::ScrollBar*, size_t _position) { - // TODO: Rotate head + float angle = (float(_position) / 49.f - 0.5) * 3.14 * 2; + float diff = angle - mCurrentAngle; + MWBase::Environment::get().getWorld ()->updateRaceSelectionPreview (diff); + mCurrentAngle += diff; } void RaceDialog::onSelectPreviousGender(MyGUI::Widget*) diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index 4aded28c3..c1517eb76 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -73,7 +73,7 @@ namespace MWGui void updateSkills(); void updateSpellPowers(); - MyGUI::CanvasPtr mAppearanceBox; + MyGUI::ImageBox* mPreviewImage; MyGUI::ListBox* mRaceList; MyGUI::ScrollBar* mHeadRotate; @@ -87,6 +87,8 @@ namespace MWGui int mFaceCount, mHairCount; std::string mCurrentRaceId; + + float mCurrentAngle; }; } #endif diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp index 415d17241..15c89d7f5 100644 --- a/apps/openmw/mwrender/actors.cpp +++ b/apps/openmw/mwrender/actors.cpp @@ -3,6 +3,8 @@ #include #include +#include "renderconst.hpp" + using namespace Ogre; using namespace MWRender; @@ -23,7 +25,7 @@ void Actors::setMwRoot(Ogre::SceneNode* root){ void Actors::insertNPC(const MWWorld::Ptr& ptr, MWWorld::InventoryStore& inv){ insertBegin(ptr, true, true); - NpcAnimation* anim = new MWRender::NpcAnimation(ptr, mRend, inv); + NpcAnimation* anim = new MWRender::NpcAnimation(ptr, ptr.getRefData ().getBaseNode (), mRend, inv, RV_Actors); mAllActors[ptr] = anim; } diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index fd25aab08..21442782f 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -6,26 +6,31 @@ #include "renderconst.hpp" +#include "npcanimation.hpp" namespace MWRender { - CharacterPreview::CharacterPreview(Ogre::SceneManager *sceneMgr, Ogre::SceneNode *node) + CharacterPreview::CharacterPreview(Ogre::SceneManager *sceneMgr, Ogre::SceneNode *node, int sizeX, int sizeY, const std::string& name, + Ogre::Vector3 position, Ogre::Vector3 lookAt) : mSceneMgr(sceneMgr) + , mSizeX(sizeX) + , mSizeY(sizeY) { - mCamera = mSceneMgr->createCamera ("CharacterPreviewCamera"); - mCamera->setAspectRatio (0.5); + mCamera = mSceneMgr->createCamera (name); + mCamera->setAspectRatio (float(sizeX) / float(sizeY)); - mNode = node->createChildSceneNode (); - mNode->attachObject (mCamera); + mNode = node; + mNode->setVisible (false); - mNode->setPosition(0, 185, 70); - mNode->roll(Ogre::Degree(180)); + mCamera->setPosition(position); + mCamera->lookAt(lookAt); - mNode->pitch(Ogre::Degree(90)); + mCamera->setNearClipDistance (0.01); + mCamera->setFarClipDistance (1000); - mTexture = Ogre::TextureManager::getSingleton().createManual("CharacterPreview", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 512, 1024, 0, Ogre::PF_A8R8G8B8, Ogre::TU_RENDERTARGET); + mTexture = Ogre::TextureManager::getSingleton().createManual(name, + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, sizeX, sizeY, 0, Ogre::PF_A8R8G8B8, Ogre::TU_RENDERTARGET); mRenderTarget = mTexture->getBuffer()->getRenderTarget(); mViewport = mRenderTarget->addViewport(mCamera); @@ -33,20 +38,55 @@ namespace MWRender mViewport->setBackgroundColour(Ogre::ColourValue(0, 0, 0, 0)); mViewport->setShadowsEnabled(false); mViewport->setMaterialScheme("local_map"); - mViewport->setVisibilityMask (RV_Player); + mViewport->setVisibilityMask (RV_PlayerPreview); mRenderTarget->setActive(true); mRenderTarget->setAutoUpdated (false); } - void CharacterPreview::update(int sizeX, int sizeY) + // -------------------------------------------------------------------------------------------------- + + + InventoryPreview::InventoryPreview(Ogre::SceneManager *sceneMgr, Ogre::SceneNode *node) + : CharacterPreview(sceneMgr, node, 512, 1024, "CharacterPreview", Ogre::Vector3(0, 65, -180), Ogre::Vector3(0,65,0)) + , mAnimation(NULL) + { + + } + + void InventoryPreview::update(int sizeX, int sizeY) { - bool wasVisible = mNode->getParentSceneNode()->getAttachedObject(0)->getVisible (); - mNode->getParentSceneNode()->setVisible(true, false); + if (mAnimation) + mAnimation->forceUpdate (); + mViewport->setDimensions (0, 0, std::min(1.f, float(sizeX) / float(512)), std::min(1.f, float(sizeY) / float(1024))); + mNode->setOrientation (Ogre::Quaternion::IDENTITY); + + mNode->setVisible (true); mRenderTarget->update(); + mNode->setVisible (false); + } + + void InventoryPreview::setNpcAnimation (NpcAnimation *anim) + { + mAnimation = anim; + } + + // -------------------------------------------------------------------------------------------------- + + RaceSelectionPreview::RaceSelectionPreview(Ogre::SceneManager *sceneMgr, Ogre::SceneNode *node) + : CharacterPreview(sceneMgr, node, 512, 512, "CharacterHeadPreview", Ogre::Vector3(0, 120, -35), Ogre::Vector3(0,125,0)) + { - mNode->getParentSceneNode()->setVisible(wasVisible, false); + } + + void RaceSelectionPreview::update(float angle) + { + mNode->roll(Ogre::Radian(angle), Ogre::SceneNode::TS_LOCAL); + + mNode->setVisible (true); + mRenderTarget->update(); + mNode->setVisible (false); } } diff --git a/apps/openmw/mwrender/characterpreview.hpp b/apps/openmw/mwrender/characterpreview.hpp index e15d6c359..ba48ea17d 100644 --- a/apps/openmw/mwrender/characterpreview.hpp +++ b/apps/openmw/mwrender/characterpreview.hpp @@ -6,14 +6,15 @@ namespace MWRender { + class NpcAnimation; + class CharacterPreview { public: - CharacterPreview(Ogre::SceneManager* sceneMgr, Ogre::SceneNode* node); - - void update(int sizeX, int sizeY); + CharacterPreview(Ogre::SceneManager* sceneMgr, Ogre::SceneNode* node, int sizeX, int sizeY, const std::string& name, + Ogre::Vector3 position, Ogre::Vector3 lookAt); - private: + protected: Ogre::TexturePtr mTexture; Ogre::RenderTarget* mRenderTarget; Ogre::Viewport* mViewport; @@ -22,6 +23,30 @@ namespace MWRender Ogre::SceneManager* mSceneMgr; Ogre::SceneNode* mNode; + + int mSizeX; + int mSizeY; + }; + + class InventoryPreview : public CharacterPreview + { + public: + InventoryPreview(Ogre::SceneManager* sceneMgr, Ogre::SceneNode* node); + + void update(int sizeX, int sizeY); + + void setNpcAnimation (NpcAnimation* anim); + + private: + NpcAnimation* mAnimation; + }; + + class RaceSelectionPreview : public CharacterPreview + { + public: + RaceSelectionPreview(Ogre::SceneManager* sceneMgr, Ogre::SceneNode* node); + + void update(float angle); }; } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 392a79c96..00b877ba0 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -45,15 +45,14 @@ NpcAnimation::~NpcAnimation() } -NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv, bool player) - : Animation(_rend), mStateID(-1), mInv(_inv), timeToChange(0), +NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, OEngine::Render::OgreRenderer& _rend, MWWorld::InventoryStore& _inv, int visibilityFlags) + : Animation(_rend), mStateID(-1), mInv(_inv), timeToChange(0), mVisibilityFlags(visibilityFlags), robe(mInv.end()), helmet(mInv.end()), shirt(mInv.end()), cuirass(mInv.end()), greaves(mInv.end()), leftpauldron(mInv.end()), rightpauldron(mInv.end()), boots(mInv.end()), leftglove(mInv.end()), rightglove(mInv.end()), skirtiter(mInv.end()), pants(mInv.end()) - , mIsPlayer(player) { MWWorld::LiveCellRef *ref = ptr.get(); @@ -85,7 +84,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n"; */ - mInsert = ptr.getRefData().getBaseNode(); + mInsert = node; assert(mInsert); std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); @@ -95,7 +94,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, OEngine::Render::OgreRendere { Ogre::Entity *base = mEntityList.mEntities[i]; - base->setVisibilityFlags(mIsPlayer ? RV_Player : RV_Actors); + base->setVisibilityFlags(mVisibilityFlags); bool transparent = false; for(unsigned int j=0;j < base->getNumSubEntities();++j) { @@ -358,7 +357,7 @@ NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, con mInsert, mesh); std::vector &parts = entities.mEntities; for(size_t i = 0;i < parts.size();i++) - parts[i]->setVisibilityFlags(mIsPlayer ? RV_Player : RV_Actors); + parts[i]->setVisibilityFlags(mVisibilityFlags); return entities; } @@ -582,4 +581,9 @@ void NpcAnimation::addPartGroup(int group, int priority, std::vector& parts); + + void forceUpdate(); }; } diff --git a/apps/openmw/mwrender/player.cpp b/apps/openmw/mwrender/player.cpp index 3ccc08022..297cb8d7a 100644 --- a/apps/openmw/mwrender/player.cpp +++ b/apps/openmw/mwrender/player.cpp @@ -35,6 +35,11 @@ namespace MWRender mPreviewCam.yaw = 0.f; mPreviewCam.offset = 400.f; } + + Player::~Player() + { + delete mAnimation; + } bool Player::rotate(const Ogre::Vector3 &rot, bool adjust) { diff --git a/apps/openmw/mwrender/player.hpp b/apps/openmw/mwrender/player.hpp index 8dd313b7f..b4d8983e4 100644 --- a/apps/openmw/mwrender/player.hpp +++ b/apps/openmw/mwrender/player.hpp @@ -63,6 +63,7 @@ namespace MWRender public: Player (Ogre::Camera *camera, Ogre::SceneNode* mNode); + ~Player(); /// Set where the player is looking at. Uses Morrowind (euler) angles /// \param rot Rotation angles in radians diff --git a/apps/openmw/mwrender/renderconst.hpp b/apps/openmw/mwrender/renderconst.hpp index 194ca9da6..e6ecb5150 100644 --- a/apps/openmw/mwrender/renderconst.hpp +++ b/apps/openmw/mwrender/renderconst.hpp @@ -54,7 +54,7 @@ enum VisibilityFlags RV_OcclusionQuery = 256, - RV_Player = 512, + RV_PlayerPreview = 512, RV_Map = RV_Terrain + RV_Statics + RV_StaticsSmall + RV_Misc + RV_Water diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index acb587d03..d2a51f5f1 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -160,8 +160,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mDebugging = new Debugging(mMwRoot, engine); mLocalMap = new MWRender::LocalMap(&mRendering, this); - mCharacterPreview = new CharacterPreview(mRendering.getScene (), playerNode); - setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); } @@ -178,7 +176,9 @@ RenderingManager::~RenderingManager () delete mOcclusionQuery; delete mCompositors; delete mWater; - delete mCharacterPreview; + delete mInventoryPreview; + delete mRaceSelectionPreview; + delete mPreviewAnimation; } MWRender::SkyManager* RenderingManager::getSkyManager() @@ -862,11 +862,20 @@ void RenderingManager::renderPlayer(const MWWorld::Ptr &ptr) { MWRender::NpcAnimation *anim = new MWRender::NpcAnimation( - ptr, + ptr, ptr.getRefData ().getBaseNode (), mRendering, - MWWorld::Class::get(ptr).getInventoryStore(ptr), true + MWWorld::Class::get(ptr).getInventoryStore(ptr), RV_Actors ); mPlayer->setAnimation(anim); + + MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr); + + Ogre::SceneNode* previewNode = mMwRoot->createChildSceneNode (); + mPreviewAnimation = new NpcAnimation(ptr, previewNode, mRendering, invStore, RV_PlayerPreview); + + mInventoryPreview = new InventoryPreview(mRendering.getScene (), previewNode); + mInventoryPreview->setNpcAnimation (mPreviewAnimation); + mRaceSelectionPreview = new RaceSelectionPreview(mRendering.getScene (), previewNode); } void RenderingManager::getPlayerData(Ogre::Vector3 &eyepos, float &pitch, float &yaw) @@ -888,7 +897,12 @@ bool RenderingManager::isPositionExplored (float nX, float nY, int x, int y, boo void RenderingManager::updateCharacterPreview (int sizeX, int sizeY) { - mCharacterPreview->update(sizeX, sizeY); + mInventoryPreview->update(sizeX, sizeY); +} + +void RenderingManager::updateRaceSelectionPreview (float angle) +{ + mRaceSelectionPreview->update(angle); } } // namespace diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index fe79c9400..cbad67472 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -43,7 +43,8 @@ namespace MWRender class LocalMap; class Water; class Compositors; - class CharacterPreview; + class InventoryPreview; + class RaceSelectionPreview; class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener { @@ -193,6 +194,7 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList ///< see MWRender::LocalMap::isPositionExplored void updateCharacterPreview(int sizeX, int sizeY); + void updateRaceSelectionPreview(float angle); protected: virtual void windowResized(Ogre::RenderWindow* rw); @@ -216,7 +218,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList TerrainManager* mTerrainManager; - CharacterPreview* mCharacterPreview; + InventoryPreview* mInventoryPreview; + RaceSelectionPreview* mRaceSelectionPreview; MWRender::Water *mWater; @@ -247,6 +250,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList MWRender::Shadows* mShadows; MWRender::Compositors* mCompositors; + + MWRender::NpcAnimation* mPreviewAnimation; }; } diff --git a/apps/openmw/mwrender/shadows.cpp b/apps/openmw/mwrender/shadows.cpp index fc28f1cb9..3d9f13243 100644 --- a/apps/openmw/mwrender/shadows.cpp +++ b/apps/openmw/mwrender/shadows.cpp @@ -111,7 +111,7 @@ void Shadows::recreate() sh::Factory::getInstance ().setSharedParameter ("shadowFar_fadeStart", sh::makeProperty(shadowFar_fadeStart)); // Set visibility mask for the shadow render textures - int visibilityMask = (RV_Actors + RV_Player) * Settings::Manager::getBool("actor shadows", "Shadows") + int visibilityMask = RV_Actors * Settings::Manager::getBool("actor shadows", "Shadows") + (RV_Statics + RV_StaticsSmall) * Settings::Manager::getBool("statics shadows", "Shadows") + RV_Misc * Settings::Manager::getBool("misc shadows", "Shadows"); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 6a3eeb509..7100540fc 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -332,7 +332,7 @@ void Water::applyVisibilityMask() mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water") + RV_Statics * Settings::Manager::getBool("reflect statics", "Water") + RV_StaticsSmall * Settings::Manager::getBool("reflect small statics", "Water") - + (RV_Actors + RV_Player) * Settings::Manager::getBool("reflect actors", "Water") + + RV_Actors * Settings::Manager::getBool("reflect actors", "Water") + RV_Misc * Settings::Manager::getBool("reflect misc", "Water") + RV_Sky; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f88f5c320..005b94ffa 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1227,4 +1227,9 @@ namespace MWWorld { mRendering->updateCharacterPreview(sizeX, sizeY); } + + void World::updateRaceSelectionPreview (float angle) + { + mRendering->updateRaceSelectionPreview(angle); + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 5e8bc697e..20da6f729 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -309,6 +309,7 @@ namespace MWWorld virtual void renderPlayer(); virtual void updateCharacterPreview(int sizeX, int sizeY); + virtual void updateRaceSelectionPreview(float angle); }; } diff --git a/files/mygui/openmw_chargen_race.layout b/files/mygui/openmw_chargen_race.layout index 3d32ffd9a..6891f5d93 100644 --- a/files/mygui/openmw_chargen_race.layout +++ b/files/mygui/openmw_chargen_race.layout @@ -8,7 +8,9 @@ - + + + diff --git a/files/mygui/openmw_inventory_window.layout b/files/mygui/openmw_inventory_window.layout index 31bf58c34..4f295212b 100644 --- a/files/mygui/openmw_inventory_window.layout +++ b/files/mygui/openmw_inventory_window.layout @@ -13,7 +13,6 @@ - diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index e342f4c5f..2764410ad 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -188,7 +188,7 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, ¶ms); // create the semi-transparent black background texture used by the GUI. - // has to be created in code with TU_DYNAMIC_WRITE_ONLY_DISCARDABLE param + // has to be created in code with TU_DYNAMIC_WRITE_ONLY param // so that it can be modified at runtime. Ogre::TextureManager::getSingleton().createManual( "transparent.png", @@ -197,7 +197,7 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& 1, 1, 0, Ogre::PF_A8R8G8B8, - Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + Ogre::TU_DYNAMIC_WRITE_ONLY); } void OgreRenderer::createScene(const std::string& camName, float fov, float nearClip)