diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 95d15f118..66844b280 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -29,7 +29,7 @@ add_openmw_dir (mwgui map_window window_pinnable_base cursorreplace tooltips scrollwindow bookwindow list formatting inventorywindow container hud countdialog tradewindow settingswindow confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu - itemselection spellbuyingwindow loadingscreen levelupdialog + itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 0fd78225a..49f1f95b0 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -222,6 +222,8 @@ namespace MWBase virtual void enableRest() = 0; virtual bool getRestEnabled() = 0; + + virtual bool getPlayerSleeping() = 0; }; } diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index a725d389d..ee474f357 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -160,6 +160,9 @@ namespace MWBase virtual void setDay (int day) = 0; ///< Set in-game time day. + virtual int getDay() = 0; + virtual int getMonth() = 0; + virtual MWWorld::TimeStamp getTimeStamp() const = 0; ///< Return current in-game time stamp. @@ -282,6 +285,13 @@ namespace MWBase virtual void renderGlobalMap() = 0; virtual void setupExternalRendering (MWRender::ExternalRendering& rendering) = 0; + + virtual int canRest() = 0; + ///< check if the player is allowed to rest \n + /// 0 - yes \n + /// 1 - only waiting \n + /// 2 - player is underwater \n + /// 3 - enemies are nearby (not implemented) }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 063f39d2a..daf39a1ee 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -141,6 +141,7 @@ namespace MWClass assert(ref->base != NULL); std::string headID = ref->base->head; + int end = headID.find_last_of("head_") - 4; std::string bodyRaceID = headID.substr(0, end); @@ -153,6 +154,7 @@ namespace MWClass model = "meshes\\base_animkna.nif"; } return model; + } std::string Npc::getName (const MWWorld::Ptr& ptr) const @@ -297,7 +299,7 @@ namespace MWClass { Ogre::Vector3 vector (0, 0, 0); - vector.x = - getMovementSettings (ptr).mLeftRight * 127; + vector.x = getMovementSettings (ptr).mLeftRight * 127; vector.y = getMovementSettings (ptr).mForwardBackward * 127; vector.z = getMovementSettings(ptr).mUpDown * 127; diff --git a/apps/openmw/mwgui/levelupdialog.cpp b/apps/openmw/mwgui/levelupdialog.cpp index 3616283d9..980a9e13b 100644 --- a/apps/openmw/mwgui/levelupdialog.cpp +++ b/apps/openmw/mwgui/levelupdialog.cpp @@ -173,7 +173,7 @@ namespace MWGui creatureStats.setLevel (creatureStats.getLevel()+1); pcStats.levelUp (); - mWindowManager.removeGuiMode (GM_Rest); + mWindowManager.removeGuiMode (GM_Levelup); } } diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index eb2c52b26..64aa1dc21 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -20,6 +20,7 @@ namespace MWGui GM_Dialogue, // NPC interaction GM_Barter, GM_Rest, + GM_RestBed, GM_SpellBuying, GM_Levelup, diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 3fe70d959..5cb73e682 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -40,7 +40,7 @@ RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) getWidget(mHeadRotate, "HeadRotate"); mHeadRotate->setScrollRange(50); - mHeadRotate->setScrollPosition(20); + mHeadRotate->setScrollPosition(25); mHeadRotate->setScrollViewPage(10); mHeadRotate->eventScrollChangePosition += MyGUI::newDelegate(this, &RaceDialog::onHeadRotate); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index d1e206a95..cdfe4d2b6 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -122,6 +122,7 @@ namespace MWGui getWidget(mInvertYButton, "InvertYButton"); getWidget(mUISensitivitySlider, "UISensitivitySlider"); getWidget(mCameraSensitivitySlider, "CameraSensitivitySlider"); + getWidget(mGammaSlider, "GammaSlider"); mSubtitlesButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mCrosshairButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -143,6 +144,7 @@ namespace MWGui mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + mGammaSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mShadowsEnabledButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mShadowsLargeDistance->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); @@ -200,6 +202,14 @@ namespace MWGui getWidget(fovText, "FovText"); fovText->setCaption("Field of View (" + boost::lexical_cast(int(Settings::Manager::getFloat("field of view", "General"))) + ")"); + float gammaVal = (Settings::Manager::getFloat("gamma", "Video")-0.1f)/(3.f-0.1f); + mGammaSlider->setScrollPosition(gammaVal * (mGammaSlider->getScrollRange()-1)); + MyGUI::TextBox* gammaText; + getWidget(gammaText, "GammaText"); + std::stringstream gamma; + gamma << std::setprecision (2) << Settings::Manager::getFloat("gamma", "Video"); + gammaText->setCaption("Gamma (" + gamma.str() + ")"); + float anisotropyVal = Settings::Manager::getInt("anisotropy", "General") / 16.0; mAnisotropySlider->setScrollPosition(anisotropyVal * (mAnisotropySlider->getScrollRange()-1)); std::string tf = Settings::Manager::getString("texture filtering", "General"); @@ -511,6 +521,15 @@ namespace MWGui fovText->setCaption("Field of View (" + boost::lexical_cast(int((1-val) * sFovMin + val * sFovMax)) + ")"); Settings::Manager::setFloat("field of view", "General", (1-val) * sFovMin + val * sFovMax); } + else if (scroller == mGammaSlider) + { + Settings::Manager::setFloat("gamma", "Video", (1-val) * 0.1f + val * 3.f); + MyGUI::TextBox* gammaText; + getWidget(gammaText, "GammaText"); + std::stringstream gamma; + gamma << std::setprecision (2) << Settings::Manager::getFloat("gamma", "Video"); + gammaText->setCaption("Gamma (" + gamma.str() + ")"); + } else if (scroller == mAnisotropySlider) { mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast(int(val*16)) + ")"); diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index d1f35ed71..e878d0abe 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -40,6 +40,7 @@ namespace MWGui MyGUI::Button* mFPSButton; MyGUI::ScrollBar* mViewDistanceSlider; MyGUI::ScrollBar* mFOVSlider; + MyGUI::ScrollBar* mGammaSlider; MyGUI::ScrollBar* mAnisotropySlider; MyGUI::Button* mTextureFilteringButton; MyGUI::TextBox* mAnisotropyLabel; diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp new file mode 100644 index 000000000..cc9019f2b --- /dev/null +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -0,0 +1,213 @@ +#include "waitdialog.hpp" + +#include + +#include + +#include "../mwbase/windowmanager.hpp" +#include "../mwbase/world.hpp" +#include "../mwbase/environment.hpp" + +#include "../mwworld/timestamp.hpp" +#include "../mwworld/player.hpp" +#include "../mwworld/ptr.hpp" +#include "../mwworld/class.hpp" + +#include "../mwmechanics/npcstats.hpp" + +#include "widgets.hpp" + + +namespace MWGui +{ + + WaitDialogProgressBar::WaitDialogProgressBar(MWBase::WindowManager &parWindowManager) + : WindowBase("openmw_wait_dialog_progressbar.layout", parWindowManager) + { + getWidget(mProgressBar, "ProgressBar"); + getWidget(mProgressText, "ProgressText"); + } + + void WaitDialogProgressBar::open() + { + center(); + } + + void WaitDialogProgressBar::setProgress (int cur, int total) + { + mProgressBar->setProgressRange (total); + mProgressBar->setProgressPosition (cur); + mProgressText->setCaption(boost::lexical_cast(cur) + "/" + boost::lexical_cast(total)); + } + + // --------------------------------------------------------------------------------------------------------- + + WaitDialog::WaitDialog(MWBase::WindowManager &parWindowManager) + : WindowBase("openmw_wait_dialog.layout", parWindowManager) + , mProgressBar(parWindowManager) + , mWaiting(false) + , mSleeping(false) + , mHours(1) + , mRemainingTime(0.05) + { + getWidget(mDateTimeText, "DateTimeText"); + getWidget(mRestText, "RestText"); + getWidget(mHourText, "HourText"); + getWidget(mHourSlider, "HourSlider"); + getWidget(mUntilHealedButton, "UntilHealedButton"); + getWidget(mWaitButton, "WaitButton"); + getWidget(mCancelButton, "CancelButton"); + + mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &WaitDialog::onCancelButtonClicked); + mUntilHealedButton->eventMouseButtonClick += MyGUI::newDelegate(this, &WaitDialog::onUntilHealedButtonClicked); + mWaitButton->eventMouseButtonClick += MyGUI::newDelegate(this, &WaitDialog::onWaitButtonClicked); + + mHourSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &WaitDialog::onHourSliderChangedPosition); + + mProgressBar.setVisible (false); + } + + void WaitDialog::open() + { + if (!MWBase::Environment::get().getWindowManager ()->getRestEnabled ()) + { + mWindowManager.popGuiMode (); + } + + int canRest = MWBase::Environment::get().getWorld ()->canRest (); + + if (canRest == 2) + { + // resting underwater or mid-air not allowed + mWindowManager.messageBox ("#{sNotifyMessage1}", std::vector()); + mWindowManager.popGuiMode (); + } + + setCanRest(canRest == 0); + + onHourSliderChangedPosition(mHourSlider, 0); + mHourSlider->setScrollPosition (0); + + // http://www.uesp.net/wiki/Lore:Calendar + std::string month; + int m = MWBase::Environment::get().getWorld ()->getMonth (); + if (m == 0) + month = "#{sMonthMorningstar}"; + else if (m == 1) + month = "#{sMonthSunsdawn}"; + else if (m == 2) + month = "#{sMonthFirstseed}"; + else if (m == 3) + month = "#{sMonthRainshand}"; + else if (m == 4) + month = "#{sMonthSecondseed}"; + else if (m == 5) + month = "#{sMonthMidyear}"; + else if (m == 6) + month = "#{sMonthSunsheight}"; + else if (m == 7) + month = "#{sMonthLastseed}"; + else if (m == 8) + month = "#{sMonthHeartfire}"; + else if (m == 9) + month = "#{sMonthFrostfall}"; + else if (m == 10) + month = "#{sMonthSunsdusk}"; + else if (m == 11) + month = "#{sMonthEveningstar}"; + + int hour = MWBase::Environment::get().getWorld ()->getTimeStamp ().getHour (); + bool pm = hour >= 12; + if (hour >= 13) hour -= 12; + + std::string dateTimeText = + boost::lexical_cast(MWBase::Environment::get().getWorld ()->getDay ()+1) + " " + + month + " (#{sDay} " + boost::lexical_cast(MWBase::Environment::get().getWorld ()->getTimeStamp ().getDay ()+1) + + ") " + boost::lexical_cast(hour) + " " + (pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}"); + + mDateTimeText->setCaptionWithReplacing (dateTimeText); + } + + void WaitDialog::onUntilHealedButtonClicked(MyGUI::Widget* sender) + { + startWaiting(); + } + + void WaitDialog::onWaitButtonClicked(MyGUI::Widget* sender) + { + startWaiting(); + } + + void WaitDialog::startWaiting () + { + MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.2); + setVisible(false); + mProgressBar.setVisible (true); + mWaiting = true; + mCurHour = 0; + mRemainingTime = 0.05; + mProgressBar.setProgress (0, mHours); + } + + void WaitDialog::onCancelButtonClicked(MyGUI::Widget* sender) + { + mWindowManager.popGuiMode (); + } + + void WaitDialog::onHourSliderChangedPosition(MyGUI::ScrollBar* sender, size_t position) + { + mHourText->setCaptionWithReplacing (boost::lexical_cast(position+1) + " #{sRestMenu2}"); + mHours = position+1; + } + + void WaitDialog::setCanRest (bool canRest) + { + mUntilHealedButton->setVisible(canRest); + mWaitButton->setCaptionWithReplacing (canRest ? "#{sRest}" : "#{sWait}"); + mRestText->setCaptionWithReplacing (canRest ? "#{sRestMenu3}" : "#{sRestIllegal}"); + + mSleeping = canRest; + + dynamic_cast(mMainWidget)->notifyChildrenSizeChanged(); + center(); + } + + void WaitDialog::onFrame(float dt) + { + if (!mWaiting) + return; + + mRemainingTime -= dt; + + if (mRemainingTime < 0) + { + mRemainingTime = 0.05; + ++mCurHour; + mProgressBar.setProgress (mCurHour, mHours); + + if (mCurHour <= mHours) + MWBase::Environment::get().getWorld ()->advanceTime (1); + } + + if (mCurHour > mHours) + stopWaiting(); + } + + void WaitDialog::stopWaiting () + { + MWBase::Environment::get().getWorld ()->getFader ()->fadeIn(0.2); + mProgressBar.setVisible (false); + mWindowManager.popGuiMode (); + mWaiting = false; + + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); + MWMechanics::NpcStats pcstats = MWWorld::Class::get(player).getNpcStats(player); + + // trigger levelup if possible + if (mSleeping && pcstats.getLevelProgress () >= 10) + { + mWindowManager.pushGuiMode (GM_Levelup); + } + } + +} diff --git a/apps/openmw/mwgui/waitdialog.hpp b/apps/openmw/mwgui/waitdialog.hpp new file mode 100644 index 000000000..4a401c0c6 --- /dev/null +++ b/apps/openmw/mwgui/waitdialog.hpp @@ -0,0 +1,66 @@ +#ifndef MWGUI_WAIT_DIALOG_H +#define MWGUI_WAIT_DIALOG_H + +#include "window_base.hpp" + +namespace MWGui +{ + + class WaitDialogProgressBar : public WindowBase + { + public: + WaitDialogProgressBar(MWBase::WindowManager& parWindowManager); + + virtual void open(); + + void setProgress(int cur, int total); + + protected: + MyGUI::ProgressBar* mProgressBar; + MyGUI::TextBox* mProgressText; + }; + + class WaitDialog : public WindowBase + { + public: + WaitDialog(MWBase::WindowManager& parWindowManager); + + virtual void open(); + + void onFrame(float dt); + + void bedActivated() { setCanRest(true); } + + bool getSleeping() { return mWaiting && mSleeping; } + + protected: + MyGUI::TextBox* mDateTimeText; + MyGUI::TextBox* mRestText; + MyGUI::TextBox* mHourText; + MyGUI::ScrollBar* mHourSlider; + MyGUI::Button* mUntilHealedButton; + MyGUI::Button* mWaitButton; + MyGUI::Button* mCancelButton; + + bool mWaiting; + bool mSleeping; + int mCurHour; + int mHours; + float mRemainingTime; + + WaitDialogProgressBar mProgressBar; + + void onUntilHealedButtonClicked(MyGUI::Widget* sender); + void onWaitButtonClicked(MyGUI::Widget* sender); + void onCancelButtonClicked(MyGUI::Widget* sender); + void onHourSliderChangedPosition(MyGUI::ScrollBar* sender, size_t position); + + void setCanRest(bool canRest); + + void startWaiting(); + void stopWaiting(); + }; + +} + +#endif diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 97a5b2eb5..313820534 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -795,7 +795,6 @@ void MWDynamicStat::initialiseOverride() // --------------------------------------------------------------------------------------------------------------------- - void AutoSizedWidget::notifySizeChange (MyGUI::Widget* w) { if (w->getParent () != 0) @@ -869,29 +868,33 @@ void AutoSizedButton::setPropertyOverride(const std::string& _key, const std::st Box::Box() : mSpacing(4) + , mPadding(0) + , mAutoResize(false) { } -void Box::setPropertyOverride(const std::string& _key, const std::string& _value) -{ - if (_key == "Spacing") - { - mSpacing = MyGUI::utility::parseValue(_value); - } -} - void Box::notifyChildrenSizeChanged () { align(); } +void Box::_setPropertyImpl(const std::string& _key, const std::string& _value) +{ + if (_key == "Spacing") + mSpacing = MyGUI::utility::parseValue(_value); + else if (_key == "Padding") + mPadding = MyGUI::utility::parseValue(_value); + else if (_key == "AutoResize") + mAutoResize = MyGUI::utility::parseValue(_value); +} void HBox::align () { unsigned int count = getChildCount (); size_t h_stretched_count = 0; int total_width = 0; + int total_height = 0; std::vector< std::pair > sizes; for (unsigned int i = 0; i < count; ++i) @@ -904,28 +907,43 @@ void HBox::align () { sizes.push_back(std::make_pair(aw->getRequestedSize (), hstretch)); total_width += aw->getRequestedSize ().width; + total_height = std::max(total_height, aw->getRequestedSize ().height); } else { - if (!hstretch) h_stretched_count ++; - sizes.push_back (std::make_pair(MyGUI::IntSize(0,0), true)); + sizes.push_back (std::make_pair(w->getSize(), hstretch)); + total_width += w->getSize().width; } if (i != count-1) total_width += mSpacing; } + if (mAutoResize && (total_width+mPadding*2 != getSize().width || total_height+mPadding*2 != getSize().height)) + { + setSize(MyGUI::IntSize(total_width+mPadding*2, total_height+mPadding*2)); + return; + } + + int curX = 0; for (unsigned int i = 0; i < count; ++i) { + if (i == 0) + curX += mPadding; + MyGUI::Widget* w = getChildAt(i); + + bool vstretch = w->getUserString ("VStretch") == "true"; + int height = vstretch ? total_height : sizes[i].first.height; + MyGUI::IntCoord widgetCoord; widgetCoord.left = curX; - widgetCoord.top = (getSize().height - sizes[i].first.height) / 2; - int width = sizes[i].second ? sizes[i].first.width + (getSize().width - total_width)/h_stretched_count + widgetCoord.top = mPadding + (getSize().height-mPadding*2 - height) / 2; + int width = sizes[i].second ? sizes[i].first.width + (getSize().width-mPadding*2 - total_width)/h_stretched_count : sizes[i].first.width; widgetCoord.width = width; - widgetCoord.height = sizes[i].first.height; + widgetCoord.height = height; w->setCoord(widgetCoord); curX += width; @@ -934,12 +952,33 @@ void HBox::align () } } +void HBox::setPropertyOverride(const std::string& _key, const std::string& _value) +{ + Box::_setPropertyImpl (_key, _value); +} + void HBox::setSize (const MyGUI::IntSize& _value) { MyGUI::Widget::setSize (_value); align(); } +void HBox::setCoord (const MyGUI::IntCoord& _value) +{ + MyGUI::Widget::setCoord (_value); + align(); +} + +void HBox::onWidgetCreated(MyGUI::Widget* _widget) +{ + align(); +} + +void HBox::onWidgetDestroy(MyGUI::Widget* _widget) +{ + align(); +} + MyGUI::IntSize HBox::getRequestedSize () { MyGUI::IntSize size(0,0); @@ -954,6 +993,19 @@ MyGUI::IntSize HBox::getRequestedSize () if (i != getChildCount()-1) size.width += mSpacing; } + else + { + MyGUI::IntSize requested = getChildAt(i)->getSize (); + size.height = std::max(size.height, requested.height); + + if (getChildAt(i)->getUserString("HStretch") != "true") + size.width = size.width + requested.width; + + if (i != getChildCount()-1) + size.width += mSpacing; + } + size.height += mPadding*2; + size.width += mPadding*2; } return size; } @@ -963,7 +1015,69 @@ MyGUI::IntSize HBox::getRequestedSize () void VBox::align () { - // not yet implemented + unsigned int count = getChildCount (); + size_t v_stretched_count = 0; + int total_height = 0; + int total_width = 0; + std::vector< std::pair > sizes; + for (unsigned int i = 0; i < count; ++i) + { + MyGUI::Widget* w = getChildAt(i); + bool vstretch = w->getUserString ("VStretch") == "true"; + v_stretched_count += vstretch; + AutoSizedWidget* aw = dynamic_cast(w); + if (aw) + { + sizes.push_back(std::make_pair(aw->getRequestedSize (), vstretch)); + total_height += aw->getRequestedSize ().height; + total_width = std::max(total_width, aw->getRequestedSize ().width); + } + else + { + sizes.push_back (std::make_pair(w->getSize(), vstretch)); + total_height += w->getSize().height; + } + + if (i != count-1) + total_height += mSpacing; + } + + if (mAutoResize && (total_width+mPadding*2 != getSize().width || total_height+mPadding*2 != getSize().height)) + { + setSize(MyGUI::IntSize(total_width+mPadding*2, total_height+mPadding*2)); + return; + } + + + int curY = 0; + for (unsigned int i = 0; i < count; ++i) + { + if (i==0) + curY += mPadding; + + MyGUI::Widget* w = getChildAt(i); + + bool hstretch = w->getUserString ("HStretch") == "true"; + int width = hstretch ? total_width : sizes[i].first.width; + + MyGUI::IntCoord widgetCoord; + widgetCoord.top = curY; + widgetCoord.left = mPadding + (getSize().width-mPadding*2 - width) / 2; + int height = sizes[i].second ? sizes[i].first.height + (getSize().height-mPadding*2 - total_height)/v_stretched_count + : sizes[i].first.height; + widgetCoord.height = height; + widgetCoord.width = width; + w->setCoord(widgetCoord); + curY += height; + + if (i != count-1) + curY += mSpacing; + } +} + +void VBox::setPropertyOverride(const std::string& _key, const std::string& _value) +{ + Box::_setPropertyImpl (_key, _value); } void VBox::setSize (const MyGUI::IntSize& _value) @@ -972,6 +1086,12 @@ void VBox::setSize (const MyGUI::IntSize& _value) align(); } +void VBox::setCoord (const MyGUI::IntCoord& _value) +{ + MyGUI::Widget::setCoord (_value); + align(); +} + MyGUI::IntSize VBox::getRequestedSize () { MyGUI::IntSize size(0,0); @@ -986,6 +1106,29 @@ MyGUI::IntSize VBox::getRequestedSize () if (i != getChildCount()-1) size.height += mSpacing; } + else + { + MyGUI::IntSize requested = getChildAt(i)->getSize (); + size.width = std::max(size.width, requested.width); + + if (getChildAt(i)->getUserString("VStretch") != "true") + size.height = size.height + requested.height; + + if (i != getChildCount()-1) + size.height += mSpacing; + } + size.height += mPadding*2; + size.width += mPadding*2; } return size; } + +void VBox::onWidgetCreated(MyGUI::Widget* _widget) +{ + align(); +} + +void VBox::onWidgetDestroy(MyGUI::Widget* _widget) +{ + align(); +} diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 16c2adec9..6298ea77d 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -357,10 +357,13 @@ namespace MWGui protected: virtual void align() = 0; - virtual void setPropertyOverride(const std::string& _key, const std::string& _value); - + virtual void _setPropertyImpl(const std::string& _key, const std::string& _value); int mSpacing; // how much space to put between elements + + int mPadding; // outer padding + + bool mAutoResize; // auto resize the box so that it exactly fits all elements }; class HBox : public Box, public MyGUI::Widget @@ -369,10 +372,16 @@ namespace MWGui public: virtual void setSize (const MyGUI::IntSize &_value); + virtual void setCoord (const MyGUI::IntCoord &_value); protected: virtual void align(); virtual MyGUI::IntSize getRequestedSize(); + + virtual void setPropertyOverride(const std::string& _key, const std::string& _value); + + virtual void onWidgetCreated(MyGUI::Widget* _widget); + virtual void onWidgetDestroy(MyGUI::Widget* _widget); }; class VBox : public Box, public MyGUI::Widget @@ -381,10 +390,16 @@ namespace MWGui public: virtual void setSize (const MyGUI::IntSize &_value); + virtual void setCoord (const MyGUI::IntCoord &_value); protected: virtual void align(); virtual MyGUI::IntSize getRequestedSize(); + + virtual void setPropertyOverride(const std::string& _key, const std::string& _value); + + virtual void onWidgetCreated(MyGUI::Widget* _widget); + virtual void onWidgetDestroy(MyGUI::Widget* _widget); }; } } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 728243d5f..c72ad9854 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -45,6 +45,7 @@ #include "quickkeysmenu.hpp" #include "loadingscreen.hpp" #include "levelupdialog.hpp" +#include "waitdialog.hpp" using namespace MWGui; @@ -71,6 +72,8 @@ WindowManager::WindowManager( , mSpellWindow(NULL) , mLoadingScreen(NULL) , mCharGen(NULL) + , mLevelupDialog(NULL) + , mWaitDialog(NULL) , mPlayerClass() , mPlayerName() , mPlayerRaceId() @@ -150,6 +153,7 @@ WindowManager::WindowManager( mSpellWindow = new SpellWindow(*this); mQuickKeysMenu = new QuickKeysMenu(*this); mLevelupDialog = new LevelupDialog(*this); + mWaitDialog = new WaitDialog(*this); mLoadingScreen = new LoadingScreen(mOgre->getScene (), mOgre->getWindow (), *this); mLoadingScreen->onResChange (w,h); @@ -204,6 +208,7 @@ WindowManager::~WindowManager() delete mSpellWindow; delete mLoadingScreen; delete mLevelupDialog; + delete mWaitDialog; cleanupGarbage(); @@ -252,6 +257,7 @@ void WindowManager::updateVisible() mSpellWindow->setVisible(false); mQuickKeysMenu->setVisible(false); mLevelupDialog->setVisible(false); + mWaitDialog->setVisible(false); mHud->setVisible(true); @@ -304,6 +310,13 @@ void WindowManager::updateVisible() mAlchemyWindow->setVisible(true); break; case GM_Rest: + mWaitDialog->setVisible(true); + break; + case GM_RestBed: + mWaitDialog->setVisible(true); + mWaitDialog->bedActivated(); + break; + case GM_Levelup: mLevelupDialog->setVisible(true); break; case GM_Name: @@ -540,6 +553,8 @@ void WindowManager::onFrame (float frameDuration) mStatsWindow->onFrame(); + mWaitDialog->onFrame(frameDuration); + mHud->onFrame(frameDuration); mDialogueWindow->checkReferenceAvailable(); @@ -934,3 +949,8 @@ void WindowManager::loadingDone () { mLoadingScreen->loadingDone (); } + +bool WindowManager::getPlayerSleeping () +{ + return mWaitDialog->getSleeping(); +} diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index a02aa17b5..0ed5e1fea 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -63,6 +63,7 @@ namespace MWGui class QuickKeysMenu; class LoadingScreen; class LevelupDialog; + class WaitDialog; class WindowManager : public MWBase::WindowManager { @@ -203,6 +204,8 @@ namespace MWGui virtual void enableRest() { mRestAllowed = true; } virtual bool getRestEnabled() { return mRestAllowed; } + virtual bool getPlayerSleeping(); + private: OEngine::GUI::MyGUIManager *mGuiManager; HUD *mHud; @@ -229,6 +232,7 @@ namespace MWGui QuickKeysMenu* mQuickKeysMenu; LoadingScreen* mLoadingScreen; LevelupDialog* mLevelupDialog; + WaitDialog* mWaitDialog; CharacterCreation* mCharGen; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index fdf4910f8..5d1d3d690 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -77,12 +77,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor bodyRaceID = "b_n_"+ref->base->race; std::transform(bodyRaceID.begin(), bodyRaceID.end(), bodyRaceID.begin(), ::tolower); - /*std::cout << "Race: " << ref->base->race ; - if(female) - std::cout << " Sex: Female" << " Height: " << race->data.height.female << "\n"; - else - std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n"; - */ mInsert = node; assert(mInsert); @@ -129,6 +123,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor } } + + if(isFemale) mInsert->scale(race->data.height.female, race->data.height.female, race->data.height.female); else diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 603d2e16c..3f1bf6826 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -131,6 +131,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const sh::Factory::getInstance ().setSharedParameter ("waterTimer", sh::makeProperty(new sh::FloatValue(0))); sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty(new sh::Vector3(0.5, -0.8, 0.2))); sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty(new sh::Vector2(1, 0.6))); + sh::Factory::getInstance ().setSharedParameter ("gammaCorrection", sh::makeProperty(new sh::FloatValue( + Settings::Manager::getFloat ("gamma", "Video")))); applyCompositors(); @@ -280,13 +282,15 @@ RenderingManager::rotateObject( float *f = ptr.getRefData().getPosition().rot; rot.x += f[0], rot.y += f[1], rot.z += f[2]; } + if (!isPlayer && isActive) { Ogre::Quaternion xr(Ogre::Radian(rot.x), Ogre::Vector3::UNIT_X); Ogre::Quaternion yr(Ogre::Radian(rot.y), Ogre::Vector3::UNIT_Y); Ogre::Quaternion zr(Ogre::Radian(rot.z), Ogre::Vector3::UNIT_Z); - + ptr.getRefData().getBaseNode()->setOrientation(xr * yr * zr); } + return force; } @@ -752,6 +756,11 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec sh::Factory::getInstance ().setShadersEnabled (Settings::Manager::getBool("shaders", "Objects")); mObjects.rebuildStaticGeometry (); } + else if (it->second == "gamma" && it->first == "Video") + { + sh::Factory::getInstance ().setSharedParameter ("gammaCorrection", sh::makeProperty(new sh::FloatValue( + Settings::Manager::getFloat ("gamma", "Video")))); + } else if (it->second == "shader mode" && it->first == "General") { sh::Language lang; diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index d58045a0a..a9f2cd143 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -202,5 +202,6 @@ op 0x200019b: PlaceItem op 0x200019c: PlaceAtPc op 0x200019d: PlaceAtMe op 0x200019e: PlaceAtMe Explicit -opcodes 0x200019f-0x3ffffff unused +op 0x200019f: GetPcSleep +opcodes 0x20001a0-0x3ffffff unused diff --git a/apps/openmw/mwscript/guiextensions.cpp b/apps/openmw/mwscript/guiextensions.cpp index 7f3b9777b..6e5540fa8 100644 --- a/apps/openmw/mwscript/guiextensions.cpp +++ b/apps/openmw/mwscript/guiextensions.cpp @@ -160,7 +160,7 @@ opcodeEnableStatsReviewMenu); new OpEnableRest ()); interpreter.installSegment5 (opcodeShowRestMenu, - new OpShowDialogue (MWGui::GM_Rest)); + new OpShowDialogue (MWGui::GM_RestBed)); interpreter.installSegment5 (opcodeGetButtonPressed, new OpGetButtonPressed); diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 864c1a1ee..a869f882b 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -10,6 +10,7 @@ #include #include "../mwbase/environment.hpp" +#include "../mwbase/windowmanager.hpp" #include "../mwworld/class.hpp" @@ -20,6 +21,16 @@ namespace MWScript { namespace Misc { + class OpGetPcSleep : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + runtime.push (MWBase::Environment::get().getWindowManager ()->getPlayerSleeping()); + } + }; + class OpXBox : public Interpreter::Opcode0 { public: @@ -249,6 +260,7 @@ namespace MWScript const int opcodeTogglePathgrid = 0x2000146; const int opcodeDontSaveObject = 0x2000153; const int opcodeToggleVanityMode = 0x2000174; + const int opcodeGetPcSleep = 0x200019f; void registerExtensions (Compiler::Extensions& extensions) { @@ -273,6 +285,7 @@ namespace MWScript extensions.registerInstruction ("dontsaveobject", "", opcodeDontSaveObject); extensions.registerInstruction ("togglevanitymode", "", opcodeToggleVanityMode); extensions.registerInstruction ("tvm", "", opcodeToggleVanityMode); + extensions.registerFunction ("getpcsleep", 'l', "", opcodeGetPcSleep); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -293,6 +306,7 @@ namespace MWScript interpreter.installSegment5 (opcodeToggleWater, new OpToggleWater); interpreter.installSegment5 (opcodeDontSaveObject, new OpDontSaveObject); interpreter.installSegment5 (opcodeToggleVanityMode, new OpToggleVanityMode); + interpreter.installSegment5 (opcodeGetPcSleep, new OpGetPcSleep); } } } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index b7cb2778d..8de415980 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -96,6 +96,10 @@ namespace MWWorld if(hasWater){ playerphysics->waterHeight = waterHeight; } + for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) + { + it->second->setCurrentWater(hasWater, waterHeight); + } } @@ -172,17 +176,20 @@ namespace MWWorld //set the DebugRenderingMode. To disable it,set it to 0 //eng->setDebugRenderingMode(1); - //set the walkdirection to 0 (no movement) for every actor) + //set the movement keys to 0 (no movement) for every actor) for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) { OEngine::Physic::PhysicActor* act = it->second; - act->setWalkDirection(btVector3(0,0,0)); + act->setMovement(0,0,0); } + playerMove::playercmd& pm_ref = playerphysics->cmd; + pm_ref.rightmove = 0; pm_ref.forwardmove = 0; pm_ref.upmove = 0; + //playerphysics->ps.move_type = PM_NOCLIP; for (std::vector >::const_iterator iter (actors.begin()); @@ -193,10 +200,12 @@ namespace MWWorld playerphysics->ps.viewangles.x = Ogre::Radian(mPlayerData.pitch).valueDegrees(); + + playerphysics->ps.viewangles.y = Ogre::Radian(mPlayerData.yaw).valueDegrees() + 90; - pm_ref.rightmove = -iter->second.x; + pm_ref.rightmove = iter->second.x; pm_ref.forwardmove = -iter->second.y; pm_ref.upmove = iter->second.z; } @@ -208,16 +217,17 @@ namespace MWWorld const std::vector >& actors) { Pmove(playerphysics); + std::vector< std::pair > response; for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) { - btVector3 newPos = it->second->getPosition(); - Ogre::Vector3 coord(newPos.x(), newPos.y(), newPos.z()); + Ogre::Vector3 coord = it->second->getPosition(); if(it->first == "player"){ - coord = playerphysics->ps.origin; + coord = playerphysics->ps.origin ; + } @@ -243,21 +253,15 @@ namespace MWWorld const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position) { handleToMesh[handle] = mesh; - OEngine::Physic::RigidBody* body = mEngine->createRigidBody(mesh,handle,scale); + OEngine::Physic::RigidBody* body = mEngine->createAndAdjustRigidBody(mesh,handle,scale, position, rotation); mEngine->addRigidBody(body); - btTransform tr; - tr.setOrigin(btVector3(position.x,position.y,position.z)); - tr.setRotation(btQuaternion(rotation.x,rotation.y,rotation.z,rotation.w)); - body->setWorldTransform(tr); } void PhysicsSystem::addActor (const std::string& handle, const std::string& mesh, - const Ogre::Vector3& position) + const Ogre::Vector3& position, float scale, const Ogre::Quaternion& rotation) { //TODO:optimize this. Searching the std::map isn't very efficient i think. - mEngine->addCharacter(handle); - OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle); - act->setPosition(btVector3(position.x,position.y,position.z)); + mEngine->addCharacter(handle, mesh, position, scale, rotation); } void PhysicsSystem::removeObject (const std::string& handle) @@ -268,15 +272,25 @@ namespace MWWorld mEngine->deleteRigidBody(handle); } - void PhysicsSystem::moveObject (const std::string& handle, const Ogre::Vector3& position) + void PhysicsSystem::moveObject (const std::string& handle, Ogre::SceneNode* node) { + Ogre::Vector3 position = node->getPosition(); if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle)) { // TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow // start positions others than 0, 0, 0 - btTransform tr = body->getWorldTransform(); - tr.setOrigin(btVector3(position.x,position.y,position.z)); - body->setWorldTransform(tr); + + + if(dynamic_cast(body->getCollisionShape()) == NULL){ + btTransform tr = body->getWorldTransform(); + tr.setOrigin(btVector3(position.x,position.y,position.z)); + body->setWorldTransform(tr); + } + else{ + //For objects that contain a box shape. + //Do any such objects exist? Perhaps animated objects? + mEngine->boxAdjustExternal(handleToMesh[handle], body, node->getScale().x, position, node->getOrientation()); + } } if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle)) { @@ -288,34 +302,45 @@ namespace MWWorld } else { - act->setPosition(btVector3(position.x,position.y,position.z)); + act->setPosition(position); } } } - void PhysicsSystem::rotateObject (const std::string& handle, const Ogre::Quaternion& rotation) + void PhysicsSystem::rotateObject (const std::string& handle, Ogre::SceneNode* node) { + Ogre::Quaternion rotation = node->getOrientation(); if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle)) { - act->setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w)); + //Needs to be changed + act->setRotation(rotation); } if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle)) { - body->getWorldTransform().setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w)); + if(dynamic_cast(body->getCollisionShape()) == NULL) + body->getWorldTransform().setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w)); + else + mEngine->boxAdjustExternal(handleToMesh[handle], body, node->getScale().x, node->getPosition(), rotation); } } - void PhysicsSystem::scaleObject (const std::string& handle, float scale) + void PhysicsSystem::scaleObject (const std::string& handle, Ogre::SceneNode* node) { if(handleToMesh.find(handle) != handleToMesh.end()) { - btTransform transform = mEngine->getRigidBody(handle)->getWorldTransform(); removeObject(handle); - Ogre::Quaternion quat = Ogre::Quaternion(transform.getRotation().getW(), transform.getRotation().getX(), transform.getRotation().getY(), transform.getRotation().getZ()); - Ogre::Vector3 vec = Ogre::Vector3(transform.getOrigin().getX(), transform.getOrigin().getY(), transform.getOrigin().getZ()); + float scale = node->getScale().x; + Ogre::Quaternion quat = node->getOrientation(); + Ogre::Vector3 vec = node->getPosition(); addObject(handle, handleToMesh[handle], quat, scale, vec); } + + if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle)) + { + float scale = node->getScale().x; + act->setScale(scale); + } } bool PhysicsSystem::toggleCollisionMode() @@ -335,8 +360,6 @@ namespace MWWorld if(cmode) { act->enableCollisions(false); - act->setGravity(0.); - act->setVerticalVelocity(0); mFreeFly = true; return false; } @@ -344,8 +367,6 @@ namespace MWWorld { mFreeFly = false; act->enableCollisions(true); - act->setGravity(4.); - act->setVerticalVelocity(0); return true; } } @@ -368,7 +389,7 @@ namespace MWWorld void PhysicsSystem::insertActorPhysics(const MWWorld::Ptr& ptr, const std::string model){ Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); - addActor (node->getName(), model, node->getPosition()); + addActor (node->getName(), model, node->getPosition(), node->getScale().x, node->getOrientation()); } bool PhysicsSystem::getObjectAABB(const MWWorld::Ptr &ptr, Ogre::Vector3 &min, Ogre::Vector3 &max) diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index c6b8199fa..1427060f6 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -24,7 +24,7 @@ namespace MWWorld const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position); void addActor (const std::string& handle, const std::string& mesh, - const Ogre::Vector3& position); + const Ogre::Vector3& position, float scale, const Ogre::Quaternion& rotation); void addHeightField (float* heights, int x, int y, float yoffset, @@ -34,11 +34,11 @@ namespace MWWorld void removeObject (const std::string& handle); - void moveObject (const std::string& handle, const Ogre::Vector3& position); + void moveObject (const std::string& handle, Ogre::SceneNode* node); - void rotateObject (const std::string& handle, const Ogre::Quaternion& rotation); + void rotateObject (const std::string& handle, Ogre::SceneNode* node); - void scaleObject (const std::string& handle, float scale); + void scaleObject (const std::string& handle, Ogre::SceneNode* node); bool toggleCollisionMode(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 592f2b4b6..d0fbf4bd6 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -189,7 +189,9 @@ namespace MWWorld mPlayer = new MWWorld::Player (mStore.npcs.find ("player"), *this); mRendering->attachCameraTo(mPlayer->getPlayer()); - mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0)); + std::string playerCollisionFile = "meshes\\base_anim.nif"; //This is used to make a collision shape for our player + //We will need to support the 1st person file too in the future + mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), playerCollisionFile, Ogre::Vector3 (0, 0, 0), 1, Ogre::Quaternion::ZERO); // global variables mGlobalVariables = new Globals (mStore); @@ -450,6 +452,16 @@ namespace MWWorld mRendering->skySetDate (mGlobalVariables->getInt ("day"), month); } + int World::getDay() + { + return mGlobalVariables->getInt("day"); + } + + int World::getMonth() + { + return mGlobalVariables->getInt("month"); + } + TimeStamp World::getTimeStamp() const { return TimeStamp (mGlobalVariables->getFloat ("gamehour"), @@ -603,7 +615,7 @@ namespace MWWorld } if (haveToMove) { mRendering->moveObject(ptr, vec); - mPhysics->moveObject(ptr.getRefData().getHandle(), vec); + mPhysics->moveObject (ptr.getRefData().getHandle(), ptr.getRefData().getBaseNode()); } } @@ -624,6 +636,8 @@ namespace MWWorld void World::moveObject (const Ptr& ptr, float x, float y, float z) { moveObjectImp(ptr, x, y, z); + + } void World::scaleObject (const Ptr& ptr, float scale) @@ -633,7 +647,7 @@ namespace MWWorld ptr.getCellRef().scale = scale; //scale = scale/ptr.getRefData().getBaseNode()->getScale().x; ptr.getRefData().getBaseNode()->setScale(scale,scale,scale); - mPhysics->scaleObject( ptr.getRefData().getHandle(), scale ); + mPhysics->scaleObject( ptr.getRefData().getHandle(), ptr.getRefData().getBaseNode()); } void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust) @@ -642,18 +656,20 @@ namespace MWWorld rot.x = Ogre::Degree(x).valueRadians(); rot.y = Ogre::Degree(y).valueRadians(); rot.z = Ogre::Degree(z).valueRadians(); - + if (mRendering->rotateObject(ptr, rot, adjust)) { float *objRot = ptr.getRefData().getPosition().rot; objRot[0] = rot.x, objRot[1] = rot.y, objRot[2] = rot.z; + if (ptr.getRefData().getBaseNode() != 0) { mPhysics->rotateObject( ptr.getRefData().getHandle(), - ptr.getRefData().getBaseNode()->getOrientation() + ptr.getRefData().getBaseNode() ); } } + } void World::safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos) @@ -1246,4 +1262,28 @@ namespace MWWorld { mRendering->setupExternalRendering (rendering); } + + int World::canRest () + { + Ptr::CellStore *currentCell = mWorldScene->getCurrentCell(); + + Ogre::Vector3 playerPos; + float* pos = mPlayer->getPlayer ().getRefData ().getPosition ().pos; + playerPos.x = pos[0]; + playerPos.y = pos[1]; + playerPos.z = pos[2]; + + std::pair hit = + mPhysics->castRay(playerPos, Ogre::Vector3(0,0,-1), 50); + bool isOnGround = (hit.first ? (hit.second.distance (playerPos) < 25) : false); + + if (!isOnGround || isUnderwater (*currentCell->cell, playerPos)) + return 2; + + if (currentCell->cell->data.flags & ESM::Cell::NoSleep) + return 1; + + return 0; + + } } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index dfb9238f5..5c5727905 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -179,6 +179,9 @@ namespace MWWorld virtual void setDay (int day); ///< Set in-game time day. + virtual int getDay(); + virtual int getMonth(); + virtual TimeStamp getTimeStamp() const; ///< Return current in-game time stamp. @@ -313,6 +316,13 @@ namespace MWWorld virtual void renderGlobalMap(); virtual void setupExternalRendering (MWRender::ExternalRendering& rendering); + + virtual int canRest(); + ///< check if the player is allowed to rest \n + /// 0 - yes \n + /// 1 - only waiting \n + /// 2 - player is underwater \n + /// 3 - enemies are nearby (not implemented) }; } diff --git a/components/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bullet_nif_loader.cpp index 0fb758ea8..a70eb7629 100644 --- a/components/nifbullet/bullet_nif_loader.cpp +++ b/components/nifbullet/bullet_nif_loader.cpp @@ -72,6 +72,9 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) cShape = static_cast(resource); resourceName = cShape->getName(); cShape->collide = false; + mBoundingBox = NULL; + cShape->boxTranslation = Ogre::Vector3(0,0,0); + cShape->boxRotation = Ogre::Quaternion::IDENTITY; mTriMesh = new btTriangleMesh(); @@ -125,9 +128,14 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) delete m_meshInterface; } }; + if(mBoundingBox != NULL) + cShape->Shape = mBoundingBox; - currentShape = new TriangleMeshShape(mTriMesh,true); - cShape->Shape = currentShape; + else + { + currentShape = new TriangleMeshShape(mTriMesh,true); + cShape->Shape = currentShape; + } } bool ManualBulletShapeLoader::hasRootCollisionNode(Nif::Node* node) @@ -218,6 +226,17 @@ void ManualBulletShapeLoader::handleNode(Nif::Node *node, int flags, } + if(node->hasBounds) + { + + + btVector3 boxsize = getbtVector((node->boundXYZ)); + cShape->boxTranslation = node->boundPos; + cShape->boxRotation = node->boundRot; + + mBoundingBox = new btBoxShape(boxsize); + } + // For NiNodes, loop through children if (node->recType == Nif::RC_NiNode) diff --git a/components/nifbullet/bullet_nif_loader.hpp b/components/nifbullet/bullet_nif_loader.hpp index 88e1ab189..82ac227a0 100644 --- a/components/nifbullet/bullet_nif_loader.hpp +++ b/components/nifbullet/bullet_nif_loader.hpp @@ -102,8 +102,11 @@ private: std::string resourceName; std::string resourceGroup; + + BulletShape* cShape;//current shape btTriangleMesh *mTriMesh; + btBoxShape *mBoundingBox; btBvhTriangleMeshShape* currentShape;//the shape curently under construction }; diff --git a/files/materials/core.h b/files/materials/core.h index cba716777..e9577bbf3 100644 --- a/files/materials/core.h +++ b/files/materials/core.h @@ -1,3 +1,7 @@ +#define gammaCorrectRead(v) pow(v, float3(gammaCorrection,gammaCorrection,gammaCorrection)) +#define gammaCorrectOutput(v) pow(v, float3(1.f/gammaCorrection,1.f/gammaCorrection,1.f/gammaCorrection)) + + #if SH_HLSL == 1 || SH_CG == 1 #define shTexture2D sampler2D diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 8e5cbf76e..45f33774d 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -112,6 +112,8 @@ shUniform(float, far) @shAutoConstant(far, far_clip_distance) #endif + shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection) + #if LIGHTING shInput(float3, normalPassthrough) shInput(float3, objSpacePositionPassthrough) @@ -173,7 +175,8 @@ SH_START_PROGRAM { shOutputColour(0) = shSample(diffuseMap, UV); - + shOutputColour(0).xyz = gammaCorrectRead(shOutputColour(0).xyz); + #if LIGHTING float3 normal = normalize(normalPassthrough); float3 lightDir; @@ -259,7 +262,7 @@ // regular fog only if fragment is above water if (worldPos.y > waterLevel) #endif - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, gammaCorrectRead(fogColour), fogValue); #endif // prevent negative colour output (for example with negative lights) @@ -274,12 +277,11 @@ float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); - float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; + float3 waterSunColour = gammaCorrectRead(float3(0.0,1.0,0.85)) *waterSunGradient * 0.5; float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0)); waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); - float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; - float3 waterext = float3(0.6, 0.9, 1.0);//water extinction + float3 watercolour = ( gammaCorrectRead(float3(0.0078, 0.5176, 0.700))+waterSunColour)*waterGradient*2.0; watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); watercolour = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3; @@ -292,6 +294,8 @@ shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater * waterEnabled); #endif + shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz); + #if MRT shOutputColour(1) = float4(depthPassthrough / far,1,1,1); #endif diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 7ef26d035..9183595e3 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -137,6 +137,8 @@ shSampler2D(normalMap) // global normal map + shUniform(float, gammaCorrection) @shSharedParameter(gammaCorrection, gammaCorrection) + @shForeach(@shPropertyString(num_blendmaps)) shSampler2D(blendMap@shIterator) @@ -247,9 +249,9 @@ #if IS_FIRST_PASS == 1 && @shIterator == 0 // first layer of first pass doesn't need a blend map - albedo = shSample(diffuseMap0, UV * 10).rgb; + albedo = gammaCorrectRead(shSample(diffuseMap0, UV * 10).rgb); #else - albedo = shLerp(albedo, shSample(diffuseMap@shIterator, UV * 10).rgb, blendValues@shPropertyString(blendmap_component_@shIterator)); + albedo = shLerp(albedo, gammaCorrectRead(shSample(diffuseMap@shIterator, UV * 10).rgb), blendValues@shPropertyString(blendmap_component_@shIterator)); #endif @shEndForeach @@ -336,7 +338,7 @@ // regular fog only if fragment is above water if (worldPos.y > waterLevel) #endif - shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, fogColour, fogValue); + shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, gammaCorrectRead(fogColour), fogValue); #endif // prevent negative colour output (for example with negative lights) @@ -351,12 +353,12 @@ float waterSunGradient = dot(eyeVec, -normalize(lightDirectionWS0.xyz)); waterSunGradient = shSaturate(pow(waterSunGradient*0.7+0.3,2.0)); - float3 waterSunColour = float3(0.0,1.0,0.85)*waterSunGradient * 0.5; + float3 waterSunColour = gammaCorrectRead(float3(0.0,1.0,0.85))*waterSunGradient * 0.5; float waterGradient = dot(eyeVec, float3(0.0,-1.0,0.0)); waterGradient = clamp((waterGradient*0.5+0.5),0.2,1.0); - float3 watercolour = (float3(0.0078, 0.5176, 0.700)+waterSunColour)*waterGradient*2.0; - float3 waterext = float3(0.6, 0.9, 1.0);//water extinction + float3 watercolour = (gammaCorrectRead(float3(0.0078, 0.5176, 0.700))+waterSunColour)*waterGradient*2.0; + float3 waterext = gammaCorrectRead(float3(0.6, 0.9, 1.0));//water extinction watercolour = shLerp(watercolour*0.3*waterSunFade_sunHeight.x, watercolour, shSaturate(1.0-exp(-waterSunFade_sunHeight.y*SUN_EXT))); watercolour = (cameraPos.y <= waterLevel) ? watercolour : watercolour*0.3; @@ -369,6 +371,8 @@ shOutputColour(0).xyz = shLerp (shOutputColour(0).xyz, watercolour, fogAmount * isUnderwater); #endif + shOutputColour(0).xyz = gammaCorrectOutput(shOutputColour(0).xyz); + #if MRT shOutputColour(1) = float4(depth / far,1,1,1); diff --git a/files/mygui/CMakeLists.txt b/files/mygui/CMakeLists.txt index 55230fa76..ae8d3afbe 100644 --- a/files/mygui/CMakeLists.txt +++ b/files/mygui/CMakeLists.txt @@ -73,6 +73,8 @@ set(MYGUI_FILES openmw_spell_buying_window.layout openmw_loading_screen.layout openmw_levelup_dialog.layout + openmw_wait_dialog.layout + openmw_wait_dialog_progressbar.layout smallbars.png VeraMono.ttf markers.png diff --git a/files/mygui/openmw_alchemy_window.layout b/files/mygui/openmw_alchemy_window.layout index 458d24b2c..8471f69df 100644 --- a/files/mygui/openmw_alchemy_window.layout +++ b/files/mygui/openmw_alchemy_window.layout @@ -77,8 +77,9 @@ - - + + + diff --git a/files/mygui/openmw_chargen_birth.layout b/files/mygui/openmw_chargen_birth.layout index 5edec72d3..f4b8c518d 100644 --- a/files/mygui/openmw_chargen_birth.layout +++ b/files/mygui/openmw_chargen_birth.layout @@ -15,7 +15,9 @@ - + + + diff --git a/files/mygui/openmw_chargen_class.layout b/files/mygui/openmw_chargen_class.layout index baa36b24a..00e3793bc 100644 --- a/files/mygui/openmw_chargen_class.layout +++ b/files/mygui/openmw_chargen_class.layout @@ -61,7 +61,9 @@ - + + + diff --git a/files/mygui/openmw_chargen_create_class.layout b/files/mygui/openmw_chargen_create_class.layout index 5e08db6e5..54f73f221 100644 --- a/files/mygui/openmw_chargen_create_class.layout +++ b/files/mygui/openmw_chargen_create_class.layout @@ -59,7 +59,9 @@ - + + + diff --git a/files/mygui/openmw_chargen_generate_class_result.layout b/files/mygui/openmw_chargen_generate_class_result.layout index 65dbf016c..aa4a89d28 100644 --- a/files/mygui/openmw_chargen_generate_class_result.layout +++ b/files/mygui/openmw_chargen_generate_class_result.layout @@ -21,7 +21,9 @@ - + + + diff --git a/files/mygui/openmw_chargen_race.layout b/files/mygui/openmw_chargen_race.layout index b69073899..a9ec9905d 100644 --- a/files/mygui/openmw_chargen_race.layout +++ b/files/mygui/openmw_chargen_race.layout @@ -57,7 +57,10 @@ - + + + + diff --git a/files/mygui/openmw_chargen_review.layout b/files/mygui/openmw_chargen_review.layout index dbe7a4780..97e32cfe2 100644 --- a/files/mygui/openmw_chargen_review.layout +++ b/files/mygui/openmw_chargen_review.layout @@ -112,7 +112,9 @@ - + + + diff --git a/files/mygui/openmw_confirmation_dialog.layout b/files/mygui/openmw_confirmation_dialog.layout index fe7f7cbf6..46b477407 100644 --- a/files/mygui/openmw_confirmation_dialog.layout +++ b/files/mygui/openmw_confirmation_dialog.layout @@ -14,7 +14,9 @@ - + + + diff --git a/files/mygui/openmw_container_window.layout b/files/mygui/openmw_container_window.layout index 896566fdd..94e9458a5 100644 --- a/files/mygui/openmw_container_window.layout +++ b/files/mygui/openmw_container_window.layout @@ -12,7 +12,9 @@ - + + + diff --git a/files/mygui/openmw_count_window.layout b/files/mygui/openmw_count_window.layout index a021d7df9..5812ec7fd 100644 --- a/files/mygui/openmw_count_window.layout +++ b/files/mygui/openmw_count_window.layout @@ -22,7 +22,9 @@ - + + + diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 38d2786e5..2f9b5a67f 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -157,7 +157,7 @@ - + @@ -174,20 +174,37 @@ - + - + - + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_trade_window.layout b/files/mygui/openmw_trade_window.layout index 7de6c85e6..d38377f98 100644 --- a/files/mygui/openmw_trade_window.layout +++ b/files/mygui/openmw_trade_window.layout @@ -56,7 +56,9 @@ - + + + diff --git a/files/mygui/openmw_wait_dialog.layout b/files/mygui/openmw_wait_dialog.layout new file mode 100644 index 000000000..66e0ec22f --- /dev/null +++ b/files/mygui/openmw_wait_dialog.layout @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/files/mygui/openmw_wait_dialog_progressbar.layout b/files/mygui/openmw_wait_dialog_progressbar.layout new file mode 100644 index 000000000..93793fd8e --- /dev/null +++ b/files/mygui/openmw_wait_dialog_progressbar.layout @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 6a77b7fc0..1768b2f5e 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -28,6 +28,8 @@ vsync = false # PBuffer, FBO, Copy opengl rtt mode = FBO +gamma = 2.2 + [GUI] # 1 is fully opaque menu transparency = 0.84 diff --git a/libs/openengine/bullet/BulletShapeLoader.h b/libs/openengine/bullet/BulletShapeLoader.h index 316ee523c..8640fd54f 100644 --- a/libs/openengine/bullet/BulletShapeLoader.h +++ b/libs/openengine/bullet/BulletShapeLoader.h @@ -4,7 +4,7 @@ #include #include #include - +#include //For some reason, Ogre Singleton cannot be used in another namespace, that's why there is no namespace here. //But the risk of name collision seems pretty low here. @@ -31,6 +31,8 @@ public: virtual ~BulletShape(); btCollisionShape* Shape; + Ogre::Vector3 boxTranslation; + Ogre::Quaternion boxRotation; //this flag indicate if the shape is used for collision or if it's for raycasting only. bool collide; }; diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index a778aef3a..74352b358 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "pmove.h" #include #include "CMotionState.h" #include "OgreRoot.h" @@ -26,111 +27,139 @@ namespace Physic COL_RAYCASTING = BIT(3) }; - PhysicActor::PhysicActor(std::string name) + PhysicActor::PhysicActor(std::string name, std::string mesh, PhysicEngine* engine, Ogre::Vector3 position, Ogre::Quaternion rotation, float scale): + mName(name), mEngine(engine), mMesh(mesh), mBoxScaledTranslation(0,0,0), mBoxRotationInverse(0,0,0,0), mBody(0), collisionMode(false), mBoxRotation(0,0,0,0) { - mName = name; - - // The capsule is at the origin - btTransform transform; - transform.setIdentity(); - - // External capsule - externalGhostObject = new PairCachingGhostObject(name); - externalGhostObject->setWorldTransform( transform ); - - btScalar externalCapsuleHeight = 120; - btScalar externalCapsuleWidth = 19; - - externalCollisionShape = new btCapsuleShapeZ( externalCapsuleWidth, externalCapsuleHeight ); - externalCollisionShape->setMargin( 0.1 ); - - externalGhostObject->setCollisionShape( externalCollisionShape ); - externalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); - - // Internal capsule - internalGhostObject = new PairCachingGhostObject(name); - internalGhostObject->setWorldTransform( transform ); - //internalGhostObject->getBroadphaseHandle()->s - btScalar internalCapsuleHeight = 110; - btScalar internalCapsuleWidth = 17; - - internalCollisionShape = new btCapsuleShapeZ( internalCapsuleWidth, internalCapsuleHeight ); - internalCollisionShape->setMargin( 0.1 ); - - internalGhostObject->setCollisionShape( internalCollisionShape ); - internalGhostObject->setCollisionFlags( btCollisionObject::CF_CHARACTER_OBJECT ); - - mCharacter = new btKinematicCharacterController( externalGhostObject,internalGhostObject,btScalar( 40 ),1,4,20,9.8,0.2 ); - mCharacter->setUpAxis(btKinematicCharacterController::Z_AXIS); - mCharacter->setUseGhostSweepTest(false); - - mCharacter->mCollision = false; - setGravity(0); - - mTranslation = btVector3(0,0,70); + mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation, &mBoxScaledTranslation, &mBoxRotation); + Ogre::Quaternion inverse = mBoxRotation.Inverse(); + mBoxRotationInverse = btQuaternion(inverse.x, inverse.y, inverse.z,inverse.w); + mEngine->addRigidBody(mBody, false); //Add rigid body to dynamics world, but do not add to object map + pmove = new playerMove; + pmove->mEngine = mEngine; + btBoxShape* box = static_cast (mBody->getCollisionShape()); + if(box != NULL){ + btVector3 size = box->getHalfExtentsWithMargin(); + Ogre::Vector3 halfExtents = Ogre::Vector3(size.getX(), size.getY(), size.getZ()); + pmove->ps.halfExtents = halfExtents; + } } PhysicActor::~PhysicActor() { - delete mCharacter; - delete internalGhostObject; - delete internalCollisionShape; - delete externalGhostObject; - delete externalCollisionShape; + if(mBody){ + mEngine->dynamicsWorld->removeRigidBody(mBody); + delete mBody; + } + delete pmove; + } + + void PhysicActor::setCurrentWater(bool hasWater, int waterHeight){ + pmove->hasWater = hasWater; + if(hasWater){ + pmove->waterHeight = waterHeight; + } } void PhysicActor::setGravity(float gravity) { - mCharacter->setGravity(gravity); - //mCharacter-> + pmove->ps.gravity = gravity; + } + + void PhysicActor::setSpeed(float speed) + { + pmove->ps.speed = speed; } void PhysicActor::enableCollisions(bool collision) { - mCharacter->mCollision = collision; + collisionMode = collision; + if(collisionMode) + pmove->ps.move_type=PM_NORMAL; + else + pmove->ps.move_type=PM_NOCLIP; } - void PhysicActor::setVerticalVelocity(float z) + void PhysicActor::setJumpVelocity(float velocity) { - mCharacter->setVerticalVelocity(z); + pmove->ps.jump_velocity = velocity; } bool PhysicActor::getCollisionMode() { - return mCharacter->mCollision; + return collisionMode; } - void PhysicActor::setWalkDirection(const btVector3& mvt) + void PhysicActor::setMovement(signed char rightmove, signed char forwardmove, signed char upmove) { - mCharacter->setWalkDirection( mvt ); + playerMove::playercmd& pm_ref = pmove->cmd; + pm_ref.rightmove = rightmove; + pm_ref.forwardmove = forwardmove; + pm_ref.upmove = upmove; } - void PhysicActor::Rotate(const btQuaternion& quat) - { - externalGhostObject->getWorldTransform().setRotation( externalGhostObject->getWorldTransform().getRotation() * quat ); - internalGhostObject->getWorldTransform().setRotation( internalGhostObject->getWorldTransform().getRotation() * quat ); + void PhysicActor::setPmoveViewAngles(float pitch, float yaw, float roll){ + pmove->ps.viewangles.x = pitch; + pmove->ps.viewangles.y = yaw; + pmove->ps.viewangles.z = roll; } - void PhysicActor::setRotation(const btQuaternion& quat) + + + void PhysicActor::setRotation(const Ogre::Quaternion quat) { - externalGhostObject->getWorldTransform().setRotation( quat ); - internalGhostObject->getWorldTransform().setRotation( quat ); + if(!quat.equals(getRotation(), Ogre::Radian(0))){ + mEngine->adjustRigidBody(mBody, getPosition(), quat, mBoxScaledTranslation, mBoxRotation); + } } - btVector3 PhysicActor::getPosition(void) + Ogre::Vector3 PhysicActor::getPosition() { - return internalGhostObject->getWorldTransform().getOrigin() -mTranslation; + btVector3 vec = mBody->getWorldTransform().getOrigin(); + Ogre::Quaternion rotation = Ogre::Quaternion(mBody->getWorldTransform().getRotation().getW(), mBody->getWorldTransform().getRotation().getX(), + mBody->getWorldTransform().getRotation().getY(), mBody->getWorldTransform().getRotation().getZ()); + Ogre::Vector3 transrot = rotation * mBoxScaledTranslation; + Ogre::Vector3 visualPosition = Ogre::Vector3(vec.getX(), vec.getY(), vec.getZ()) - transrot; + return visualPosition; } - btQuaternion PhysicActor::getRotation(void) + Ogre::Quaternion PhysicActor::getRotation() { - return internalGhostObject->getWorldTransform().getRotation(); + btQuaternion quat = mBody->getWorldTransform().getRotation() * mBoxRotationInverse; + return Ogre::Quaternion(quat.getW(), quat.getX(), quat.getY(), quat.getZ()); } - void PhysicActor::setPosition(const btVector3& pos) + void PhysicActor::setPosition(const Ogre::Vector3 pos) { - internalGhostObject->getWorldTransform().setOrigin(pos+mTranslation); - externalGhostObject->getWorldTransform().setOrigin(pos+mTranslation); + mEngine->adjustRigidBody(mBody, pos, getRotation(), mBoxScaledTranslation, mBoxRotation); + btVector3 vec = mBody->getWorldTransform().getOrigin(); + pmove->ps.origin = Ogre::Vector3(vec.getX(), vec.getY(), vec.getZ()); + } + + void PhysicActor::setScale(float scale){ + Ogre::Vector3 position = getPosition(); + Ogre::Quaternion rotation = getRotation(); + //We only need to change the scaled box translation, box rotations remain the same. + mBoxScaledTranslation = mBoxScaledTranslation / mBody->getCollisionShape()->getLocalScaling().getX(); + mBoxScaledTranslation *= scale; + if(mBody){ + mEngine->dynamicsWorld->removeRigidBody(mBody); + delete mBody; + } + //Create the newly scaled rigid body + mBody = mEngine->createAndAdjustRigidBody(mMesh, mName, scale, position, rotation); + mEngine->addRigidBody(mBody, false); //Add rigid body to dynamics world, but do not add to object map + btBoxShape* box = static_cast (mBody->getCollisionShape()); + if(box != NULL){ + btVector3 size = box->getHalfExtentsWithMargin(); + Ogre::Vector3 halfExtents = Ogre::Vector3(size.getX(), size.getY(), size.getZ()); + pmove->ps.halfExtents = halfExtents; + } + } + + void PhysicActor::runPmove(){ + Pmove(pmove); + Ogre::Vector3 newpos = pmove->ps.origin; + mBody->getWorldTransform().setOrigin(btVector3(newpos.x, newpos.y, newpos.z)); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -230,8 +259,8 @@ namespace Physic delete hf_it->second.mBody; } - RigidBodyContainer::iterator rb_it = RigidBodyMap.begin(); - for (; rb_it != RigidBodyMap.end(); ++rb_it) + RigidBodyContainer::iterator rb_it = ObjectMap.begin(); + for (; rb_it != ObjectMap.end(); ++rb_it) { if (rb_it->second != NULL) { @@ -247,9 +276,7 @@ namespace Physic { if (pa_it->second != NULL) { - dynamicsWorld->removeCollisionObject(pa_it->second->externalGhostObject); - dynamicsWorld->removeCollisionObject(pa_it->second->internalGhostObject); - dynamicsWorld->removeAction(pa_it->second->mCharacter); + delete pa_it->second; pa_it->second = NULL; @@ -332,18 +359,42 @@ namespace Physic mHeightFieldMap.erase(name); } - RigidBody* PhysicEngine::createRigidBody(std::string mesh,std::string name,float scale) - { + void PhysicEngine::adjustRigidBody(RigidBody* body, Ogre::Vector3 position, Ogre::Quaternion rotation, + Ogre::Vector3 scaledBoxTranslation, Ogre::Quaternion boxRotation){ + btTransform tr; + rotation = rotation * boxRotation; + Ogre::Vector3 transrot = rotation * scaledBoxTranslation; + Ogre::Vector3 newPosition = transrot + position; + + tr.setOrigin(btVector3(newPosition.x, newPosition.y, newPosition.z)); + tr.setRotation(btQuaternion(rotation.x,rotation.y,rotation.z,rotation.w)); + body->setWorldTransform(tr); + } + void PhysicEngine::boxAdjustExternal(std::string mesh, RigidBody* body, float scale, Ogre::Vector3 position, Ogre::Quaternion rotation){ std::string sid = (boost::format("%07.3f") % scale).str(); std::string outputstring = mesh + sid; //std::cout << "The string" << outputstring << "\n"; + //get the shape from the .nif + mShapeLoader->load(outputstring,"General"); + BulletShapeManager::getSingletonPtr()->load(outputstring,"General"); + BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General"); + + adjustRigidBody(body, position, rotation, shape->boxTranslation * scale, shape->boxRotation); + } + + RigidBody* PhysicEngine::createAndAdjustRigidBody(std::string mesh,std::string name,float scale, Ogre::Vector3 position, Ogre::Quaternion rotation, + Ogre::Vector3* scaledBoxTranslation, Ogre::Quaternion* boxRotation) + { + std::string sid = (boost::format("%07.3f") % scale).str(); + std::string outputstring = mesh + sid; + //get the shape from the .nif mShapeLoader->load(outputstring,"General"); BulletShapeManager::getSingletonPtr()->load(outputstring,"General"); BulletShapePtr shape = BulletShapeManager::getSingleton().getByName(outputstring,"General"); shape->Shape->setLocalScaling( btVector3(scale,scale,scale)); - //btScaledBvhTriangleMeshShape* scaled = new btScaledBvhTriangleMeshShape(dynamic_cast (shape->Shape), btVector3(scale,scale,scale)); + //create the motionState CMotionState* newMotionState = new CMotionState(this,name); @@ -352,11 +403,19 @@ namespace Physic btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo(0,newMotionState,shape->Shape); RigidBody* body = new RigidBody(CI,name); body->collide = shape->collide; + + if(scaledBoxTranslation != 0) + *scaledBoxTranslation = shape->boxTranslation * scale; + if(boxRotation != 0) + *boxRotation = shape->boxRotation; + + adjustRigidBody(body, position, rotation, shape->boxTranslation * scale, shape->boxRotation); + return body; } - void PhysicEngine::addRigidBody(RigidBody* body) + void PhysicEngine::addRigidBody(RigidBody* body, bool addToMap) { if(body) { @@ -369,21 +428,23 @@ namespace Physic dynamicsWorld->addRigidBody(body,COL_RAYCASTING,COL_RAYCASTING|COL_WORLD); } body->setActivationState(DISABLE_DEACTIVATION); - RigidBody* oldBody = RigidBodyMap[body->mName]; - if (oldBody != NULL) - { - dynamicsWorld->removeRigidBody(oldBody); - delete oldBody; - } + if(addToMap){ + RigidBody* oldBody = ObjectMap[body->mName]; + if (oldBody != NULL) + { + dynamicsWorld->removeRigidBody(oldBody); + delete oldBody; + } - RigidBodyMap[body->mName] = body; + ObjectMap[body->mName] = body; + } } } void PhysicEngine::removeRigidBody(std::string name) { - RigidBodyContainer::iterator it = RigidBodyMap.find(name); - if (it != RigidBodyMap.end() ) + RigidBodyContainer::iterator it = ObjectMap.find(name); + if (it != ObjectMap.end() ) { RigidBody* body = it->second; if(body != NULL) @@ -402,8 +463,8 @@ namespace Physic void PhysicEngine::deleteRigidBody(std::string name) { - RigidBodyContainer::iterator it = RigidBodyMap.find(name); - if (it != RigidBodyMap.end() ) + RigidBodyContainer::iterator it = ObjectMap.find(name); + if (it != ObjectMap.end() ) { RigidBody* body = it->second; //btScaledBvhTriangleMeshShape* scaled = dynamic_cast (body->getCollisionShape()); @@ -416,16 +477,16 @@ namespace Physic { delete scaled; }*/ - RigidBodyMap.erase(it); + ObjectMap.erase(it); } } RigidBody* PhysicEngine::getRigidBody(std::string name) { - RigidBodyContainer::iterator it = RigidBodyMap.find(name); - if (it != RigidBodyMap.end() ) + RigidBodyContainer::iterator it = ObjectMap.find(name); + if (it != ObjectMap.end() ) { - RigidBody* body = RigidBodyMap[name]; + RigidBody* body = ObjectMap[name]; return body; } else @@ -443,16 +504,17 @@ namespace Physic } } - void PhysicEngine::addCharacter(std::string name) + void PhysicEngine::addCharacter(std::string name, std::string mesh, + Ogre::Vector3 position, float scale, Ogre::Quaternion rotation) { // Remove character with given name, so we don't make memory // leak when character would be added twice removeCharacter(name); - PhysicActor* newActor = new PhysicActor(name); - dynamicsWorld->addCollisionObject( newActor->externalGhostObject, COL_ACTOR_EXTERNAL, COL_WORLD |COL_ACTOR_EXTERNAL ); - dynamicsWorld->addCollisionObject( newActor->internalGhostObject, COL_ACTOR_INTERNAL, COL_WORLD |COL_ACTOR_INTERNAL ); - dynamicsWorld->addAction( newActor->mCharacter ); + PhysicActor* newActor = new PhysicActor(name, mesh, this, position, rotation, scale); + + + //dynamicsWorld->addAction( newActor->mCharacter ); PhysicActorMap[name] = newActor; } @@ -465,25 +527,11 @@ namespace Physic PhysicActor* act = it->second; if(act != NULL) { - /*broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher); - broadphase->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher); - PhysicActorContainer::iterator it2 = PhysicActorMap.begin(); - for(;it2!=PhysicActorMap.end();it++) - { - it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher); - it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->externalGhostObject->getBroadphaseHandle(),dispatcher); - it->second->internalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher); - it->second->externalGhostObject->getOverlappingPairCache()->removeOverlappingPairsContainingProxy(act->internalGhostObject->getBroadphaseHandle(),dispatcher); - }*/ - //act->externalGhostObject-> - dynamicsWorld->removeCollisionObject(act->externalGhostObject); - dynamicsWorld->removeCollisionObject(act->internalGhostObject); - dynamicsWorld->removeAction(act->mCharacter); + delete act; } PhysicActorMap.erase(it); } - //std::cout << "ok"; } PhysicActor* PhysicEngine::getCharacter(std::string name) diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 9ae8e7607..e4e71706f 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -9,14 +9,16 @@ #include "BulletShapeLoader.h" #include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" + + class btRigidBody; class btBroadphaseInterface; class btDefaultCollisionConfiguration; class btSequentialImpulseConstraintSolver; class btCollisionDispatcher; class btDiscreteDynamicsWorld; -class btKinematicCharacterController; class btHeightfieldTerrainShape; +struct playerMove; namespace BtOgre { @@ -28,11 +30,14 @@ namespace MWWorld class World; } + namespace OEngine { namespace Physic { class CMotionState; struct PhysicEvent; + class PhysicEngine; + class RigidBody; /** *This is just used to be able to name objects. @@ -50,55 +55,88 @@ namespace Physic }; /** - * A physic Actor use a modifed KinematicCharacterController taken in the bullet forum. + * A physic actor uses a rigid body based on box shapes. + * Pmove is used to move the physic actor around the dynamic world. */ class PhysicActor { public: - PhysicActor(std::string name); + PhysicActor(std::string name, std::string mesh, PhysicEngine *engine, Ogre::Vector3 position, Ogre::Quaternion rotation, float scale); ~PhysicActor(); + void setCurrentWater(bool hasWater, int waterHeight); + /** - * This function set the walkDirection. This is not relative to the actor orientation. - * I think it's also needed to take time into account. A typical call should look like this: - * setWalkDirection( mvt * orientation * dt) + * This function sets the movement keys for pmove */ - void setWalkDirection(const btVector3& mvt); + void setMovement(signed char rightmove, signed char forwardmove, signed char upmove); - void Rotate(const btQuaternion& quat); - - void setRotation(const btQuaternion& quat); + /** + * This adjusts the rotation of a PhysicActor + * If we have any problems with this (getting stuck in pmove) we should change it + * from setting the visual orientation to setting the orientation of the rigid body directly. + */ + void setRotation(const Ogre::Quaternion quat); void setGravity(float gravity); - void setVerticalVelocity(float z); + void setSpeed(float speed); + + void setJumpVelocity(float velocity); void enableCollisions(bool collision); bool getCollisionMode(); - btVector3 getPosition(void); - - btQuaternion getRotation(void); - - void setPosition(const btVector3& pos); - - btKinematicCharacterController* mCharacter; - - PairCachingGhostObject* internalGhostObject; - btCollisionShape* internalCollisionShape; - - PairCachingGhostObject* externalGhostObject; - btCollisionShape* externalCollisionShape; - - std::string mName; + /** + * This returns the visual position of the PhysicActor (used to position a scenenode). + * Note - this is different from the position of the contained mBody. + */ + Ogre::Vector3 getPosition(); /** - *NPC scenenode is located on there feet, and you can't simply translate a btShape, so this vector is used - *each time get/setposition is called. - */ - btVector3 mTranslation; + * Returns the visual orientation of the PhysicActor + */ + Ogre::Quaternion getRotation(); + + /** + * Sets the position of mBody from a visual position input. + * For most cases this should not be used. We should instead let pmove move the PhysicActor around for us + */ + void setPosition(const Ogre::Vector3 pos); + + /** + * Sets the view angles for pmove directly. + * Remember, add 90 for yaw. Set roll to 0. + */ + void setPmoveViewAngles(float pitch, float yaw, float roll); + + /** + * Sets the scale of the PhysicActor + */ + void setScale(float scale); + + /** + * Runs pmove for this PhysicActor + */ + void runPmove(); + + + + + private: + + OEngine::Physic::RigidBody* mBody; + Ogre::Vector3 mBoxScaledTranslation; + btQuaternion mBoxRotationInverse; + Ogre::Quaternion mBoxRotation; + bool collisionMode; + std::string mMesh; + PhysicEngine* mEngine; + std::string mName; + playerMove* pmove; + }; /** @@ -143,11 +181,22 @@ namespace Physic ~PhysicEngine(); /** - * Create a RigidBody.It does not add it to the simulation, but it does add it to the rigidBody Map, - * so you can get it with the getRigidBody function. + * Creates a RigidBody. It does not add it to the simulation. + * After created, the body is set to the correct rotation, position, and scale */ - RigidBody* createRigidBody(std::string mesh,std::string name,float scale); + RigidBody* createAndAdjustRigidBody(std::string mesh,std::string name,float scale, Ogre::Vector3 position, Ogre::Quaternion rotation, + Ogre::Vector3* scaledBoxTranslation = 0, Ogre::Quaternion* boxRotation = 0); + /** + * Adjusts a rigid body to the right position and rotation + */ + + void adjustRigidBody(RigidBody* body, Ogre::Vector3 position, Ogre::Quaternion rotation, + Ogre::Vector3 scaledBoxTranslation = Ogre::Vector3::ZERO, Ogre::Quaternion boxRotation = Ogre::Quaternion::IDENTITY); + /** + Mainly used to (but not limited to) adjust rigid bodies based on box shapes to the right position and rotation. + */ + void boxAdjustExternal(std::string mesh, RigidBody* body, float scale, Ogre::Vector3 position, Ogre::Quaternion rotation); /** * Add a HeightField to the simulation */ @@ -163,7 +212,7 @@ namespace Physic /** * Add a RigidBody to the simulation */ - void addRigidBody(RigidBody* body); + void addRigidBody(RigidBody* body, bool addToMap = true); /** * Remove a RigidBody from the simulation. It does not delete it, and does not remove it from the RigidBodyMap. @@ -184,7 +233,8 @@ namespace Physic /** * Create and add a character to the scene, and add it to the ActorMap. */ - void addCharacter(std::string name); + void addCharacter(std::string name, std::string mesh, + Ogre::Vector3 position, float scale, Ogre::Quaternion rotation); /** * Remove a character from the scene. TODO:delete it! for now, a small memory leak^^ done? @@ -254,7 +304,7 @@ namespace Physic HeightFieldContainer mHeightFieldMap; typedef std::map RigidBodyContainer; - RigidBodyContainer RigidBodyMap; + RigidBodyContainer ObjectMap; typedef std::map PhysicActorContainer; PhysicActorContainer PhysicActorMap; @@ -263,6 +313,7 @@ namespace Physic BtOgre::DebugDrawer* mDebugDrawer; bool isDebugCreated; bool mDebugActive; + }; diff --git a/libs/openengine/bullet/pmove.cpp b/libs/openengine/bullet/pmove.cpp index e13e9e6c0..645abf205 100644 --- a/libs/openengine/bullet/pmove.cpp +++ b/libs/openengine/bullet/pmove.cpp @@ -231,7 +231,7 @@ bool PM_SlideMove( bool gravity ) // see if we can make it there //pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemaskg); //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&(end), *(const D3DXVECTOR3* const)&(pm->ps.velocity), 0, pml.traceObj); - newtrace(&trace, pm->ps.origin, end, halfExtents, Ogre::Math::DegreesToRadians (pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + newtrace(&trace, pm->ps.origin, end, pm->ps.halfExtents, Ogre::Math::DegreesToRadians (pm->ps.viewangles.y), pm->isInterior, pm->mEngine); if (trace.allsolid) { @@ -301,7 +301,7 @@ bool PM_SlideMove( bool gravity ) if(planes[i].x >= .70) { - pm->ps.velocity = Ogre::Vector3(0,0,0); + pm->ps.velocity.z = 0; return true; } // see how hard we are hitting things @@ -449,7 +449,7 @@ int PM_StepSlideMove( bool gravity ) //pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); //tracefunc(&trace, start_o, down, , 0, pml.scene); //tracefunc(&trace, *(const D3DXVECTOR3* const)&start_o, *(const D3DXVECTOR3* const)&down, D3DXVECTOR3(0.0f, -STEPSIZE, 0.0f), 0, pml.traceObj); - newtrace(&trace, start_o, down, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + newtrace(&trace, down, start_o, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); // up = vec3(0, 0, 1) //VectorSet(up, 0, 0, 1); @@ -479,7 +479,7 @@ int PM_StepSlideMove( bool gravity ) // test the player position if they were a stepheight higher //pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask); //tracefunc(&trace, *(const D3DXVECTOR3* const)&start_o, *(const D3DXVECTOR3* const)&up, D3DXVECTOR3(0.0f, STEPSIZE, 0.0f), 0, pml.traceObj); - newtrace(&trace, start_o, up, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + newtrace(&trace, start_o, up, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); if ( trace.allsolid ) { //if ( pm->debugLevel ) @@ -510,7 +510,7 @@ int PM_StepSlideMove( bool gravity ) //pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask); //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&down, D3DXVECTOR3(0.0f, -STEPSIZE, 0.0f), 0, pml.traceObj); - newtrace(&trace, pm->ps.origin, down, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + newtrace(&trace, pm->ps.origin, down, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); if ( !trace.allsolid ) //VectorCopy (trace.endpos, pm->ps->origin); pm->ps.origin = trace.endpos; @@ -527,7 +527,7 @@ int PM_StepSlideMove( bool gravity ) delta = pm->ps.origin.z - start_o.z; if ( delta > 2 ) { - pm->ps.counter = 5; + pm->ps.counter = 10; /* if (gravity) @@ -657,10 +657,11 @@ static void PM_Accelerate( Ogre::Vector3& wishdir, float wishspeed, float accel // int i; float addspeed, accelspeed, currentspeed; + // currentspeed = pm->ps->velocity dot wishdir //currentspeed = DotProduct (pm->ps->velocity, wishdir); currentspeed = pm->ps.velocity.dotProduct(wishdir); - + addspeed = wishspeed - currentspeed; if (addspeed <= 0) return; @@ -675,6 +676,8 @@ static void PM_Accelerate( Ogre::Vector3& wishdir, float wishspeed, float accel //for (i=0 ; i<3 ; i++) //pm->ps->velocity[i] += accelspeed * wishdir[i]; pm->ps.velocity += (wishdir * accelspeed); + //pm->ps.velocity = wishdir * wishspeed; //New, for instant acceleration + } static bool PM_CheckJump(void) @@ -701,7 +704,7 @@ static bool PM_CheckJump(void) //pm->ps->pm_flags |= PMF_JUMP_HELD; pm->ps.groundEntityNum = ENTITYNUM_NONE; - pm->ps.velocity.z = JUMP_VELOCITY; + pm->ps.velocity.z = pm->ps.jump_velocity; pm->ps.bSnap = false; //PM_AddEvent( EV_JUMP ); @@ -899,7 +902,7 @@ static void PM_WalkMove( playerMove* const pmove ) if (pmove->hasWater ) { const float waterHeight = pmove->waterHeight; - const float waterSoundStepHeight = waterHeight + halfExtents.y; + const float waterSoundStepHeight = waterHeight + pm->ps.halfExtents.y; if (pmove->ps.origin.y < waterSoundStepHeight) step_underwater = true; } @@ -1179,7 +1182,7 @@ void PM_GroundTraceMissed() //pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -64.0f, 0.0f), 0, pml.traceObj); - newtrace(&trace, pm->ps.origin, point, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + newtrace(&trace, pm->ps.origin, point, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); //It hit the ground below if ( trace.fraction < 1.0 && pm->ps.origin.z > trace.endpos.z) { @@ -1225,7 +1228,7 @@ static bool PM_CorrectAllSolid(traceResults* const trace) //pm->trace (trace, point, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); //tracefunc(trace, *(const D3DXVECTOR3* const)&point, *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, 0.0f, 0.0f), 0, pml.traceObj); - newtrace(trace, point, point, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + newtrace(trace, point, point, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); if ( !trace->allsolid ) { @@ -1237,7 +1240,7 @@ static bool PM_CorrectAllSolid(traceResults* const trace) //pm->trace (trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); //tracefunc(trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -0.25f, 0.0f), 0, pml.traceObj); - newtrace(trace, pm->ps.origin, point, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + newtrace(trace, pm->ps.origin, point, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); pml.groundTrace = *trace; return true; } @@ -1338,7 +1341,7 @@ static void PM_CrashLand( void ) { const float waterHeight = pm->waterHeight; - const float waterHeightSplash = waterHeight + halfExtents.y; + const float waterHeightSplash = waterHeight + pm->ps.halfExtents.y; if (pm->ps.origin.z < waterHeightSplash) { splashSound = true; @@ -1413,7 +1416,7 @@ static void PM_GroundTrace( void ) //pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); //tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -0.25f, 0.0f), 0, pml.traceObj); - newtrace(&trace, pm->ps.origin, point, halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); + newtrace(&trace, pm->ps.origin, point, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine); pml.groundTrace = trace; // do something corrective if the trace starts in a solid... diff --git a/libs/openengine/bullet/pmove.h b/libs/openengine/bullet/pmove.h index aea63d1db..fa303184e 100644 --- a/libs/openengine/bullet/pmove.h +++ b/libs/openengine/bullet/pmove.h @@ -23,7 +23,7 @@ Quake 3 Arena is copyright (C) 1999-2005 Id Software, Inc. extern SceneInstance* global_lastscene; #endif*/ -static const Ogre::Vector3 halfExtents(14.64f * 2, 14.24f * 2, 33.25f * 2); +static const Ogre::Vector3 halfExtentsDefault(14.64f * 2, 14.24f * 2, 33.25f * 2); #define MAX_CLIP_PLANES 5 #define OVERCLIP 1.001f @@ -42,7 +42,6 @@ static const Ogre::Vector3 halfExtents(14.64f * 2, 14.24f * 2, 33.25f * 2); #define ENTITYNUM_NONE (MAX_GENTITIES - 1) #define ENTITYNUM_WORLD (MAX_GENTITIES - 2) #define MIN_WALK_NORMAL .7f // can't walk on very steep slopes -#define JUMP_VELOCITY (270) #define PS_PMOVEFRAMECOUNTBITS 6 #define MINS_Z -24 #define DEFAULT_VIEWHEIGHT 26 @@ -90,9 +89,9 @@ struct playerMove { struct playerStruct { - playerStruct() : gravity(800.0f), speed(480.0f), pmove_framecount(20), groundEntityNum(ENTITYNUM_NONE), commandTime(40), move_type(PM_NOCLIP), pm_time(0), snappingImplemented(true), bSnap(false), counter(-1) + playerStruct() : gravity(800.0f), speed(480.0f), jump_velocity(270), pmove_framecount(20), groundEntityNum(ENTITYNUM_NONE), commandTime(40), move_type(PM_NOCLIP), pm_time(0), snappingImplemented(true), bSnap(false), counter(-1), halfExtents(halfExtentsDefault) { - origin = Ogre::Vector3(733.164f,900.0f, 839.432f); + origin = Ogre::Vector3(0.0f, 0.0f, 0.0f); velocity = Ogre::Vector3(0.0f, 0.0f, 0.0f); viewangles = Ogre::Vector3(0.0f, 0.0f, 0.0f); @@ -117,11 +116,13 @@ struct playerMove Ogre::Vector3 velocity; Ogre::Vector3 origin; + Ogre::Vector3 halfExtents; bool bSnap; bool snappingImplemented; int counter; float gravity; // default = 800 float speed; // default = 320 + float jump_velocity; //default = 270 int commandTime; // the time at which this command was issued (in milliseconds) diff --git a/libs/openengine/bullet/trace.cpp b/libs/openengine/bullet/trace.cpp index 89d654e6a..03ed4ffb1 100644 --- a/libs/openengine/bullet/trace.cpp +++ b/libs/openengine/bullet/trace.cpp @@ -13,18 +13,22 @@ void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::Vector3& BBHalfExtents, const float rotation, bool isInterior, OEngine::Physic::PhysicEngine* enginePass) //Traceobj was a Aedra Object { - + static float lastyaw = 0.0f; + static float lastpitch = 0.0f; //if (!traceobj) // return; //if (!traceobj->incellptr) // return; + const Ogre::Vector3 rayDir = end - start; + + + - // Nudge starting point backwards - //const Position3D nudgestart = start + (rayDir * -0.1f); // by 10% (isn't that too much?) - //const Position3D nudgestart = start; + + NewPhysTraceResults out; //std::cout << "Starting trace\n"; @@ -32,7 +36,7 @@ void newtrace(traceResults* const results, const Ogre::Vector3& start, const Ogr //Ogre::Vector3 endReplace = startReplace; //endReplace.z -= .25; - const bool hasHit = NewPhysicsTrace(&out, start, end, BBHalfExtents, Ogre::Vector3(0.0f, 0.0, rotation), isInterior, enginePass); + const bool hasHit = NewPhysicsTrace(&out, start, end, BBHalfExtents, Ogre::Vector3(0.0f, 0.0f, 0.0f), isInterior, enginePass); if (out.fraction < 0.001f) results->startsolid = true; @@ -95,13 +99,14 @@ const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& //if(enginePass->dynamicsWorld->getCollisionObjectArray().at(60)->getCollisionShape()->isConvex()) // std::cout << "It's convex\n"; - + const btVector3 btstart(start.x, start.y, start.z + BBHalfExtents.z); const btVector3 btend(end.x, end.y, end.z + BBHalfExtents.z); const btQuaternion btrot(rotation.y, rotation.x, rotation.z); //y, x, z - const btBoxShape newshape(btVector3(BBHalfExtents.x, BBHalfExtents.y, BBHalfExtents.z)); + const btBoxShape newshape(btVector3(BBHalfExtents.x, BBHalfExtents.y, BBHalfExtents.z)); + //const btCapsuleShapeZ newshape(BBHalfExtents.x, BBHalfExtents.z * 2 - BBHalfExtents.x * 2); const btTransform from(btrot, btstart); const btTransform to(btrot, btend); @@ -176,7 +181,8 @@ const bool NewPhysicsTrace(NewPhysTraceResults* const out, const Ogre::Vector3& if (!TestPointAgainstAabb2(aabbMin, aabbMax, *(const btVector3* const)&(start) ) ) { //We're solid - out->startSolid = true; + //THIS NEEDS TO BE TURNED OFF IF WE WANT FALLING IN EXTERIORS TO WORK CORRECTLY!!!!!!! + //out->startSolid = true; } } } diff --git a/libs/openengine/bullet/trace.h b/libs/openengine/bullet/trace.h index 076baf56e..1bfe0c717 100644 --- a/libs/openengine/bullet/trace.h +++ b/libs/openengine/bullet/trace.h @@ -5,9 +5,8 @@ #include #include #include -#include #include - +#include "pmove.h" enum traceWorldType diff --git a/libs/openengine/ogre/fader.cpp b/libs/openengine/ogre/fader.cpp index 41b7773ea..ba532b527 100644 --- a/libs/openengine/ogre/fader.cpp +++ b/libs/openengine/ogre/fader.cpp @@ -1,52 +1,50 @@ #include "fader.hpp" -#include -#include -#include #include #include #include #include +#include +#include -#define FADE_OVERLAY_NAME "FadeInOutOverlay" -#define FADE_OVERLAY_PANEL_NAME "FadeInOutOverlayPanel" -#define FADE_MATERIAL_NAME "FadeInOutMaterial" using namespace Ogre; using namespace OEngine::Render; -Fader::Fader() : - mMode(FadingMode_In), - mRemainingTime(0.f), - mTargetTime(0.f), - mTargetAlpha(0.f), - mCurrentAlpha(0.f), - mStartAlpha(0.f) +Fader::Fader(Ogre::SceneManager* sceneMgr) + : mSceneMgr(sceneMgr) + , mMode(FadingMode_In) + , mRemainingTime(0.f) + , mTargetTime(0.f) + , mTargetAlpha(0.f) + , mCurrentAlpha(0.f) + , mStartAlpha(0.f) { - // Create the fading material - MaterialPtr material = MaterialManager::getSingleton().create( FADE_MATERIAL_NAME, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); + MaterialPtr material = MaterialManager::getSingleton().create("FadeInOutMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); Pass* pass = material->getTechnique(0)->getPass(0); pass->setSceneBlending(SBT_TRANSPARENT_ALPHA); mFadeTextureUnit = pass->createTextureUnitState(); mFadeTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(0.f, 0.f, 0.f)); // always black colour - // Create the overlay - OverlayManager& ovm = OverlayManager::getSingleton(); + mRectangle = new Ogre::Rectangle2D(true); + mRectangle->setCorners(-1.0, 1.0, 1.0, -1.0); + mRectangle->setMaterial("FadeInOutMaterial"); + mRectangle->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY-1); + // Use infinite AAB to always stay visible + Ogre::AxisAlignedBox aabInf; + aabInf.setInfinite(); + mRectangle->setBoundingBox(aabInf); + // Attach background to the scene + Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode(); + node->attachObject(mRectangle); + mRectangle->setVisible(false); + mRectangle->setVisibilityFlags (0x01); +} - mOverlay = ovm.create( FADE_OVERLAY_NAME ); - - OverlayContainer* overlay_panel; - overlay_panel = (OverlayContainer*)ovm.createOverlayElement("Panel", FADE_OVERLAY_PANEL_NAME); - - // position it over the whole screen - overlay_panel->_setPosition(0, 0); - overlay_panel->_setDimensions(1, 1); - - overlay_panel->setMaterialName( FADE_MATERIAL_NAME ); - overlay_panel->show(); - mOverlay->add2D(overlay_panel); - mOverlay->hide(); +Fader::~Fader() +{ + delete mRectangle; } void Fader::update(float dt) @@ -69,12 +67,12 @@ void Fader::update(float dt) mRemainingTime -= dt; } - if (mCurrentAlpha == 0.f) mOverlay->hide(); + if (mCurrentAlpha == 0.f) mRectangle->setVisible(false); } void Fader::applyAlpha() { - mOverlay->show(); + mRectangle->setVisible(true); mFadeTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, mCurrentAlpha); } diff --git a/libs/openengine/ogre/fader.hpp b/libs/openengine/ogre/fader.hpp index efb12a5d2..bddf5dc91 100644 --- a/libs/openengine/ogre/fader.hpp +++ b/libs/openengine/ogre/fader.hpp @@ -4,52 +4,52 @@ /* A class that handles fading in the screen from black or fading it out to black. - To achieve this, it uses a full-screen Ogre::Overlay - - inspired by http://www.ogre3d.org/tikiwiki/FadeEffectOverlay (heavily adjusted) + To achieve this, it uses a full-screen Rectangle2d */ namespace Ogre { class TextureUnitState; - class Overlay; + class Rectangle2D; + class SceneManager; } namespace OEngine { namespace Render { - class Fader - { - public: - Fader(); - - void update(float dt); - - void fadeIn(const float time); - void fadeOut(const float time); - void fadeTo(const int percent, const float time); - - private: - enum FadingMode + class Fader { - FadingMode_In, - FadingMode_Out + public: + Fader(Ogre::SceneManager* sceneMgr); + ~Fader(); + + void update(float dt); + + void fadeIn(const float time); + void fadeOut(const float time); + void fadeTo(const int percent, const float time); + + private: + enum FadingMode + { + FadingMode_In, + FadingMode_Out + }; + + void applyAlpha(); + + Ogre::TextureUnitState* mFadeTextureUnit; + Ogre::Rectangle2D* mRectangle; + + FadingMode mMode; + + float mRemainingTime; + float mTargetTime; + float mTargetAlpha; + float mCurrentAlpha; + float mStartAlpha; + + Ogre::SceneManager* mSceneMgr; }; - - void applyAlpha(); - - Ogre::TextureUnitState* mFadeTextureUnit; - Ogre::Overlay* mOverlay; - - FadingMode mMode; - - float mRemainingTime; - float mTargetTime; - float mTargetAlpha; - float mCurrentAlpha; - float mStartAlpha; - - protected: - }; -}} + }} #endif diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 5f3435c52..87ebe1139 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -247,7 +247,7 @@ void OgreRenderer::createScene(const std::string& camName, float fov, float near // Alter the camera aspect ratio to match the viewport mCamera->setAspectRatio(Real(mView->getActualWidth()) / Real(mView->getActualHeight())); - mFader = new Fader(); + mFader = new Fader(mScene); } void OgreRenderer::adjustViewport()