From bffbfff41c791c18a182e49d1f11710b6c46a3b2 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Mon, 30 Sep 2013 00:32:06 -0400 Subject: [PATCH 1/9] My own fix to make it hackily compile --- apps/launcher/main.cpp | 16 ++++++++++++++++ apps/opencs/view/doc/adjusterwidget.cpp | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index f67f5edcff..a5cda76476 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -62,3 +62,19 @@ int main(int argc, char *argv[]) return returnValue; } + +#include +#include + +#ifdef __GNUC__ +#define _stdcall __attribute__((stdcall)) +#endif + +int _stdcall +WinMain (struct HINSTANCE__ *hInstance, + struct HINSTANCE__ *hPrevInstance, + char *lpszCmdLine, + int nCmdShow) +{ + return main (__argc, __argv); +} \ No newline at end of file diff --git a/apps/opencs/view/doc/adjusterwidget.cpp b/apps/opencs/view/doc/adjusterwidget.cpp index 9108197006..c97f066725 100644 --- a/apps/opencs/view/doc/adjusterwidget.cpp +++ b/apps/opencs/view/doc/adjusterwidget.cpp @@ -61,7 +61,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) if (path.parent_path().string()==mLocalData.string()) { // path already points to the local data directory - message = QString::fromUtf8 (("Will be saved as: " + path.native()).c_str()); + message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); mResultPath = path; mValid = true; } @@ -70,7 +70,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) // path points somewhere else or is a leaf name. path = mLocalData / path.filename(); - message = QString::fromUtf8 (("Will be saved as: " + path.native()).c_str()); + message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); mResultPath = path; mValid = true; From 00a776a1a8585c2205c86f958bbe2dc7ba9e64c6 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Mon, 30 Sep 2013 02:54:20 -0400 Subject: [PATCH 2/9] Fixed compilation failure on my machine Fixed shared records not being populated before the player record is moved. --- apps/openmw/mwworld/worldimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f3d4c81b76..8e8f68f70e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -225,8 +225,8 @@ namespace MWWorld if (mEsm[0].getFormat() == 0) ensureNeededRecords(); - mStore.movePlayerRecord(); mStore.setUp(); + mStore.movePlayerRecord(); mGlobalVariables = new Globals (mStore); From eae02ea00dc9823fed63366709ef9c857f4e1956 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Mon, 30 Sep 2013 03:33:31 -0400 Subject: [PATCH 3/9] Cleaned up my hackish code for WinMain --- apps/launcher/main.cpp | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index a5cda76476..73bdb95dae 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -62,19 +62,14 @@ int main(int argc, char *argv[]) return returnValue; } - -#include -#include - -#ifdef __GNUC__ -#define _stdcall __attribute__((stdcall)) -#endif - -int _stdcall -WinMain (struct HINSTANCE__ *hInstance, - struct HINSTANCE__ *hPrevInstance, - char *lpszCmdLine, - int nCmdShow) +#ifdef _WINDOWS +// If the system compiles for main(), then main will be used. +// If it wants WinMain, this will call main anyways. +int _stdcall WinMain(struct HINSTANCE__ *hInstance, + struct HINSTANCE__ *hPrevInstance, + char *lpszCmdLine, + int nCmdShow) { - return main (__argc, __argv); -} \ No newline at end of file + return main(__argc, __argv); +} +#endif From 4496244b1428cb43d9d5d41d191360b7b98e2cb0 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Tue, 1 Oct 2013 05:36:13 -0400 Subject: [PATCH 4/9] Tabs to spaces My own code uses only tabs - I forgot to change the setting on my IDE, sorry! --- apps/launcher/main.cpp | 2 +- apps/opencs/view/doc/adjusterwidget.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 73bdb95dae..df7aa11d47 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -72,4 +72,4 @@ int _stdcall WinMain(struct HINSTANCE__ *hInstance, { return main(__argc, __argv); } -#endif +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/adjusterwidget.cpp b/apps/opencs/view/doc/adjusterwidget.cpp index c97f066725..9e01f685ca 100644 --- a/apps/opencs/view/doc/adjusterwidget.cpp +++ b/apps/opencs/view/doc/adjusterwidget.cpp @@ -61,7 +61,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) if (path.parent_path().string()==mLocalData.string()) { // path already points to the local data directory - message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); + message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); mResultPath = path; mValid = true; } @@ -70,7 +70,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) // path points somewhere else or is a leaf name. path = mLocalData / path.filename(); - message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); + message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); mResultPath = path; mValid = true; From 296abfd48faec66aa77490f58d6f0e868bb4f17f Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Tue, 1 Oct 2013 10:48:34 -0400 Subject: [PATCH 5/9] Bug #840, First Person Sneaking Camera Height Also, added comments to existing code in the area. --- apps/openmw/mwrender/npcanimation.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 13b5971e2a..7b5a105c0a 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -443,11 +443,31 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) Ogre::Vector3 ret = Animation::runAnimation(timepassed); Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton(); + + // We have to make a few adjustments to the first person animation, since the armature + // is partly driven by code. if(mViewMode == VM_FirstPerson && mCamera) { + // Bend his neck and shoulders so his eyes don't go into his torso. float pitch = mCamera->getPitch(); Ogre::Node *node = baseinst->getBone("Bip01 Neck"); node->pitch(Ogre::Radian(pitch*0.75f), Ogre::Node::TS_WORLD); + + // If NPC is sneaking, his head and shoulders must lower to adjust his camera. + const MWWorld::Class *npcClass = &MWWorld::Class::get(mPtr); + const MWBase::World *world = MWBase::Environment::get().getWorld(); + + bool isSneaking = npcClass->getStance(mPtr, MWWorld::Class::Sneak); + bool isInAir = !world->isOnGround(mPtr); + bool isSwimming = world->isSwimming(mPtr); + + if(isSneaking && !(isSwimming || isInAir)) + { + Ogre::Node *headNode = baseinst->getBone("Bip01 Neck"); + Ogre::Vector3 position = headNode->getPosition(); + position.x -= 9.5f; + headNode->setPosition(position); + } } for(size_t i = 0;i < ESM::PRT_Count;i++) From 0ddb5097fc48f5e4f87ac08121fa6c02b3f25c16 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Tue, 1 Oct 2013 11:44:45 -0400 Subject: [PATCH 6/9] Revert "Bug #840, First Person Sneaking Camera Height" This reverts commit 296abfd48faec66aa77490f58d6f0e868bb4f17f. --- apps/openmw/mwrender/npcanimation.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 7b5a105c0a..13b5971e2a 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -443,31 +443,11 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) Ogre::Vector3 ret = Animation::runAnimation(timepassed); Ogre::SkeletonInstance *baseinst = mSkelBase->getSkeleton(); - - // We have to make a few adjustments to the first person animation, since the armature - // is partly driven by code. if(mViewMode == VM_FirstPerson && mCamera) { - // Bend his neck and shoulders so his eyes don't go into his torso. float pitch = mCamera->getPitch(); Ogre::Node *node = baseinst->getBone("Bip01 Neck"); node->pitch(Ogre::Radian(pitch*0.75f), Ogre::Node::TS_WORLD); - - // If NPC is sneaking, his head and shoulders must lower to adjust his camera. - const MWWorld::Class *npcClass = &MWWorld::Class::get(mPtr); - const MWBase::World *world = MWBase::Environment::get().getWorld(); - - bool isSneaking = npcClass->getStance(mPtr, MWWorld::Class::Sneak); - bool isInAir = !world->isOnGround(mPtr); - bool isSwimming = world->isSwimming(mPtr); - - if(isSneaking && !(isSwimming || isInAir)) - { - Ogre::Node *headNode = baseinst->getBone("Bip01 Neck"); - Ogre::Vector3 position = headNode->getPosition(); - position.x -= 9.5f; - headNode->setPosition(position); - } } for(size_t i = 0;i < ESM::PRT_Count;i++) From ed0c31b4854cc19d474402127d434ea379c374c1 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Wed, 2 Oct 2013 05:16:52 -0400 Subject: [PATCH 7/9] Refactored, moved logic out of NpcAnimation The logic is now handled by RenderingManager, and Camera sets its animation's first person offset height. Due to how NpcAnimation seems to be updated, it has to be the one to actually set its own nodes, in the case of the hands. Otherwise, the hands would not move without a messier hack. --- apps/openmw/mwrender/camera.cpp | 6 ++++++ apps/openmw/mwrender/camera.hpp | 6 ++++++ apps/openmw/mwrender/npcanimation.cpp | 13 ++++++++++++- apps/openmw/mwrender/npcanimation.hpp | 7 +++++++ apps/openmw/mwrender/renderingmanager.cpp | 9 +++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 36f53c0fea..232b95c699 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -187,6 +187,12 @@ namespace MWRender rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false); } + void Camera::setSneakOffset() + { + if(mAnimation) + mAnimation->addFirstPersonOffset(Ogre::Vector3(-9.8f, 0.f, 0.f)); + } + float Camera::getYaw() { if(mVanity.enabled || mPreviewMode) diff --git a/apps/openmw/mwrender/camera.hpp b/apps/openmw/mwrender/camera.hpp index dc552371e6..baf2f3685a 100644 --- a/apps/openmw/mwrender/camera.hpp +++ b/apps/openmw/mwrender/camera.hpp @@ -79,6 +79,12 @@ namespace MWRender void togglePreviewMode(bool enable); + /// \brief Lowers the camera for sneak. + /// As animation is tied to the camera, this needs + /// to be set each frame after the animation is + /// applied. + void setSneakOffset(); + bool isFirstPerson() const { return !(mVanity.enabled || mPreviewMode || !mFirstPersonView); } diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 13b5971e2a..84e89773c2 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -84,7 +84,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor mWeapon(inv.end()), mShield(inv.end()), mViewMode(viewMode), - mShowWeapons(false) + mShowWeapons(false), + mFirstPersonOffset(0.f, 0.f, 0.f) { mNpc = mPtr.get()->mBase; @@ -392,6 +393,11 @@ void NpcAnimation::updateParts(bool forceupdate) } } +void NpcAnimation::addFirstPersonOffset(const Ogre::Vector3 &offset) +{ + mFirstPersonOffset += offset; +} + class SetObjectGroup { int mGroup; @@ -448,7 +454,12 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) float pitch = mCamera->getPitch(); Ogre::Node *node = baseinst->getBone("Bip01 Neck"); node->pitch(Ogre::Radian(pitch*0.75f), Ogre::Node::TS_WORLD); + + // This has to be done before this function ends; + // updateSkeletonInstance, below, touches the hands. + node->translate(mFirstPersonOffset); } + mFirstPersonOffset = 0.f; // reset the X, Y, Z offset for the next frame. for(size_t i = 0;i < ESM::PRT_Count;i++) { diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 24205acafd..b1abf97af0 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -64,6 +64,8 @@ private: int mPartslots[ESM::PRT_Count]; //Each part slot is taken by clothing, armor, or is empty int mPartPriorities[ESM::PRT_Count]; + Ogre::Vector3 mFirstPersonOffset; + void updateNpcBase(); NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename); @@ -89,6 +91,11 @@ public: void updateParts(bool forceupdate = false); + /// \brief Applies a translation to the arms and hands. + /// This may be called multiple times before the animation + /// is updated to add additional offsets. + void addFirstPersonOffset(const Ogre::Vector3 &offset); + /// Rebuilds the NPC, updating their root model, animation sources, and equipment. void rebuild(); }; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index e03b2ccfcf..261fd45c88 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -354,6 +354,15 @@ void RenderingManager::update (float duration, bool paused) mCamera->setCameraDistance(test.second * orig.distance(dest), false, false); } + // Sink the camera while sneaking + bool isSneaking = MWWorld::Class::get(player).getStance(player, MWWorld::Class::Sneak); + bool isInAir = !world->isOnGround(player); + bool isSwimming = world->isSwimming(player); + + if(isSneaking && !(isSwimming || isInAir)) + mCamera->setSneakOffset(); + + mOcclusionQuery->update(duration); mVideoPlayer->update (); From f1b4c2e400743dfb207f8b9bbad19e50af6b95ed Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Wed, 2 Oct 2013 07:03:39 -0400 Subject: [PATCH 8/9] Fixed first person offset to use world transform It slipped my mind that some necks might not be perfectly vertical. --- apps/openmw/mwrender/camera.cpp | 2 +- apps/openmw/mwrender/npcanimation.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index 232b95c699..9af3987a8e 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -190,7 +190,7 @@ namespace MWRender void Camera::setSneakOffset() { if(mAnimation) - mAnimation->addFirstPersonOffset(Ogre::Vector3(-9.8f, 0.f, 0.f)); + mAnimation->addFirstPersonOffset(Ogre::Vector3(0.f, 0.f, -9.8f)); } float Camera::getYaw() diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 84e89773c2..9ffe53eabb 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -457,7 +457,7 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) // This has to be done before this function ends; // updateSkeletonInstance, below, touches the hands. - node->translate(mFirstPersonOffset); + node->translate(mFirstPersonOffset, Ogre::Node::TS_WORLD); } mFirstPersonOffset = 0.f; // reset the X, Y, Z offset for the next frame. From cfc30933202a7804be0c5ff5a5de23f908175218 Mon Sep 17 00:00:00 2001 From: "Alex \"rainChu\" Haddad" Date: Sat, 12 Oct 2013 10:46:44 -0400 Subject: [PATCH 9/9] Reverted conditional compiling --- apps/launcher/main.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index df7aa11d47..f67f5edcff 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -62,14 +62,3 @@ int main(int argc, char *argv[]) return returnValue; } -#ifdef _WINDOWS -// If the system compiles for main(), then main will be used. -// If it wants WinMain, this will call main anyways. -int _stdcall WinMain(struct HINSTANCE__ *hInstance, - struct HINSTANCE__ *hPrevInstance, - char *lpszCmdLine, - int nCmdShow) -{ - return main(__argc, __argv); -} -#endif \ No newline at end of file