From 51d9c2c7809ff555bad7601cd37d0fcd9248f44c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Nov 2011 14:16:20 +0100 Subject: [PATCH 01/47] fixed argument type in ai related script instructions --- apps/openmw/mwscript/aiextensions.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 6d74ae45a..aa541e55d 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -25,13 +25,13 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - Interpreter::Type_Float x = runtime[0].mInteger; + Interpreter::Type_Float x = runtime[0].mFloat; runtime.pop(); - Interpreter::Type_Float y = runtime[0].mInteger; + Interpreter::Type_Float y = runtime[0].mFloat; runtime.pop(); - Interpreter::Type_Float z = runtime[0].mInteger; + Interpreter::Type_Float z = runtime[0].mFloat; runtime.pop(); // discard additional arguments (reset), because we have no idea what they mean. @@ -53,16 +53,16 @@ namespace MWScript std::string actor = runtime.getStringLiteral (runtime[0].mInteger); runtime.pop(); - Interpreter::Type_Float duration = runtime[0].mInteger; + Interpreter::Type_Float duration = runtime[0].mFloat; runtime.pop(); - Interpreter::Type_Float x = runtime[0].mInteger; + Interpreter::Type_Float x = runtime[0].mFloat; runtime.pop(); - Interpreter::Type_Float y = runtime[0].mInteger; + Interpreter::Type_Float y = runtime[0].mFloat; runtime.pop(); - Interpreter::Type_Float z = runtime[0].mInteger; + Interpreter::Type_Float z = runtime[0].mFloat; runtime.pop(); // discard additional arguments (reset), because we have no idea what they mean. @@ -99,9 +99,9 @@ namespace MWScript void registerExtensions (Compiler::Extensions& extensions) { - extensions.registerInstruction ("aitravel", "lll/l", opcodeAiTravel, + extensions.registerInstruction ("aitravel", "fff/l", opcodeAiTravel, opcodeAiTravelExplicit); - extensions.registerInstruction ("aiescort", "cllll/l", opcodeAiEscort, + extensions.registerInstruction ("aiescort", "cffff/l", opcodeAiEscort, opcodeAiEscortExplicit); extensions.registerFunction ("getaipackagedone", 'l', "", opcodeGetAiPackageDone, From bc51ba5a38a3c032a96ac84e16497b7271f5b97b Mon Sep 17 00:00:00 2001 From: gugus Date: Mon, 28 Nov 2011 16:51:11 +0100 Subject: [PATCH 02/47] Add the journal window (J key). It's still not in the right position. --- apps/openmw/mwgui/journal_window.cpp | 52 +++++++++++++++++++ apps/openmw/mwgui/journal_window.hpp | 45 ++++++++++++++++ apps/openmw/mwgui/mode.hpp | 1 + apps/openmw/mwgui/window_manager.cpp | 10 ++++ apps/openmw/mwgui/window_manager.hpp | 2 + apps/openmw/mwinput/inputmanager.cpp | 18 +++++++ .../openmw_journal_layout.xml | 13 +++++ 7 files changed, 141 insertions(+) create mode 100644 apps/openmw/mwgui/journal_window.cpp create mode 100644 apps/openmw/mwgui/journal_window.hpp create mode 100644 extern/mygui_3.0.1/openmw_resources/openmw_journal_layout.xml diff --git a/apps/openmw/mwgui/journal_window.cpp b/apps/openmw/mwgui/journal_window.cpp new file mode 100644 index 000000000..f52b3dc22 --- /dev/null +++ b/apps/openmw/mwgui/journal_window.cpp @@ -0,0 +1,52 @@ +#include "journal_window.hpp" +#include "window_manager.hpp" + + +void formatText() +{ + //std::string +} + + +MWGui::JournalWindow::JournalWindow (WindowManager& parWindowManager) + : WindowBase("openmw_journal_layout.xml", parWindowManager) + , lastPos(0) +{ + setCoord(0,0,498, 342); + + getWidget(mLeftTextWidget, "LeftText"); + getWidget(mRightTextWidget, "RightText"); + //MyGUI::ItemBox* list = new MyGUI::ItemBox(); + //list->addItem("qaq","aqzazaz"); + //mScrollerWidget->addChildItem(list); + //mScrollerWidget->addItem("dserzt",MyGUI::UString("fedgdfg")); + //mEditWidget->addText("ljblsxdvdsfvgedfvdfvdkjfghldfjgn sdv,nhsxl;vvn lklksbvlksb lbsdflkbdSLKJGBLskdhbvlshow(); + //mEditWidget->setEditStatic(true); + mLeftTextWidget->addText("left texxxt "); + mLeftTextWidget->setEditReadOnly(true); + mRightTextWidget->setEditReadOnly(true); + mRightTextWidget->setEditStatic(true); + mLeftTextWidget->setEditStatic(true); + mRightTextWidget->addText("Right texxt "); + + displayLeftText("sdfsdfsdfvf"); + + MyGUI::WindowPtr t = static_cast(mMainWidget); + t->eventWindowChangeCoord = MyGUI::newDelegate(this, &JournalWindow::onWindowResize); +} + +void MWGui::JournalWindow::onWindowResize(MyGUI::Window* window) +{ +} + +void MWGui::JournalWindow::displayLeftText(std::string text) +{ + mLeftTextWidget->removeAllRenderItems(); + mLeftTextWidget->addText(text); +} + +void MWGui::JournalWindow::displayRightText(std::string text) +{ + mRightTextWidget->addText(text); +} \ No newline at end of file diff --git a/apps/openmw/mwgui/journal_window.hpp b/apps/openmw/mwgui/journal_window.hpp new file mode 100644 index 000000000..9b4698398 --- /dev/null +++ b/apps/openmw/mwgui/journal_window.hpp @@ -0,0 +1,45 @@ +#ifndef MWGUI_JOURNAL_H +#define MWGUI_JOURNAL_H + +#include +#include +#include +#include +#include "../mwdialogue/journal.hpp" + +#include "window_base.hpp" + +namespace MWGui +{ + class WindowManager; + + class JournalWindow : public WindowBase + { + public: + JournalWindow(WindowManager& parWindowManager); + + private: + enum ColorStyle + { + CS_Sub, + CS_Normal, + CS_Super + }; + + void onWindowResize(MyGUI::Window* window); + + void displayLeftText(std::string text); + void displayRightText(std::string text); + + static const int lineHeight; + + MyGUI::WidgetPtr skillAreaWidget, skillClientWidget; + MyGUI::VScrollPtr skillScrollerWidget; + int lastPos, clientHeight; + MyGUI::EditPtr mLeftTextWidget; + MyGUI::EditPtr mRightTextWidget; + }; + +} + +#endif \ No newline at end of file diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index b0dc14029..55f0952ce 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -10,6 +10,7 @@ namespace MWGui GM_MainMenu, // Main menu mode GM_Console, // Console mode + GM_Journal, // Journal mode // None of the following are implemented yet diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 84e45859f..ff98df7af 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -14,6 +14,7 @@ #include "../mwinput/inputmanager.hpp" #include "console.hpp" +#include "journal_window.hpp" #include #include @@ -61,6 +62,7 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment inventory = new InventoryWindow (); #endif console = new Console(w,h, environment, extensions); + mJournal = new JournalWindow(*this); mMessageBoxManager = new MessageBoxManager(this); // The HUD is always on @@ -89,6 +91,7 @@ WindowManager::~WindowManager() delete map; delete menu; delete stats; + delete mJournal; #if 0 delete inventory; #endif @@ -156,6 +159,7 @@ void WindowManager::updateVisible() inventory->setVisible(false); #endif console->disable(); + mJournal->setVisible(false); // Mouse is visible whenever we're not in game mode gui->setVisiblePointer(isGuiMode()); @@ -338,6 +342,12 @@ void WindowManager::updateVisible() return; } + if(mode == GM_Journal) + { + mJournal->setVisible(true); + return; + } + // Unsupported mode, switch back to game // Note: The call will eventually end up this method again but diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 293bac601..9db3f8c60 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -51,6 +51,7 @@ namespace MWGui class StatsWindow; class InventoryWindow; class Console; + class JournalWindow; class TextInputDialog; class InfoBoxDialog; @@ -90,6 +91,7 @@ namespace MWGui InventoryWindow *inventory; #endif Console *console; + JournalWindow* mJournal; // Character creation TextInputDialog *nameDialog; diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index eb6c59963..e0c819a71 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -134,6 +134,21 @@ namespace MWInput else setGuiMode(GM_Console); } + void toggleJournal() + { + using namespace MWGui; + + GuiMode mode = windows.getMode(); + + // Toggle between game mode and journal mode + if(mode == GM_Game) + setGuiMode(GM_Journal); + else if(mode == GM_Journal) + setGuiMode(GM_Game); + + // .. but don't touch any other mode. + } + void activate() { mEngine.activate(); @@ -188,6 +203,8 @@ namespace MWInput "Toggle inventory screen"); disp->funcs.bind(A_Console, boost::bind(&InputImpl::toggleConsole, this), "Toggle console"); + disp->funcs.bind(A_Journal, boost::bind(&InputImpl::toggleJournal, this), + "Toggle journal"); disp->funcs.bind(A_Activate, boost::bind(&InputImpl::activate, this), "Activate"); disp->funcs.bind(A_AutoMove, boost::bind(&InputImpl::toggleAutoMove, this), @@ -236,6 +253,7 @@ namespace MWInput disp->bind(A_Screenshot, KC_SYSRQ); disp->bind(A_Inventory, KC_I); disp->bind(A_Console, KC_F1); + disp->bind(A_Journal, KC_J); disp->bind(A_Activate, KC_SPACE); disp->bind(A_AutoMove, KC_Z); disp->bind(A_ToggleSneak, KC_X); diff --git a/extern/mygui_3.0.1/openmw_resources/openmw_journal_layout.xml b/extern/mygui_3.0.1/openmw_resources/openmw_journal_layout.xml new file mode 100644 index 000000000..a9cf42fdd --- /dev/null +++ b/extern/mygui_3.0.1/openmw_resources/openmw_journal_layout.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + From 62946cc79d47f80c81e5083a932d7e1ce23a5f09 Mon Sep 17 00:00:00 2001 From: gugus Date: Mon, 28 Nov 2011 17:00:32 +0100 Subject: [PATCH 03/47] can now clear text. --- apps/openmw/mwgui/journal_window.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/journal_window.cpp b/apps/openmw/mwgui/journal_window.cpp index f52b3dc22..8dee4efc6 100644 --- a/apps/openmw/mwgui/journal_window.cpp +++ b/apps/openmw/mwgui/journal_window.cpp @@ -42,11 +42,12 @@ void MWGui::JournalWindow::onWindowResize(MyGUI::Window* window) void MWGui::JournalWindow::displayLeftText(std::string text) { - mLeftTextWidget->removeAllRenderItems(); + mLeftTextWidget->eraseText(0,mLeftTextWidget->getTextLength()); mLeftTextWidget->addText(text); } void MWGui::JournalWindow::displayRightText(std::string text) { + mRightTextWidget->eraseText(0,mRightTextWidget->getTextLength()); mRightTextWidget->addText(text); } \ No newline at end of file From 4087ab3cdaf14950bdef98b8824758cf272914b9 Mon Sep 17 00:00:00 2001 From: gugus Date: Thu, 1 Dec 2011 13:44:34 +0100 Subject: [PATCH 04/47] correct CMake and add some text formating attempt. --- apps/openmw/CMakeLists.txt | 2 + apps/openmw/mwgui/journal_window.cpp | 53 --------- apps/openmw/mwgui/journalwindow.cpp | 108 ++++++++++++++++++ .../{journal_window.hpp => journalwindow.hpp} | 0 apps/openmw/mwgui/window_manager.cpp | 2 +- 5 files changed, 111 insertions(+), 54 deletions(-) delete mode 100644 apps/openmw/mwgui/journal_window.cpp create mode 100644 apps/openmw/mwgui/journalwindow.cpp rename apps/openmw/mwgui/{journal_window.hpp => journalwindow.hpp} (100%) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 21f3e18a2..906308c4c 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -58,6 +58,7 @@ set(GAMEGUI_HEADER mwgui/window_base.hpp mwgui/stats_window.hpp mwgui/messagebox.hpp + mwgui/journalwindow.hpp ) set(GAMEGUI mwgui/window_manager.cpp @@ -74,6 +75,7 @@ set(GAMEGUI mwgui/window_base.cpp mwgui/stats_window.cpp mwgui/messagebox.cpp + mwgui/journalwindow.cpp ) source_group(apps\\openmw\\mwgui FILES ${GAMEGUI_HEADER} ${GAMEGUI}) diff --git a/apps/openmw/mwgui/journal_window.cpp b/apps/openmw/mwgui/journal_window.cpp deleted file mode 100644 index 8dee4efc6..000000000 --- a/apps/openmw/mwgui/journal_window.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "journal_window.hpp" -#include "window_manager.hpp" - - -void formatText() -{ - //std::string -} - - -MWGui::JournalWindow::JournalWindow (WindowManager& parWindowManager) - : WindowBase("openmw_journal_layout.xml", parWindowManager) - , lastPos(0) -{ - setCoord(0,0,498, 342); - - getWidget(mLeftTextWidget, "LeftText"); - getWidget(mRightTextWidget, "RightText"); - //MyGUI::ItemBox* list = new MyGUI::ItemBox(); - //list->addItem("qaq","aqzazaz"); - //mScrollerWidget->addChildItem(list); - //mScrollerWidget->addItem("dserzt",MyGUI::UString("fedgdfg")); - //mEditWidget->addText("ljblsxdvdsfvgedfvdfvdkjfghldfjgn sdv,nhsxl;vvn lklksbvlksb lbsdflkbdSLKJGBLskdhbvlshow(); - //mEditWidget->setEditStatic(true); - mLeftTextWidget->addText("left texxxt "); - mLeftTextWidget->setEditReadOnly(true); - mRightTextWidget->setEditReadOnly(true); - mRightTextWidget->setEditStatic(true); - mLeftTextWidget->setEditStatic(true); - mRightTextWidget->addText("Right texxt "); - - displayLeftText("sdfsdfsdfvf"); - - MyGUI::WindowPtr t = static_cast(mMainWidget); - t->eventWindowChangeCoord = MyGUI::newDelegate(this, &JournalWindow::onWindowResize); -} - -void MWGui::JournalWindow::onWindowResize(MyGUI::Window* window) -{ -} - -void MWGui::JournalWindow::displayLeftText(std::string text) -{ - mLeftTextWidget->eraseText(0,mLeftTextWidget->getTextLength()); - mLeftTextWidget->addText(text); -} - -void MWGui::JournalWindow::displayRightText(std::string text) -{ - mRightTextWidget->eraseText(0,mRightTextWidget->getTextLength()); - mRightTextWidget->addText(text); -} \ No newline at end of file diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp new file mode 100644 index 000000000..12909aebc --- /dev/null +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -0,0 +1,108 @@ +#include "journalwindow.hpp" +#include "window_manager.hpp" + + +std::list formatText(std::string text) +{ + std::cout << "\n \n \n"; + std::list stringList; + //stringList.push_back(""); + int maxLine = 10; + int lineSize = 20; + + int cLineSize = 0; + int cLine = 0; + std::string cString; + + std::string::iterator wordBegin = text.begin(); + std::string::iterator wordEnd; + + std::string cText = text; + + while(cText.length() != 0) + { + std::cout << "a"; + size_t firstSpace = cText.find_first_of(' '); + if(firstSpace == std::string::npos) + { + cString = cString + cText; + stringList.push_back(cString); + //TODO:finnish this + std::cout << "brerak?"; + break; + } + std::cout << "notbreak"; + if(firstSpace + cLineSize <= lineSize) + { + cLineSize = firstSpace + cLineSize; + cString = cString + cText.substr(0,firstSpace +1); + } + else + { + cLineSize = firstSpace; + if(cLine +1 <= maxLine) + { + cLine = cLine + 1; + cString = cString + std::string("\n") + cText.substr(0,firstSpace +1); + } + else + { + cLine = 0; + stringList.push_back(cString); + cString = cText.substr(0,firstSpace +1); + } + } + //std::cout << cText << "\n"; + std::cout << cText.length(); + if(firstSpace == cText.length()) std::cout << "maxi error en veu"; + cText = cText.substr(firstSpace +1,cText.length() - firstSpace -1); + } + return stringList; + //std::string +} + + +MWGui::JournalWindow::JournalWindow (WindowManager& parWindowManager) + : WindowBase("openmw_journal_layout.xml", parWindowManager) + , lastPos(0) +{ + setCoord(0,0,498, 342); + + getWidget(mLeftTextWidget, "LeftText"); + getWidget(mRightTextWidget, "RightText"); + //MyGUI::ItemBox* list = new MyGUI::ItemBox(); + //list->addItem("qaq","aqzazaz"); + //mScrollerWidget->addChildItem(list); + //mScrollerWidget->addItem("dserzt",MyGUI::UString("fedgdfg")); + //mEditWidget->addText("ljblsxdvdsfvgedfvdfvdkjfghldfjgn sdv,nhsxl;vvn lklksbvlksb lbsdflkbdSLKJGBLskdhbvlshow(); + //mEditWidget->setEditStatic(true); + mLeftTextWidget->addText("left texxxt "); + mLeftTextWidget->setEditReadOnly(true); + mRightTextWidget->setEditReadOnly(true); + mRightTextWidget->setEditStatic(true); + mLeftTextWidget->setEditStatic(true); + mRightTextWidget->addText("Right texxt "); + + std::list list = formatText("OpenMW rgh dsfg sqef srg ZT uzql n ZLIEHRF LQSJH GLOIjf qjfmj hslkdgn jlkdjhg qlr isgli shli uhs fiuh qksf cg ksjnf lkqsnbf ksbf sbfkl zbf kuyzflkj sbgdfkj zlfh ozhjfmo hzmfh lizuf rty qzt ezy tkyEZT RYYJ DG fgh is an open-source implementation of the game engine found in the game Morrowind. This is a dumb test text msodjbg smojg smoig fiiinnn"); + displayLeftText(list.front()); + + MyGUI::WindowPtr t = static_cast(mMainWidget); + t->eventWindowChangeCoord = MyGUI::newDelegate(this, &JournalWindow::onWindowResize); +} + +void MWGui::JournalWindow::onWindowResize(MyGUI::Window* window) +{ +} + +void MWGui::JournalWindow::displayLeftText(std::string text) +{ + mLeftTextWidget->eraseText(0,mLeftTextWidget->getTextLength()); + mLeftTextWidget->addText(text); +} + +void MWGui::JournalWindow::displayRightText(std::string text) +{ + mRightTextWidget->eraseText(0,mRightTextWidget->getTextLength()); + mRightTextWidget->addText(text); +} \ No newline at end of file diff --git a/apps/openmw/mwgui/journal_window.hpp b/apps/openmw/mwgui/journalwindow.hpp similarity index 100% rename from apps/openmw/mwgui/journal_window.hpp rename to apps/openmw/mwgui/journalwindow.hpp diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index ff98df7af..eeac57519 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -14,7 +14,7 @@ #include "../mwinput/inputmanager.hpp" #include "console.hpp" -#include "journal_window.hpp" +#include "journalwindow.hpp" #include #include From 7a3bc885d070d09bb26c7b6e869d5e93b080f210 Mon Sep 17 00:00:00 2001 From: gugus Date: Sun, 11 Dec 2011 11:21:48 +0100 Subject: [PATCH 05/47] Merge branch 'master' of https://github.com/zinnschlag/openmw.git into journal Conflicts: apps/openmw/CMakeLists.txt --- apps/openmw/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 906308c4c..21f3e18a2 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -58,7 +58,6 @@ set(GAMEGUI_HEADER mwgui/window_base.hpp mwgui/stats_window.hpp mwgui/messagebox.hpp - mwgui/journalwindow.hpp ) set(GAMEGUI mwgui/window_manager.cpp @@ -75,7 +74,6 @@ set(GAMEGUI mwgui/window_base.cpp mwgui/stats_window.cpp mwgui/messagebox.cpp - mwgui/journalwindow.cpp ) source_group(apps\\openmw\\mwgui FILES ${GAMEGUI_HEADER} ${GAMEGUI}) From dd14368f76641a9f03e4cf7b32eb7c84d358805b Mon Sep 17 00:00:00 2001 From: gugus Date: Sun, 11 Dec 2011 11:24:25 +0100 Subject: [PATCH 06/47] correct CMake --- apps/openmw/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 90b752264..37ecc3eaa 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -25,7 +25,7 @@ add_openmw_dir (mwinput add_openmw_dir (mwgui layouts text_input widgets race class birth review window_manager console dialogue - dialogue_history window_base stats_window messagebox + dialogue_history window_base stats_window messagebox journalwindow ) add_openmw_dir (mwdialogue From 0178e226056b26560e02f59a6f3a56854d98a15a Mon Sep 17 00:00:00 2001 From: gugus Date: Mon, 26 Dec 2011 18:36:15 +0100 Subject: [PATCH 07/47] correct CMake error --- extern/mygui_3.0.1/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/extern/mygui_3.0.1/CMakeLists.txt b/extern/mygui_3.0.1/CMakeLists.txt index 6e54d1adc..d66298225 100644 --- a/extern/mygui_3.0.1/CMakeLists.txt +++ b/extern/mygui_3.0.1/CMakeLists.txt @@ -66,6 +66,7 @@ configure_file("${SDIR}/openmw_text.skin.xml" "${DDIR}/openmw_text.skin.xml" COP configure_file("${SDIR}/openmw_windows.skin.xml" "${DDIR}/openmw_windows.skin.xml" COPYONLY) configure_file("${SDIR}/openmw_messagebox_layout.xml" "${DDIR}/openmw_messagebox_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_interactive_messagebox_layout.xml" "${DDIR}/openmw_interactive_messagebox_layout.xml" COPYONLY) +configure_file("${SDIR}/openmw_journal_layout.xml" "${DDIR}/openmw_journal_layout.xml" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) configure_file("${SDIR}/transparent.png" "${DDIR}/transparent.png" COPYONLY) configure_file("${SDIR}/VeraMono.ttf" "${DDIR}/VeraMono.ttf" COPYONLY) From 022f0fd5bd5749993c732b1fea3fe9a09cc068e3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 Dec 2011 22:28:53 +0100 Subject: [PATCH 08/47] link order fix for components --- components/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 76e68dd89..75b8aff8c 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -64,3 +64,5 @@ add_component_dir (interpreter include_directories(${BULLET_INCLUDE_DIRS}) add_library (components STATIC ${COMPONENT_FILES}) + +target_link_libraries (components ${Boost_LIBRARIES} ${OGRE_LIBRARIES}) From 33f8049a3660e933756b397b3d715fd77afe5fc4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 29 Dec 2011 17:32:57 +0100 Subject: [PATCH 09/47] accessing topic index didn't work --- apps/openmw/mwdialogue/journalentry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwdialogue/journalentry.cpp b/apps/openmw/mwdialogue/journalentry.cpp index 5e9dfa674..4eb6b8001 100644 --- a/apps/openmw/mwdialogue/journalentry.cpp +++ b/apps/openmw/mwdialogue/journalentry.cpp @@ -42,7 +42,7 @@ namespace MWDialogue iter!=dialogue->mInfo.end(); ++iter) if (iter->data.disposition==index) /// \todo cleanup info structure { - iter->id; + return iter->id; } throw std::runtime_error ("unknown journal index for topic " + topic); From d59284a09611c962a0e510c2cf2c7f8805ae81f7 Mon Sep 17 00:00:00 2001 From: gugus Date: Thu, 29 Dec 2011 17:58:58 +0100 Subject: [PATCH 10/47] first attempt to read the journal --- apps/openmw/mwgui/journalwindow.cpp | 22 ++++++++++++++++++++-- apps/openmw/mwgui/journalwindow.hpp | 2 +- apps/openmw/mwgui/window_manager.cpp | 6 ++++++ apps/openmw/mwgui/window_manager.hpp | 2 ++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 12909aebc..c42e6de88 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -1,5 +1,8 @@ #include "journalwindow.hpp" #include "window_manager.hpp" +#include "../mwdialogue/journal.hpp" +#include "../mwworld/environment.hpp" +#include "../mwworld/world.hpp" std::list formatText(std::string text) @@ -84,13 +87,28 @@ MWGui::JournalWindow::JournalWindow (WindowManager& parWindowManager) mLeftTextWidget->setEditStatic(true); mRightTextWidget->addText("Right texxt "); - std::list list = formatText("OpenMW rgh dsfg sqef srg ZT uzql n ZLIEHRF LQSJH GLOIjf qjfmj hslkdgn jlkdjhg qlr isgli shli uhs fiuh qksf cg ksjnf lkqsnbf ksbf sbfkl zbf kuyzflkj sbgdfkj zlfh ozhjfmo hzmfh lizuf rty qzt ezy tkyEZT RYYJ DG fgh is an open-source implementation of the game engine found in the game Morrowind. This is a dumb test text msodjbg smojg smoig fiiinnn"); - displayLeftText(list.front()); + //std::list list = formatText("OpenMW rgh dsfg sqef srg ZT uzql n ZLIEHRF LQSJH GLOIjf qjfmj hslkdgn jlkdjhg qlr isgli shli uhs fiuh qksf cg ksjnf lkqsnbf ksbf sbfkl zbf kuyzflkj sbgdfkj zlfh ozhjfmo hzmfh lizuf rty qzt ezy tkyEZT RYYJ DG fgh is an open-source implementation of the game engine found in the game Morrowind. This is a dumb test text msodjbg smojg smoig fiiinnn"); + //std::list list = formatText(); + //displayLeftText(list.front()); MyGUI::WindowPtr t = static_cast(mMainWidget); t->eventWindowChangeCoord = MyGUI::newDelegate(this, &JournalWindow::onWindowResize); } +void MWGui::JournalWindow::open() +{ + if(mWindowManager.getEnvironment().mJournal->begin()!=mWindowManager.getEnvironment().mJournal->end()) + { + std::string a = mWindowManager.getEnvironment().mJournal->begin()->getText(mWindowManager.getEnvironment().mWorld->getStore()); + std::cout << a; + } + else + { + std::cout << "empty"; + //std::cout << mWindowManager.getEnvironment().mJournal->begin()->getText(mWindowManager.getEnvironment().mWorld->getStore()); + } +} + void MWGui::JournalWindow::onWindowResize(MyGUI::Window* window) { } diff --git a/apps/openmw/mwgui/journalwindow.hpp b/apps/openmw/mwgui/journalwindow.hpp index 9b4698398..67450d8e9 100644 --- a/apps/openmw/mwgui/journalwindow.hpp +++ b/apps/openmw/mwgui/journalwindow.hpp @@ -5,7 +5,6 @@ #include #include #include -#include "../mwdialogue/journal.hpp" #include "window_base.hpp" @@ -17,6 +16,7 @@ namespace MWGui { public: JournalWindow(WindowManager& parWindowManager); + void open(); private: enum ColorStyle diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index be4632b41..feef07043 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -144,6 +144,11 @@ void WindowManager::update() } } +MWWorld::Environment& WindowManager::getEnvironment() +{ + return environment; +} + void WindowManager::setNextMode(GuiMode newMode) { nextMode = newMode; @@ -351,6 +356,7 @@ void WindowManager::updateVisible() if(mode == GM_Journal) { mJournal->setVisible(true); + mJournal->open(); return; } diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 9db3f8c60..44b7da086 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -174,6 +174,8 @@ namespace MWGui */ void update(); + MWWorld::Environment& getEnvironment(); + void setMode(GuiMode newMode) { if (newMode==GM_Inventory && allowed==GW_None) From 428d0ce820d351653185de7105361fdd8dc4e901 Mon Sep 17 00:00:00 2001 From: gugus Date: Fri, 30 Dec 2011 11:39:17 +0100 Subject: [PATCH 11/47] journal formating. Problems with french accents. --- apps/openmw/mwgui/journalwindow.cpp | 73 ++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index c42e6de88..9b85e0e0c 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -4,19 +4,31 @@ #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" +struct book +{ + int endLine; + std::list pages; +}; -std::list formatText(std::string text) +book formatText(std::string text,book mBook,int maxLine, int lineSize) { - std::cout << "\n \n \n"; - std::list stringList; //stringList.push_back(""); - int maxLine = 10; - int lineSize = 20; int cLineSize = 0; - int cLine = 0; + int cLine = mBook.endLine +1; std::string cString; + if(mBook.pages.empty()) + { + cString = ""; + cLine = 0; + } + else + { + cString = mBook.pages.back() + std::string("\n"); + mBook.pages.pop_back(); + } + std::string::iterator wordBegin = text.begin(); std::string::iterator wordEnd; @@ -24,17 +36,14 @@ std::list formatText(std::string text) while(cText.length() != 0) { - std::cout << "a"; size_t firstSpace = cText.find_first_of(' '); if(firstSpace == std::string::npos) { cString = cString + cText; - stringList.push_back(cString); + mBook.pages.push_back(cString); //TODO:finnish this - std::cout << "brerak?"; break; } - std::cout << "notbreak"; if(firstSpace + cLineSize <= lineSize) { cLineSize = firstSpace + cLineSize; @@ -51,16 +60,16 @@ std::list formatText(std::string text) else { cLine = 0; - stringList.push_back(cString); + mBook.pages.push_back(cString); cString = cText.substr(0,firstSpace +1); } } //std::cout << cText << "\n"; - std::cout << cText.length(); - if(firstSpace == cText.length()) std::cout << "maxi error en veu"; + //std::cout << cText.length(); cText = cText.substr(firstSpace +1,cText.length() - firstSpace -1); } - return stringList; + mBook.endLine = cLine; + return mBook; //std::string } @@ -99,8 +108,40 @@ void MWGui::JournalWindow::open() { if(mWindowManager.getEnvironment().mJournal->begin()!=mWindowManager.getEnvironment().mJournal->end()) { - std::string a = mWindowManager.getEnvironment().mJournal->begin()->getText(mWindowManager.getEnvironment().mWorld->getStore()); - std::cout << a; + std::vector leftPages; + std::vector rightPages; + + book journal; + journal.endLine = 0; + + for(std::deque::const_iterator it = mWindowManager.getEnvironment().mJournal->begin();it!=mWindowManager.getEnvironment().mJournal->end();it++) + { + std::string a = it->getText(mWindowManager.getEnvironment().mWorld->getStore()); + std::cout << a; + journal = formatText(a,journal,10,20); + journal.endLine = journal.endLine +1; + journal.pages.back() = journal.pages.back() + std::string("\n"); + } + //std::string a = mWindowManager.getEnvironment().mJournal->begin()->getText(mWindowManager.getEnvironment().mWorld->getStore()); + //std::list journal = formatText(a,10,20,1); + bool left = true; + for(std::list::iterator it = journal.pages.begin(); it != journal.pages.end();it++) + { + if(left) + { + leftPages.push_back(*it); + } + else + { + rightPages.push_back(*it); + } + left = !left; + } + if(!left) rightPages.push_back(""); + + displayLeftText(leftPages.back()); + displayRightText(rightPages.back()); + } else { From 9031f6296207d2f0146195bbdfcd3bc4973b6211 Mon Sep 17 00:00:00 2001 From: gugus Date: Wed, 11 Jan 2012 12:58:39 +0100 Subject: [PATCH 12/47] The journal is now in the center of the screen. --- apps/openmw/mwgui/journalwindow.cpp | 3 ++- .../openmw_resources/openmw_journal_layout.xml | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 9b85e0e0c..7c09c3220 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -78,7 +78,8 @@ MWGui::JournalWindow::JournalWindow (WindowManager& parWindowManager) : WindowBase("openmw_journal_layout.xml", parWindowManager) , lastPos(0) { - setCoord(0,0,498, 342); + //setCoord(0,0,498, 342); + center(); getWidget(mLeftTextWidget, "LeftText"); getWidget(mRightTextWidget, "RightText"); diff --git a/extern/mygui_3.0.1/openmw_resources/openmw_journal_layout.xml b/extern/mygui_3.0.1/openmw_resources/openmw_journal_layout.xml index a9cf42fdd..1d9a11dd8 100644 --- a/extern/mygui_3.0.1/openmw_resources/openmw_journal_layout.xml +++ b/extern/mygui_3.0.1/openmw_resources/openmw_journal_layout.xml @@ -1,13 +1,18 @@  + + - + - + + + + From 18e4b73a8632bea79613e33eb1a2ad0b18699f64 Mon Sep 17 00:00:00 2001 From: Jacob Essex Date: Mon, 16 Jan 2012 15:33:21 +0000 Subject: [PATCH 13/47] Added a more detailed fps counter displaying the triangle and batch count --- apps/openmw/engine.cpp | 20 ++++++++--- apps/openmw/engine.hpp | 4 +-- apps/openmw/main.cpp | 6 ++-- apps/openmw/mwgui/layouts.cpp | 35 ++++++++++++++++--- apps/openmw/mwgui/layouts.hpp | 6 +++- apps/openmw/mwgui/window_manager.cpp | 10 +++--- apps/openmw/mwgui/window_manager.hpp | 12 +++++-- .../openmw_resources/openmw_hud_layout.xml | 11 ++++-- 8 files changed, 81 insertions(+), 23 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 7fa98f8e2..b8a71d2e7 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -7,6 +7,7 @@ #include #include +#include #include @@ -112,8 +113,17 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) } // update GUI - if(mShowFPS) + if(mFpsLevel == 1) + { mEnvironment.mWindowManager->wmSetFPS(mOgre->getFPS()); + } + else if(mFpsLevel == 2) //detailed + { + Ogre::RenderWindow* window = mOgre->getWindow(); + mEnvironment.mWindowManager->wmSetDetailedFPS(window->getLastFPS(), + window->getTriangleCount(), + window->getBatchCount()); + } mEnvironment.mWindowManager->onFrame(mEnvironment.mFrameDuration); @@ -157,7 +167,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) OMW::Engine::Engine(Cfg::ConfigurationManager& configurationManager) : mOgre (0) , mPhysicEngine (0) - , mShowFPS (false) + , mFpsLevel(0) , mDebug (false) , mVerboseScripts (false) , mNewGame (false) @@ -331,7 +341,7 @@ void OMW::Engine::go() MWScript::registerExtensions (mExtensions); mEnvironment.mWindowManager = new MWGui::WindowManager(mGuiManager->getGui(), mEnvironment, - mExtensions, mShowFPS, mNewGame); + mExtensions, mFpsLevel, mNewGame); // Create sound system mEnvironment.mSoundManager = new MWSound::SoundManager(mOgre->getRoot(), @@ -451,9 +461,9 @@ void OMW::Engine::setSoundUsage(bool soundUsage) mUseSound = soundUsage; } -void OMW::Engine::showFPS(bool showFps) +void OMW::Engine::showFPS(int level) { - mShowFPS = showFps; + mFpsLevel = level; } void OMW::Engine::setEncoding(const std::string& encoding) diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 443f790a4..259c44d11 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -66,7 +66,7 @@ namespace OMW OEngine::Physic::PhysicEngine* mPhysicEngine; std::string mCellName; std::string mMaster; - bool mShowFPS; + int mFpsLevel; bool mDebug; bool mVerboseScripts; bool mNewGame; @@ -128,7 +128,7 @@ namespace OMW void addMaster(const std::string& master); /// Enable fps counter - void showFPS(bool showFps); + void showFPS(int level); /// Enable debug mode: /// - non-exclusive input diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 933d1c48a..acb852020 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -75,8 +75,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Cfg::Configuratio ("plugin", bpo::value()->default_value(StringsVector(), "") ->multitoken(), "plugin file(s)") - ("fps", boost::program_options::value()->implicit_value(true) - ->default_value(false), "show fps counter") + ("fps", boost::program_options::value()->implicit_value(1) + ->default_value(0), "fps counter detail (0 = off, 1 = fps counter, 2 = full detail)") ("debug", boost::program_options::value()->implicit_value(true) ->default_value(false), "debug mode") @@ -200,7 +200,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Cfg::Configuratio engine.setNewGame(variables["new-game"].as()); // other settings - engine.showFPS(variables["fps"].as()); + engine.showFPS(variables["fps"].as()); engine.setDebugMode(variables["debug"].as()); engine.setSoundUsage(!variables["nosound"].as()); engine.setScriptsVerbosity(variables["script-verbose"].as()); diff --git a/apps/openmw/mwgui/layouts.cpp b/apps/openmw/mwgui/layouts.cpp index 10740e224..ea9a85113 100644 --- a/apps/openmw/mwgui/layouts.cpp +++ b/apps/openmw/mwgui/layouts.cpp @@ -13,7 +13,7 @@ using namespace MWGui; -HUD::HUD(int width, int height, bool fpsSwitch) +HUD::HUD(int width, int height, int fpsLevel) : Layout("openmw_hud_layout.xml") { setCoord(0,0, width, height); @@ -37,10 +37,28 @@ HUD::HUD(int width, int height, bool fpsSwitch) getWidget(crosshair, "Crosshair"); - getWidget(fpsbox, "FPSBox"); - getWidget(fpscounter, "FPSCounter"); - fpsbox->setVisible(fpsSwitch); + MyGUI::WidgetPtr fpsBoxAdvanced; + MyGUI::WidgetPtr fpsBoxDefault; + + getWidget(fpsBoxDefault, "FPSBox"); + getWidget(fpsBoxAdvanced, "FPSBoxAdv"); + if ( fpsLevel == 2 ){ + fpsBoxDefault->setVisible(false); + fpsbox = fpsBoxAdvanced; + getWidget(fpscounter, "FPSCounterAdv"); + }else if ( fpsLevel == 1 ){ + fpsBoxAdvanced->setVisible(false); + fpsbox = fpsBoxDefault; + getWidget(fpscounter, "FPSCounter"); + }else{ + fpsBoxDefault->setVisible(false); + fpsBoxAdvanced->setVisible(false); + + getWidget(fpscounter, "FPSCounter"); + } + getWidget(trianglecounter, "TriangleCounter"); + getWidget(batchcounter, "BatchCounter"); compass->setImageTexture("textures\\compass.dds"); crosshair->setImageTexture("textures\\target.dds"); @@ -59,6 +77,15 @@ void HUD::setFPS(float fps) fpscounter->setCaption(boost::lexical_cast((int)fps)); } +void HUD::setTriangleCount(size_t count) +{ + trianglecounter->setCaption(boost::lexical_cast(count)); +} + +void HUD::setBatchCount(size_t count) +{ + batchcounter->setCaption(boost::lexical_cast(count)); +} void HUD::setStats(int h, int hmax, int m, int mmax, int s, int smax) { diff --git a/apps/openmw/mwgui/layouts.hpp b/apps/openmw/mwgui/layouts.hpp index ab91f4217..9917dcdcc 100644 --- a/apps/openmw/mwgui/layouts.hpp +++ b/apps/openmw/mwgui/layouts.hpp @@ -32,7 +32,7 @@ namespace MWGui class HUD : public OEngine::GUI::Layout { public: - HUD(int width, int height, bool fpsSwitch); + HUD(int width, int height, int fpsLevel); void setStats(int h, int hmax, int m, int mmax, int s, int smax); void setWeapIcon(const char *str); void setSpellIcon(const char *str); @@ -41,6 +41,8 @@ namespace MWGui void setEffect(const char *img); void setValue (const std::string& id, const MWMechanics::DynamicStat& value); void setFPS(float fps); + void setTriangleCount(size_t count); + void setBatchCount(size_t count); MyGUI::ProgressPtr health, magicka, stamina; MyGUI::StaticImagePtr weapImage, spellImage; @@ -53,6 +55,8 @@ namespace MWGui MyGUI::WidgetPtr fpsbox; MyGUI::StaticTextPtr fpscounter; + MyGUI::StaticTextPtr trianglecounter; + MyGUI::StaticTextPtr batchcounter; }; class MapWindow : public OEngine::GUI::Layout diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 095d347e7..0a17daf80 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -22,7 +22,7 @@ using namespace MWGui; WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment, - const Compiler::Extensions& extensions, bool fpsSwitch, bool newGame) + const Compiler::Extensions& extensions, int fpsLevel, bool newGame) : environment(environment) , nameDialog(nullptr) , raceDialog(nullptr) @@ -41,7 +41,7 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment , shown(GW_ALL) , allowed(newGame ? GW_None : GW_ALL) { - showFPSCounter = fpsSwitch; + showFPSLevel = fpsLevel; creationStage = NotStarted; @@ -53,7 +53,7 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment int w = gui->getViewSize().width; int h = gui->getViewSize().height; - hud = new HUD(w,h, showFPSCounter); + hud = new HUD(w,h, showFPSLevel); menu = new MainMenu(w,h); map = new MapWindow(); stats = new StatsWindow(*this); @@ -135,9 +135,11 @@ void WindowManager::update() environment.mInputManager->setGuiMode(nextMode); nextMode = GM_Game; } - if (showFPSCounter) + if (showFPSLevel > 0) { hud->setFPS(mFPS); + hud->setTriangleCount(mTriangleCount); + hud->setBatchCount(mBatchCount); } } diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 293bac601..0178943eb 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -156,13 +156,15 @@ namespace MWGui void setGuiMode(GuiMode newMode); - bool showFPSCounter; + int showFPSLevel; float mFPS; + size_t mTriangleCount; + size_t mBatchCount; public: /// The constructor needs the main Gui object WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment, - const Compiler::Extensions& extensions, bool fpsSwitch, bool newGame); + const Compiler::Extensions& extensions, int fpsLevel, bool newGame); virtual ~WindowManager(); /** @@ -204,6 +206,12 @@ namespace MWGui MyGUI::Gui* getGui() const { return gui; } void wmSetFPS(float fps) { mFPS = fps; } + void wmSetDetailedFPS(float fps, size_t triangleCount, size_t batchCount) + { + mFPS = fps; + mTriangleCount = triangleCount; + mBatchCount = batchCount; + } void setValue (const std::string& id, const MWMechanics::Stat& value); ///< Set value for the given ID. diff --git a/extern/mygui_3.0.1/openmw_resources/openmw_hud_layout.xml b/extern/mygui_3.0.1/openmw_resources/openmw_hud_layout.xml index 8dc3cebab..32eb31027 100644 --- a/extern/mygui_3.0.1/openmw_resources/openmw_hud_layout.xml +++ b/extern/mygui_3.0.1/openmw_resources/openmw_hud_layout.xml @@ -49,12 +49,19 @@ - - + + + + + + + + From eb4dea3d87965acf4e9e2ec4d81851d5614229f9 Mon Sep 17 00:00:00 2001 From: gugus Date: Mon, 16 Jan 2012 17:46:25 +0100 Subject: [PATCH 14/47] Previous/Next button implemented --- apps/openmw/mwgui/journalwindow.cpp | 38 ++++++++++++++++--- apps/openmw/mwgui/journalwindow.hpp | 12 ++++++ .../openmw_journal_layout.xml | 11 ++++-- .../openmw_resources/openmw_journal_skin.xml | 29 ++++++++++++++ 4 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 extern/mygui_3.0.1/openmw_resources/openmw_journal_skin.xml diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 7c09c3220..7d83539e0 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -83,6 +83,10 @@ MWGui::JournalWindow::JournalWindow (WindowManager& parWindowManager) getWidget(mLeftTextWidget, "LeftText"); getWidget(mRightTextWidget, "RightText"); + getWidget(mPrevBtn, "PrevPageBTN"); + mPrevBtn->eventMouseButtonClick = MyGUI::newDelegate(this,&MWGui::JournalWindow::notifyPrevPage); + getWidget(mNextBtn, "NextPageBTN"); + mNextBtn->eventMouseButtonClick = MyGUI::newDelegate(this,&MWGui::JournalWindow::notifyNextPage); //MyGUI::ItemBox* list = new MyGUI::ItemBox(); //list->addItem("qaq","aqzazaz"); //mScrollerWidget->addChildItem(list); @@ -107,11 +111,9 @@ MWGui::JournalWindow::JournalWindow (WindowManager& parWindowManager) void MWGui::JournalWindow::open() { + mPageNumber = 0; if(mWindowManager.getEnvironment().mJournal->begin()!=mWindowManager.getEnvironment().mJournal->end()) { - std::vector leftPages; - std::vector rightPages; - book journal; journal.endLine = 0; @@ -119,7 +121,7 @@ void MWGui::JournalWindow::open() { std::string a = it->getText(mWindowManager.getEnvironment().mWorld->getStore()); std::cout << a; - journal = formatText(a,journal,10,20); + journal = formatText(a,journal,10,17); journal.endLine = journal.endLine +1; journal.pages.back() = journal.pages.back() + std::string("\n"); } @@ -140,8 +142,9 @@ void MWGui::JournalWindow::open() } if(!left) rightPages.push_back(""); - displayLeftText(leftPages.back()); - displayRightText(rightPages.back()); + mPageNumber = leftPages.size()-1; + displayLeftText(leftPages[mPageNumber]); + displayRightText(rightPages[mPageNumber]); } else @@ -165,4 +168,27 @@ void MWGui::JournalWindow::displayRightText(std::string text) { mRightTextWidget->eraseText(0,mRightTextWidget->getTextLength()); mRightTextWidget->addText(text); +} + + +void MWGui::JournalWindow::notifyNextPage(MyGUI::WidgetPtr _sender) +{ + std::cout << mPageNumber; + if(mPageNumber < int(leftPages.size())-1) + { + mPageNumber = mPageNumber + 1; + displayLeftText(leftPages[mPageNumber]); + displayRightText(rightPages[mPageNumber]); + } +} + +void MWGui::JournalWindow::notifyPrevPage(MyGUI::WidgetPtr _sender) +{ + std::cout << mPageNumber; + if(mPageNumber > 0) + { + mPageNumber = mPageNumber - 1; + displayLeftText(leftPages[mPageNumber]); + displayRightText(rightPages[mPageNumber]); + } } \ No newline at end of file diff --git a/apps/openmw/mwgui/journalwindow.hpp b/apps/openmw/mwgui/journalwindow.hpp index 67450d8e9..e66448763 100644 --- a/apps/openmw/mwgui/journalwindow.hpp +++ b/apps/openmw/mwgui/journalwindow.hpp @@ -31,6 +31,13 @@ namespace MWGui void displayLeftText(std::string text); void displayRightText(std::string text); + + /** + *Called when next/prev button is used. + */ + void notifyNextPage(MyGUI::WidgetPtr _sender); + void notifyPrevPage(MyGUI::WidgetPtr _sender); + static const int lineHeight; MyGUI::WidgetPtr skillAreaWidget, skillClientWidget; @@ -38,6 +45,11 @@ namespace MWGui int lastPos, clientHeight; MyGUI::EditPtr mLeftTextWidget; MyGUI::EditPtr mRightTextWidget; + MyGUI::ButtonPtr mPrevBtn; + MyGUI::ButtonPtr mNextBtn; + std::vector leftPages; + std::vector rightPages; + int mPageNumber; //store the number of the current left page }; } diff --git a/extern/mygui_3.0.1/openmw_resources/openmw_journal_layout.xml b/extern/mygui_3.0.1/openmw_resources/openmw_journal_layout.xml index 1d9a11dd8..dc2116ee0 100644 --- a/extern/mygui_3.0.1/openmw_resources/openmw_journal_layout.xml +++ b/extern/mygui_3.0.1/openmw_resources/openmw_journal_layout.xml @@ -1,6 +1,5 @@  - @@ -9,8 +8,14 @@ - - + + + + + + + + diff --git a/extern/mygui_3.0.1/openmw_resources/openmw_journal_skin.xml b/extern/mygui_3.0.1/openmw_resources/openmw_journal_skin.xml new file mode 100644 index 000000000..b6cb1bca7 --- /dev/null +++ b/extern/mygui_3.0.1/openmw_resources/openmw_journal_skin.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ba2fc27c2d58db520b092c89002be85ab10d94ea Mon Sep 17 00:00:00 2001 From: gugus Date: Mon, 16 Jan 2012 18:10:16 +0100 Subject: [PATCH 15/47] oups forgot Cmake stuff --- extern/mygui_3.0.1/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/extern/mygui_3.0.1/CMakeLists.txt b/extern/mygui_3.0.1/CMakeLists.txt index d66298225..2cbe8aabe 100644 --- a/extern/mygui_3.0.1/CMakeLists.txt +++ b/extern/mygui_3.0.1/CMakeLists.txt @@ -67,6 +67,7 @@ configure_file("${SDIR}/openmw_windows.skin.xml" "${DDIR}/openmw_windows.skin.xm configure_file("${SDIR}/openmw_messagebox_layout.xml" "${DDIR}/openmw_messagebox_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_interactive_messagebox_layout.xml" "${DDIR}/openmw_interactive_messagebox_layout.xml" COPYONLY) configure_file("${SDIR}/openmw_journal_layout.xml" "${DDIR}/openmw_journal_layout.xml" COPYONLY) +configure_file("${SDIR}/openmw_journal_skin.xml" "${DDIR}/openmw_journal_skin.xml" COPYONLY) configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY) configure_file("${SDIR}/transparent.png" "${DDIR}/transparent.png" COPYONLY) configure_file("${SDIR}/VeraMono.ttf" "${DDIR}/VeraMono.ttf" COPYONLY) From 3b15170d09f40f67043d908464f657610dcb4ecb Mon Sep 17 00:00:00 2001 From: Jacob Essex Date: Mon, 16 Jan 2012 18:16:33 +0000 Subject: [PATCH 16/47] Cleaned up and simplified the code relating to the fps display --- apps/openmw/engine.cpp | 15 ++++----------- apps/openmw/mwgui/window_manager.hpp | 3 +-- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index b8a71d2e7..f4a1c407e 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -113,17 +113,10 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) } // update GUI - if(mFpsLevel == 1) - { - mEnvironment.mWindowManager->wmSetFPS(mOgre->getFPS()); - } - else if(mFpsLevel == 2) //detailed - { - Ogre::RenderWindow* window = mOgre->getWindow(); - mEnvironment.mWindowManager->wmSetDetailedFPS(window->getLastFPS(), - window->getTriangleCount(), - window->getBatchCount()); - } + Ogre::RenderWindow* window = mOgre->getWindow(); + mEnvironment.mWindowManager->wmUpdateFps(window->getLastFPS(), + window->getTriangleCount(), + window->getBatchCount()); mEnvironment.mWindowManager->onFrame(mEnvironment.mFrameDuration); diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index 0178943eb..a46aa3533 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -205,8 +205,7 @@ namespace MWGui MyGUI::Gui* getGui() const { return gui; } - void wmSetFPS(float fps) { mFPS = fps; } - void wmSetDetailedFPS(float fps, size_t triangleCount, size_t batchCount) + void wmUpdateFps(float fps, size_t triangleCount, size_t batchCount) { mFPS = fps; mTriangleCount = triangleCount; From edbf4f7bdca6b92a1ed77aecdc1868ab26e7aecf Mon Sep 17 00:00:00 2001 From: gugus Date: Mon, 16 Jan 2012 19:35:35 +0100 Subject: [PATCH 17/47] forgot to update core.xml --- extern/mygui_3.0.1/openmw_resources/core.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/extern/mygui_3.0.1/openmw_resources/core.xml b/extern/mygui_3.0.1/openmw_resources/core.xml index 3d4d5ba3b..31d409a35 100644 --- a/extern/mygui_3.0.1/openmw_resources/core.xml +++ b/extern/mygui_3.0.1/openmw_resources/core.xml @@ -19,6 +19,7 @@ + From 484b8a95f088c5567a29479991d2f2fb5fe57704 Mon Sep 17 00:00:00 2001 From: gugus Date: Mon, 16 Jan 2012 21:58:18 +0100 Subject: [PATCH 18/47] removed useless std::cout --- apps/openmw/mwgui/journalwindow.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 7d83539e0..89ec6998e 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -120,7 +120,6 @@ void MWGui::JournalWindow::open() for(std::deque::const_iterator it = mWindowManager.getEnvironment().mJournal->begin();it!=mWindowManager.getEnvironment().mJournal->end();it++) { std::string a = it->getText(mWindowManager.getEnvironment().mWorld->getStore()); - std::cout << a; journal = formatText(a,journal,10,17); journal.endLine = journal.endLine +1; journal.pages.back() = journal.pages.back() + std::string("\n"); @@ -149,7 +148,6 @@ void MWGui::JournalWindow::open() } else { - std::cout << "empty"; //std::cout << mWindowManager.getEnvironment().mJournal->begin()->getText(mWindowManager.getEnvironment().mWorld->getStore()); } } @@ -173,7 +171,6 @@ void MWGui::JournalWindow::displayRightText(std::string text) void MWGui::JournalWindow::notifyNextPage(MyGUI::WidgetPtr _sender) { - std::cout << mPageNumber; if(mPageNumber < int(leftPages.size())-1) { mPageNumber = mPageNumber + 1; @@ -184,7 +181,6 @@ void MWGui::JournalWindow::notifyNextPage(MyGUI::WidgetPtr _sender) void MWGui::JournalWindow::notifyPrevPage(MyGUI::WidgetPtr _sender) { - std::cout << mPageNumber; if(mPageNumber > 0) { mPageNumber = mPageNumber - 1; From e73640e720dcbab59153a97155d986bb107086a1 Mon Sep 17 00:00:00 2001 From: Jacob Essex Date: Tue, 17 Jan 2012 11:58:06 +0000 Subject: [PATCH 19/47] Improved code, added labels to the counter --- apps/openmw/mwgui/layouts.cpp | 17 ++++---------- .../openmw_resources/openmw_hud_layout.xml | 22 +++++++++++++++---- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwgui/layouts.cpp b/apps/openmw/mwgui/layouts.cpp index ea9a85113..ebabc6faf 100644 --- a/apps/openmw/mwgui/layouts.cpp +++ b/apps/openmw/mwgui/layouts.cpp @@ -37,24 +37,15 @@ HUD::HUD(int width, int height, int fpsLevel) getWidget(crosshair, "Crosshair"); - - MyGUI::WidgetPtr fpsBoxAdvanced; - MyGUI::WidgetPtr fpsBoxDefault; - - getWidget(fpsBoxDefault, "FPSBox"); - getWidget(fpsBoxAdvanced, "FPSBoxAdv"); if ( fpsLevel == 2 ){ - fpsBoxDefault->setVisible(false); - fpsbox = fpsBoxAdvanced; + getWidget(fpsbox, "FPSBoxAdv"); + fpsbox->setVisible(true); getWidget(fpscounter, "FPSCounterAdv"); }else if ( fpsLevel == 1 ){ - fpsBoxAdvanced->setVisible(false); - fpsbox = fpsBoxDefault; + getWidget(fpsbox, "FPSBox"); + fpsbox->setVisible(true); getWidget(fpscounter, "FPSCounter"); }else{ - fpsBoxDefault->setVisible(false); - fpsBoxAdvanced->setVisible(false); - getWidget(fpscounter, "FPSCounter"); } getWidget(trianglecounter, "TriangleCounter"); diff --git a/extern/mygui_3.0.1/openmw_resources/openmw_hud_layout.xml b/extern/mygui_3.0.1/openmw_resources/openmw_hud_layout.xml index 32eb31027..9e5f26c5b 100644 --- a/extern/mygui_3.0.1/openmw_resources/openmw_hud_layout.xml +++ b/extern/mygui_3.0.1/openmw_resources/openmw_hud_layout.xml @@ -52,15 +52,29 @@ + - - - - + + + + + + + + + + + + + + + + From f5a82931b6d22a650ba885609d5861101b0fd6e0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 17 Jan 2012 13:53:27 +0100 Subject: [PATCH 20/47] some cleanup --- apps/openmw/mwgui/journalwindow.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 89ec6998e..457a07582 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -4,11 +4,14 @@ #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" -struct book +namespace { - int endLine; - std::list pages; -}; + struct book + { + int endLine; + std::list pages; + }; +} book formatText(std::string text,book mBook,int maxLine, int lineSize) { @@ -44,7 +47,7 @@ book formatText(std::string text,book mBook,int maxLine, int lineSize) //TODO:finnish this break; } - if(firstSpace + cLineSize <= lineSize) + if(static_cast (firstSpace) + cLineSize <= lineSize) { cLineSize = firstSpace + cLineSize; cString = cString + cText.substr(0,firstSpace +1); @@ -70,7 +73,7 @@ book formatText(std::string text,book mBook,int maxLine, int lineSize) } mBook.endLine = cLine; return mBook; - //std::string + //std::string } @@ -187,4 +190,4 @@ void MWGui::JournalWindow::notifyPrevPage(MyGUI::WidgetPtr _sender) displayLeftText(leftPages[mPageNumber]); displayRightText(rightPages[mPageNumber]); } -} \ No newline at end of file +} From 9b910dda94f8d86111e4b216e7715be769bf05c8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 17 Jan 2012 15:10:53 +0100 Subject: [PATCH 21/47] clean up --- apps/openmw/mwclass/npc.cpp | 5 +- apps/openmw/mwrender/animation.cpp | 136 +++++++------ apps/openmw/mwrender/creatureanimation.cpp | 10 +- apps/openmw/mwrender/npcanimation.cpp | 90 ++++----- apps/openmw/mwrender/renderingmanager.cpp | 2 +- components/nif/node.hpp | 8 +- components/nifogre/ogre_nif_loader.cpp | 220 ++++++++++----------- components/nifogre/ogre_nif_loader.hpp | 22 +-- 8 files changed, 243 insertions(+), 250 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index acb0a5a35..2b98a3d60 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -38,18 +38,17 @@ namespace MWClass void Npc::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const { - + ESMS::LiveCellRef *ref = ptr.get(); - const std::string &model = ref->base->model; assert (ref->base != NULL); std::string headID = ref->base->head; std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; - + std::string smodel = "meshes\\base_anim.nif"; if(beast) smodel = "meshes\\base_animkna.nif"; diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 3bd160e6d..5a9731d2d 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -18,7 +18,7 @@ namespace MWRender{ mUniqueIDs[copy] = mUniqueIDs[copy] + 1; counter = mUniqueIDs[copy]; } - + std::stringstream out; if(counter > 99 && counter < 1000) out << "0"; @@ -38,7 +38,7 @@ namespace MWRender{ time = startTime; } else if(textmappings){ - + std::string startName = groupname + ": loop start"; std::string stopName = groupname + ": loop stop"; @@ -49,7 +49,7 @@ namespace MWRender{ stopName = groupname + ": loop stop"; for(std::map::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++){ - + std::string current = iter->first.substr(0, startName.size()); std::transform(current.begin(), current.end(), current.begin(), ::tolower); std::string current2 = iter->first.substr(0, stopName.size()); @@ -71,9 +71,9 @@ namespace MWRender{ if(!first){ startName = groupname + ": start"; stopName = groupname + ": stop"; - + for(std::map::iterator iter = textmappings->begin(); iter != textmappings->end(); iter++){ - + std::string current = iter->first.substr(0, startName.size()); std::transform(current.begin(), current.end(), current.begin(), ::tolower); std::string current2 = iter->first.substr(0, stopName.size()); @@ -92,9 +92,9 @@ namespace MWRender{ } } } - + } - + } void Animation::stopScript(){ animate = 0; @@ -103,24 +103,21 @@ namespace MWRender{ void Animation::handleShapes(std::vector* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){ bool useHandles = skel == creaturemodel->getSkeleton(); shapeNumber = 0; - + std::vector::iterator allshapesiter; for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++) - + { //std::map vecPosRot; - + Nif::NiTriShapeCopy& copy = *allshapesiter; std::vector* allvertices = ©.vertices; - std::vector* allnormals = ©.normals; - - //std::set vertices; //std::set normals; //std::vector boneinfovector = copy.boneinfo; - std::map>* verticesToChange = ©.vertsToWeights; - + std::map >* verticesToChange = ©.vertsToWeights; + //std::cout << "Name " << copy.sname << "\n"; Ogre::HardwareVertexBufferSharedPtr vbuf = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(0); Ogre::Real* pReal = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); @@ -135,7 +132,7 @@ namespace MWRender{ if(copy.vertices.size() == initialVertices.size()) { //Create if it doesn't already exist - if(shapeIndexI.size() == shapeNumber) + if(shapeIndexI.size() == static_cast (shapeNumber)) { std::vector vec; shapeIndexI.push_back(vec); @@ -165,10 +162,10 @@ namespace MWRender{ } - + } - + allvertices = &initialVertices; } shapeNumber++; @@ -177,8 +174,8 @@ namespace MWRender{ if(verticesToChange->size() > 0){ - - for(std::map>::iterator iter = verticesToChange->begin(); + + for(std::map >::iterator iter = verticesToChange->begin(); iter != verticesToChange->end(); iter++) { std::vector inds = iter->second; @@ -192,15 +189,15 @@ namespace MWRender{ } else bonePtr = skel->getBone(boneinfocopy->bonename); - + Ogre::Vector3 vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; Ogre::Quaternion vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; - - + + /*if(vecPosRot.find(boneinfocopy->bonehandle) == vecPosRot.end()){ vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; - + if(useHandles){ PosAndRot both; both.vecPos = vecPos; @@ -215,9 +212,9 @@ namespace MWRender{ }*/ Ogre::Vector3 absVertPos = (vecPos + vecRot * currentVertex) * inds[0].weight; - - for(int i = 1; i < inds.size(); i++){ + + for(std::size_t i = 1; i < inds.size(); i++){ boneinfocopy = &(allshapesiter->boneinfo[inds[i].boneinfocopyindex]); if(useHandles) bonePtr = skel->getBone(boneinfocopy->bonehandle); @@ -229,7 +226,7 @@ namespace MWRender{ /*if(vecPosRot.find(boneinfocopy->bonehandle) == vecPosRot.end()){ vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; - + if(useHandles){ PosAndRot both; both.vecPos = vecPos; @@ -243,24 +240,25 @@ namespace MWRender{ vecRot = both.vecRot; }*/ - + absVertPos += (vecPos + vecRot * currentVertex) * inds[i].weight; - + } Ogre::Real* addr = (pReal + 3 * verIndex); *addr = absVertPos.x; *(addr+1) = absVertPos.y; *(addr+2) = absVertPos.z; } - - /*for (unsigned int i = 0; i < boneinfovector.size(); i++) + +#if 0 + for (unsigned int i = 0; i < boneinfovector.size(); i++) { Nif::NiSkinData::BoneInfoCopy boneinfo = boneinfovector[i]; if(skel->hasBone(boneinfo.bonename)){ Ogre::Bone *bonePtr = skel->getBone(boneinfo.bonename); Ogre::Vector3 vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfo.trafo.trans; Ogre::Quaternion vecRot = bonePtr->_getDerivedOrientation() * boneinfo.trafo.rotation; - + for (unsigned int j=0; j < boneinfo.weights.size(); j++) { unsigned int verIndex = boneinfo.weights[j].vertex; @@ -273,12 +271,12 @@ namespace MWRender{ *addr = absVertPos.x; *(addr+1) = absVertPos.y; *(addr+2) = absVertPos.z; - + } - else + else { - + Ogre::Vector3 absVertPos = vecPos + vecRot * allvertices[verIndex]; absVertPos = absVertPos * boneinfo.weights[j].weight; Ogre::Vector3 old = Ogre::Vector3(pReal + 3 * verIndex); @@ -287,12 +285,12 @@ namespace MWRender{ *addr = absVertPos.x; *(addr+1) = absVertPos.y; *(addr+2) = absVertPos.z; - + //std::cout << "Vertex" << verIndex << "Weight: " << boneinfo.weights[i].weight << "was seen twice\n"; } - - /*if(normals.find(verIndex) == normals.end()) + + if(normals.find(verIndex) == normals.end()) { Ogre::Vector3 absNormalsPos = vecRot * allnormals[verIndex]; absNormalsPos = absNormalsPos * boneinfo.weights[j].weight; @@ -314,16 +312,16 @@ namespace MWRender{ *(addr+1) = absNormalsPos.y; *(addr+2) = absNormalsPos.z; - }*/ - + } +#endif //} //} - - + + //} //Comment out - + ; - } + } else { //Ogre::Bone *bonePtr = creaturemodel->getSkeleton()->getBone(copy.bonename); @@ -337,9 +335,9 @@ namespace MWRender{ float scale; if(skel->hasBone(*boneSequenceIter)){ Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter); - - - + + + transmult = bonePtr->getPosition(); rotmult = bonePtr->getOrientation(); @@ -368,13 +366,13 @@ namespace MWRender{ rotmult = shaperot; scale = shapescale; } - - - + + + // Computes C = B + AxC*scale // final_vector = old_vector + old_rotation*new_vector*old_scale/ - + for(unsigned int i = 0; i < allvertices->size(); i++){ Ogre::Vector3 current = transmult + rotmult * (*allvertices)[i]; Ogre::Real* addr = pReal + i * 3; @@ -414,10 +412,10 @@ namespace MWRender{ x = 0.0; return true; } - + if ( i < 0 || i >= count ) i = 0; - + float tI = times[i]; if ( time > tI ) { @@ -457,11 +455,11 @@ namespace MWRender{ void Animation::handleAnimationTransforms(){ Ogre::SkeletonInstance* skel = base->getSkeleton(); - + Ogre::Bone* b = skel->getRootBone(); b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3)); //This is a trick - + skel->_updateTransforms(); //skel->_notifyManualBonesDirty(); @@ -474,7 +472,7 @@ namespace MWRender{ Ogre::Bone* b = skel->getRootBone(); b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3));//This is a trick - + skel->_updateTransforms(); // skel->_notifyManualBonesDirty(); @@ -492,17 +490,17 @@ namespace MWRender{ slot++; //iter++; continue; - + } float x; float x2; - + std::vector quats = iter->getQuat(); std::vector ttime = iter->gettTime(); std::vector::iterator ttimeiter = ttime.begin(); - + std::vector rtime = iter->getrTime(); int rindexJ = 0; timeIndex(time, rtime, rindexI[slot], rindexJ, x2); @@ -516,15 +514,15 @@ namespace MWRender{ //std::cout << "X: " << x << " X2: " << x2 << "\n"; Ogre::Vector3 t; Ogre::Quaternion r; - + bool bTrans = translist1.size() > 0; if(bTrans){ Ogre::Vector3 v1 = translist1[tindexI[slot]]; Ogre::Vector3 v2 = translist1[tindexJ]; t = (v1 + (v2 - v1) * x); - + } - + bool bQuats = quats.size() > 0; if(bQuats){ r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true); @@ -538,15 +536,15 @@ namespace MWRender{ if(bQuats) bone->setOrientation(r); - - + + skel->_updateTransforms(); //skel->_notifyManualBonesDirty(); base->getAllAnimationStates()->_notifyDirty(); //base->_updateAnimation(); base->_notifyMoved(); - } - for(int i = 0; i < entityparts.size(); i++){ + } + for(std::size_t i = 0; i < entityparts.size(); i++){ skel = entityparts[i]->getSkeleton(); if(skel->hasBone(iter->getBonename())){ Ogre::Bone* bone = skel->getBone(iter->getBonename()); @@ -554,17 +552,17 @@ namespace MWRender{ bone->setPosition(t); if(bQuats) bone->setOrientation(r); - + skel->_updateTransforms(); //skel->_notifyManualBonesDirty(); entityparts[i]->getAllAnimationStates()->_notifyDirty(); // entityparts[i]->_updateAnimation(); entityparts[i]->_notifyMoved(); - } + } } slot++; } } } -} \ No newline at end of file +} diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index c2b95186b..3cb40f2f1 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -14,7 +14,7 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environme ESMS::LiveCellRef *ref = ptr.get(); - assert (ref->base != NULL); + assert (ref->base != NULL); if(!ref->base->model.empty()){ const std::string &mesh = "meshes\\" + ref->base->model; std::string meshNumbered = mesh + getUniqueID(mesh) + ">|"; @@ -22,9 +22,9 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environme base = mRend.getScene()->createEntity(meshNumbered); std::string meshZero = mesh + "0000>|"; - if(transformations = (NIFLoader::getSingletonPtr())->getAnim(meshZero)){ + if((transformations = (NIFLoader::getSingletonPtr())->getAnim(meshZero))){ - for(int init = 0; init < transformations->size(); init++){ + for(std::size_t init = 0; init < transformations->size(); init++){ rindexI.push_back(0); tindexI.push_back(0); } @@ -53,10 +53,10 @@ void CreatureAnimation::runAnimation(float timepassed){ else time = startTime + (time - stopTime); } - + handleAnimationTransforms(); handleShapes(shapes, base, base->getSkeleton()); } } -} \ No newline at end of file +} diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 0ff679507..ef5c10559 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -13,7 +13,7 @@ NpcAnimation::~NpcAnimation(){ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,OEngine::Render::OgreRenderer& _rend): Animation(_env,_rend){ ESMS::LiveCellRef *ref = ptr.get(); - + //Part selection on last character of the file string // " Tri Chest // * Tri Tail @@ -35,10 +35,10 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O std::string hairID = ref->base->hair; std::string headID = ref->base->head; std::string npcName = ref->base->name; - //ESMStore::Races r = + //ESMStore::Races r = const ESM::Race* race = mEnvironment.mWorld->getStore().races.find(ref->base->race); - - + + std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4); char secondtolast = bodyRaceID.at(bodyRaceID.length() - 2); bool female = tolower(secondtolast) == 'f'; @@ -51,7 +51,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O std::cout << " Sex: Male" << " Height: " << race->data.height.male << "\n"; }*/ - + std::string smodel = "meshes\\base_anim.nif"; if(beast) @@ -61,25 +61,25 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O assert(insert); NifOgre::NIFLoader::load(smodel); - + base = mRend.getScene()->createEntity(smodel); - base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones + base->setSkipAnimationStateUpdate(true); //Magical line of code, this makes the bones //stay in the same place when we skipanim, or open a gui window - - if(transformations = (NIFLoader::getSingletonPtr())->getAnim(smodel)){ + + if((transformations = (NIFLoader::getSingletonPtr())->getAnim(smodel))){ for(unsigned int init = 0; init < transformations->size(); init++){ rindexI.push_back(0); tindexI.push_back(0); } - + stopTime = transformations->begin()->getStopTime(); startTime = transformations->begin()->getStartTime(); } textmappings = NIFLoader::getSingletonPtr()->getTextIndices(smodel); insert->attachObject(base); - + if(female) insert->scale(race->data.height.female, race->data.height.female, race->data.height.female); else @@ -108,18 +108,18 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O forearml = mEnvironment.mWorld->getStore().bodyParts.search ("b_n_argonian_m_forearm"); //We need two if(!handl) handl = mEnvironment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands"); - //const ESM::BodyPart* claviclel = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "clavicle"); + //const ESM::BodyPart* claviclel = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "clavicle"); //const ESM::BodyPart* clavicler = claviclel; const ESM::BodyPart* handr = handl; const ESM::BodyPart* forearmr = forearml; const ESM::BodyPart* wristr = wristl; const ESM::BodyPart* armr = arml; - + if(upperleg){ insertBoundedPart("meshes\\" + upperleg->model + "*|", "Left Upper Leg"); insertBoundedPart("meshes\\" + upperleg->model, "Right Upper Leg"); - + } if(foot){ if(bodyRaceID.compare("b_n_khajiit_m_") == 0) @@ -139,10 +139,10 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O { insertBoundedPart("meshes\\" + knee->model + "*|", "Left Knee"); //e insertBoundedPart("meshes\\" + knee->model, "Right Knee"); //e - + } if(ankle){ - + insertBoundedPart("meshes\\" + ankle->model + "*|", "Left Ankle"); //Ogre::Quaternion(Ogre::Radian(3.14 / 4), Ogre::Vector3(1, 0, 0)),blank); //1,0,0, blank); insertBoundedPart("meshes\\" + ankle->model, "Right Ankle"); } @@ -167,17 +167,17 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O if(wristl) insertBoundedPart("meshes\\" + wristl->model + "*|", "Left Wrist"); - - - - + + + + /*if(claviclel) insertBoundedPart("meshes\\" + claviclel->model + "*|", "Left Clavicle", base); if(clavicler) insertBoundedPart("meshes\\" + clavicler->model , "Right Clavicle", base);*/ - - + + if(neck) { insertBoundedPart("meshes\\" + neck->model, "Neck"); @@ -186,19 +186,19 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O insertBoundedPart("meshes\\" + head->model, "Head"); if(hair) insertBoundedPart("meshes\\" + hair->model, "Head"); - + if (chest){ insertFreePart("meshes\\" + chest->model, ">\"", insert); - - + + } if (handr){ insertFreePart("meshes\\" + handr->model , ">?", insert); - + } if (handl){ insertFreePart("meshes\\" + handl->model, ">>", insert); - + } if(tail){ insertFreePart("meshes\\" + tail->model, ">*", insert); @@ -215,16 +215,16 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::string bonename){ NIFLoader::load(mesh); Entity* ent = mRend.getScene()->createEntity(mesh); - - base->attachObjectToBone(bonename, ent); + + base->attachObjectToBone(bonename, ent); return ent; } void NpcAnimation::insertFreePart(const std::string &mesh, const std::string suffix, Ogre::SceneNode* insert){ - std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix; + std::string meshNumbered = mesh + getUniqueID(mesh + suffix) + suffix; NIFLoader::load(meshNumbered); - + Ogre::Entity* ent = mRend.getScene()->createEntity(meshNumbered); - + /*MaterialPtr material = ent->getSubEntity(0)->getMaterial(); material->removeAllTechniques(); @@ -234,7 +234,7 @@ void NpcAnimation::insertFreePart(const std::string &mesh, const std::string suf pass2->setVertexProgram("Ogre/HardwareSkinningTwoWeights"); pass2->setColourWriteEnabled(false); //tech->setSchemeName("blahblah");*/ - + insert->attachObject(ent); entityparts.push_back(ent); @@ -244,7 +244,7 @@ void NpcAnimation::insertFreePart(const std::string &mesh, const std::string suf handleShapes(shapes, ent, base->getSkeleton()); } - + } @@ -256,10 +256,10 @@ void NpcAnimation::runAnimation(float timepassed){ //3. Handle the shapes dependent on animation transforms if(animate > 0){ time += timepassed; - + if(time > stopTime){ animate--; - + if(animate == 0) time = stopTime; else @@ -270,21 +270,21 @@ void NpcAnimation::runAnimation(float timepassed){ Ogre::Vector3 current = insert->_getWorldAABB().getCenter(); //This is the attempt at npc physics - //mEnvironment.mWorld->setObjectPhysicsPosition(insert->getName(), current); + //mEnvironment.mWorld->setObjectPhysicsPosition(insert->getName(), current); + - /*if(base->hasSkeleton()) { - + Ogre::Quaternion boneQuat = rotate; Ogre::Vector3 boneTrans = trans; mEnvironment.mWorld->setObjectPhysicsPosition(insert->getName(), boneTrans + insert->getPosition()); //mEnvironment.mWorld->setObjectPhysicsRotation(insert->getName(), boneQuat * insert->getOrientation()); - + }*/ - - + + std::vector*>::iterator shapepartsiter = shapeparts.begin(); std::vector::iterator entitypartsiter = entityparts.begin(); while(shapepartsiter != shapeparts.end()) @@ -292,12 +292,12 @@ void NpcAnimation::runAnimation(float timepassed){ std::vector* shapes = *shapepartsiter; Ogre::Entity* theentity = *entitypartsiter; /* - Pass* pass = theentity->getSubEntity(0)->getMaterial()->getBestTechnique()->getPass(0); + Pass* pass = theentity->getSubEntity(0)->getMaterial()->getBestTechnique()->getPass(0); if (pass->hasVertexProgram() && pass->getVertexProgram()->isSkeletalAnimationIncluded()) std::cout << "It's hardware\n"; else std::cout << "It's software\n";*/ - + handleShapes(shapes, theentity, theentity->getSkeleton()); shapepartsiter++; entitypartsiter++; @@ -305,4 +305,4 @@ void NpcAnimation::runAnimation(float timepassed){ } } -} \ No newline at end of file +} diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index fff141263..6215c1913 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -22,7 +22,7 @@ namespace MWRender { RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Environment& environment) -:mRendering(_rend), mObjects(mRendering), mDebugging(engine), mActors(mRendering, environment) +:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mDebugging(engine) { mRendering.createScene("PlayerCam", 55, 5); mSkyManager = MWRender::SkyManager::create(mRendering.getWindow(), mRendering.getCamera(), resDir); diff --git a/components/nif/node.hpp b/components/nif/node.hpp index bbceb866e..080042746 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -103,7 +103,7 @@ struct NiTriShapeCopy std::vector vertices; std::vector normals; std::vector boneinfo; - std::map> vertsToWeights; + std::map > vertsToWeights; Nif::NiMorphData morph; }; @@ -158,13 +158,13 @@ struct NiTriShape : Node { float *current = (float*) (ptr + i * 3); copy.vertices.push_back(Ogre::Vector3(*current, *(current + 1), *(current + 2))); - + if(ptrNormals){ float *currentNormals = (float*) (ptrNormals + i * 3); - copy.normals.push_back(Ogre::Vector3(*currentNormals, *(currentNormals + 1), *(currentNormals + 2))); + copy.normals.push_back(Ogre::Vector3(*currentNormals, *(currentNormals + 1), *(currentNormals + 2))); } } - + return copy; } diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 92a5713a3..c62f59ea3 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -222,7 +222,7 @@ void NIFLoader::createMaterial(const String &name, //Hardware Skinning code, textures may be the wrong color if enabled /*if(!mSkel.isNull()){ material->removeAllTechniques(); - + Ogre::Technique* tech = material->createTechnique(); //tech->setSchemeName("blahblah"); Pass* pass = tech->createPass(); @@ -234,8 +234,8 @@ void NIFLoader::createMaterial(const String &name, // will automatically be loaded when needed. If not (such as for // internal NIF textures that we might support later), we should // already have inserted a manual loader for the texture. - - + + if (!texName.empty()) { Pass *pass = material->getTechnique(0)->getPass(0); @@ -295,8 +295,8 @@ void NIFLoader::createMaterial(const String &name, material->setSpecular(specular.array[0], specular.array[1], specular.array[2], alpha); material->setSelfIllumination(emissive.array[0], emissive.array[1], emissive.array[2]); material->setShininess(glossiness); - - + + } // Takes a name and adds a unique part to it. This is just used to @@ -359,7 +359,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_FLOAT3), numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); - + if(flip) { float *datamod = new float[data->vertices.length]; @@ -381,7 +381,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std { vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, false); } - + VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding; bind->setBinding(nextBuf++, vbuf); @@ -392,7 +392,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_FLOAT3), numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); - + if(flip) { Quaternion rotation = mTransform.extractQuaternion(); @@ -456,10 +456,10 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std if(flip) { float *datamod = new float[data->uvlist.length]; - + for(unsigned int i = 0; i < data->uvlist.length; i+=2){ float x = *(data->uvlist.ptr + i); - + float y = *(data->uvlist.ptr + i + 1); datamod[i] =x; @@ -474,10 +474,10 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std // Triangle faces - The total number of triangle points int numFaces = data->triangles.length; - + if (numFaces) { - + sub->indexData->indexCount = numFaces; sub->indexData->indexStart = 0; HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). @@ -508,14 +508,14 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std index += 3; } - + ibuf->writeData(0, ibuf->getSizeInBytes(), datamod, false); } else ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, false); sub->indexData->indexBuffer = ibuf; - + } @@ -753,9 +753,9 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou //use niskindata for the position of vertices. if (!shape->skin.empty()) { - - - + + + // vector that stores if the position of a vertex is absolute std::vector vertexPosAbsolut(numVerts,false); std::vector vertexPosOriginal(numVerts, Ogre::Vector3::ZERO); @@ -791,7 +791,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou bonePtr = mSkel->getBone(shape->skin->bones[boneIndex].name.toString()); // final_vector = old_vector + old_rotation*new_vector*old_scale - + Nif::NiSkinData::BoneInfoCopy boneinfocopy; boneinfocopy.trafo.rotation = convertRotation(it->trafo->rotation); @@ -841,7 +841,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou Vector3 absNormalsPos = vecRot * Vector3(ptrNormals + verIndex *3); absNormalsPos = absNormalsPos * (it->weights.ptr + i)->weight; vertexNormalOriginal[verIndex] = Vector3(ptrNormals + verIndex *3); - + for (int j=0; j<3; j++) (ptrNormals + verIndex*3)[j] = absNormalsPos[j]; } @@ -868,7 +868,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou absNormalsPos = absNormalsPos * (it->weights.ptr + i)->weight; Vector3 oldNormal = Vector3(ptrNormals + verIndex *3); absNormalsPos = absNormalsPos + oldNormal; - + for (int j=0; j<3; j++) (ptrNormals + verIndex*3)[j] = absNormalsPos[j]; } @@ -879,19 +879,19 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou vba.boneIndex = bonePtr->getHandle(); vba.vertexIndex = verIndex; vba.weight = (it->weights.ptr + i)->weight; - + vertexBoneAssignments.push_back(vba); } - + boneIndex++; } - + } else { - + copy.boneSequence = boneSequence; // Rotate, scale and translate all the vertices, const Matrix &rot = shape->trafo->rotation; @@ -902,7 +902,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou copy.trafo.rotation = convertRotation(original.rotation); copy.trafo.scale = original.scale; //We don't use velocity for anything yet, so it does not need to be saved - + // Computes C = B + AxC*scale for (int i=0; inormals.length) { @@ -955,7 +955,7 @@ void NIFLoader::calculateTransform() // Calculate transform Matrix4 transform = Matrix4::IDENTITY; transform = Matrix4::getScale(vector) * transform; - + // Check whether we have to flip vertex winding. // We do have to, if we changed our right hand base. // We can test it by using the cross product from X and Y and see, if it is a non-negative @@ -963,7 +963,7 @@ void NIFLoader::calculateTransform() // but the test is cheap either way. Matrix3 m3; transform.extract3x3Matrix(m3); - + if (m3.GetColumn(0).crossProduct(m3.GetColumn(1)).dotProduct(m3.GetColumn(2)) < 0) { mFlipVertexWinding = true; @@ -1003,39 +1003,38 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, } if (e->recType == RC_NiTextKeyExtraData){ - Nif::NiTextKeyExtraData* extra = dynamic_cast (e); - - std::ofstream file; + Nif::NiTextKeyExtraData* extra = dynamic_cast (e); + + std::ofstream file; if(mOutputAnimFiles){ - std::string cut = ""; - for(unsigned int i = 0; i < name.length(); i++) - { - if(!(name.at(i) == '\\' || name.at(i) == '/' || name.at(i) == '>' || name.at(i) == '<' || name.at(i) == '?' || name.at(i) == '*' || name.at(i) == '|' || name.at(i) == ':' || name.at(i) == '"')) - { - cut += name.at(i); - } - } - - std::cout << "Outputting " << cut << "\n"; - - file.open((verbosePath + "/Indices" + cut + ".txt").c_str()); + std::string cut = ""; + for(unsigned int i = 0; i < name.length(); i++) + { + if(!(name.at(i) == '\\' || name.at(i) == '/' || name.at(i) == '>' || name.at(i) == '<' || name.at(i) == '?' || name.at(i) == '*' || name.at(i) == '|' || name.at(i) == ':' || name.at(i) == '"')) + { + cut += name.at(i); + } + } + + std::cout << "Outputting " << cut << "\n"; + + file.open((verbosePath + "/Indices" + cut + ".txt").c_str()); } - - for(std::vector::iterator textiter = extra->list.begin(); textiter != extra->list.end(); textiter++) - { - - std::string text = textiter->text.toString(); - - replace(text.begin(), text.end(), '\n', '/'); - text.erase(std::remove(text.begin(), text.end(), '\r'), text.end()); - int i = 0; + for(std::vector::iterator textiter = extra->list.begin(); textiter != extra->list.end(); textiter++) + { + std::string text = textiter->text.toString(); + + replace(text.begin(), text.end(), '\n', '/'); + + text.erase(std::remove(text.begin(), text.end(), '\r'), text.end()); + std::size_t i = 0; while(i < text.length()){ while(i < text.length() && text.at(i) == '/' ){ i++; } - int first = i; + std::size_t first = i; int length = 0; while(i < text.length() && text.at(i) != '/' ){ i++; @@ -1045,15 +1044,15 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, //length = text.length() - first; std::string sub = text.substr(first, length); - if(mOutputAnimFiles) + if(mOutputAnimFiles) file << "Time: " << textiter->time << "|" << sub << "\n"; - - textmappings[sub] = textiter->time; + + textmappings[sub] = textiter->time; } } - } - file.close(); - } + } + file.close(); + } } Bone *bone = 0; @@ -1064,7 +1063,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, //FIXME: "Bip01" isn't every time the root bone if (node->name == "Bip01" || node->name == "Root Bone") //root node, create a skeleton { - + mSkel = SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true); } @@ -1072,7 +1071,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, { std::string name = node->name.toString(); boneSequence.push_back(name); - + // Quick-n-dirty workaround for the fact that several // bones may have the same name. if(!mSkel->hasBone(name)) @@ -1125,7 +1124,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, else if (node->recType == RC_NiTriShape && bNiTri) { std::string nodename = node->name.toString(); - + if (triname == "") { handleNiTriShape(dynamic_cast(node), flags, bounds, original, boneSequence); @@ -1172,12 +1171,12 @@ void NIFLoader::loadResource(Resource *resource) baddin = true; bNiTri = true; std::string sub = name.substr(name.length() - 6, 4); - + if(sub.compare("0000") != 0) addAnim = false; - + } - + switch(name.at(name.length() - 1)) { case '"': @@ -1253,33 +1252,30 @@ void NIFLoader::loadResource(Resource *resource) // Handle the node std::vector boneSequence; - - + + handleNode(node, 0, NULL, bounds, 0, boneSequence); if(addAnim) { for(int i = 0; i < nif.numRecords(); i++) - { - Nif::NiKeyframeController *f = dynamic_cast(nif.getRecord(i)); - - Nif::Node *n = dynamic_cast(nif.getRecord(i)); - if(f != NULL) - { - hasAnim = true; - Nif::Node *o = dynamic_cast(f->target.getPtr()); - Nif::NiKeyframeDataPtr data = f->data; - - if (f->timeStart == 10000000000000000) - continue; - data->setBonename(o->name.toString()); - data->setStartTime(f->timeStart); - data->setStopTime(f->timeStop); - - allanim.push_back(data.get()); - - - } + { + Nif::NiKeyframeController *f = dynamic_cast(nif.getRecord(i)); + + if(f != NULL) + { + hasAnim = true; + Nif::Node *o = dynamic_cast(f->target.getPtr()); + Nif::NiKeyframeDataPtr data = f->data; + + if (f->timeStart == 10000000000000000) + continue; + data->setBonename(o->name.toString()); + data->setStartTime(f->timeStart); + data->setStopTime(f->timeStop); + + allanim.push_back(data.get()); + } } } // set the bounding value. @@ -1290,18 +1286,18 @@ void NIFLoader::loadResource(Resource *resource) mesh->_setBoundingSphereRadius(bounds.getRadius()); } if(hasAnim && addAnim){ - allanimmap[name] = allanim; - alltextmappings[name] = textmappings; - } - if(!mSkel.isNull() && shapes.size() > 0 && addAnim) - { - allshapesmap[name] = shapes; - - } - + allanimmap[name] = allanim; + alltextmappings[name] = textmappings; + } + if(!mSkel.isNull() && shapes.size() > 0 && addAnim) + { + allshapesmap[name] = shapes; + + } + if(flip){ - mesh->_setBounds(mBoundingBox, false); - } + mesh->_setBounds(mBoundingBox, false); + } if (!mSkel.isNull()) { @@ -1310,7 +1306,7 @@ void NIFLoader::loadResource(Resource *resource) } void NIFLoader::addInMesh(Ogre::Mesh* input){ - addin.push_back(input); + addin.push_back(input); } @@ -1318,7 +1314,7 @@ void NIFLoader::addInMesh(Ogre::Mesh* input){ MeshPtr NIFLoader::load(const std::string &name, const std::string &group) { - + MeshManager *m = MeshManager::getSingletonPtr(); // Check if the resource already exists ResourcePtr ptr = m->getByName(name, group); @@ -1335,26 +1331,26 @@ MeshPtr NIFLoader::load(const std::string &name, /* This function shares much of the same code handleShapes() in MWRender::Animation -This function also creates new position and normal buffers for submeshes. +This function also creates new position and normal buffers for submeshes. This function points to existing texture and IndexData buffers */ std::vector* NIFLoader::getAnim(std::string lowername){ - - std::map,ciLessBoost>::iterator iter = allanimmap.find(lowername); + + std::map,ciLessBoost>::iterator iter = allanimmap.find(lowername); std::vector* pass = 0; - if(iter != allanimmap.end()) - pass = &(iter->second); - return pass; - + if(iter != allanimmap.end()) + pass = &(iter->second); + return pass; + } std::vector* NIFLoader::getShapes(std::string lowername){ - - std::map,ciLessBoost>::iterator iter = allshapesmap.find(lowername); + + std::map,ciLessBoost>::iterator iter = allshapesmap.find(lowername); std::vector* pass = 0; - if(iter != allshapesmap.end()) - pass = &(iter->second); - return pass; + if(iter != allshapesmap.end()) + pass = &(iter->second); + return pass; } std::map* NIFLoader::getTextIndices(std::string lowername){ diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index fd1620822..62239bb4c 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -79,7 +79,7 @@ namespace Mangle namespace NifOgre { - + /** Manual resource loader for NIF meshes. This is the main class responsible for translating the internal NIF mesh structure into @@ -109,7 +109,7 @@ class NIFLoader : Ogre::ManualResourceLoader const std::string &group="General"); //void insertMeshInsideBase(Ogre::Mesh* mesh); std::vector* getAnim(std::string name); - std::vector* getShapes(std::string name); + std::vector* getShapes(std::string name); std::map* getTextIndices(std::string name); void addInMesh(Ogre::Mesh* input); @@ -121,12 +121,12 @@ class NIFLoader : Ogre::ManualResourceLoader void setVerbosePath(std::string path); private: - NIFLoader() : mNormaliseNormals(false), resourceGroup("General"), resourceName(""), flip(false), + NIFLoader() : resourceName(""), resourceGroup("General"), flip(false), mNormaliseNormals(false), mFlipVertexWinding(false), mOutputAnimFiles(false) {} NIFLoader(NIFLoader& n) {} void calculateTransform(); - + void warn(std::string msg); void fail(std::string msg); @@ -167,7 +167,7 @@ class NIFLoader : Ogre::ManualResourceLoader std::string verbosePath; std::string resourceName; std::string resourceGroup; - Ogre::Matrix4 mTransform; + Ogre::Matrix4 mTransform; Ogre::AxisAlignedBox mBoundingBox; bool flip; bool mNormaliseNormals; @@ -184,14 +184,14 @@ class NIFLoader : Ogre::ManualResourceLoader std::string name; std::string triname; std::vector allanim; - std::map textmappings; - std::map,ciLessBoost> alltextmappings; - std::map,ciLessBoost> allanimmap; - std::map,ciLessBoost> allshapesmap; + std::map textmappings; + std::map,ciLessBoost> alltextmappings; + std::map,ciLessBoost> allanimmap; + std::map,ciLessBoost> allshapesmap; std::vector addin; std::vector mAnim; - std::vector mS; - + std::vector mS; + }; } From 16bc374921a8480625fccf3b0660b208ff760a3d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 23 Jan 2012 14:33:06 +0100 Subject: [PATCH 22/47] animation updates were hooked up to the wrong update function --- apps/openmw/engine.cpp | 7 +++++-- apps/openmw/mwrender/actors.cpp | 21 ++++++++------------- apps/openmw/mwrender/actors.hpp | 8 ++++---- apps/openmw/mwrender/renderingmanager.cpp | 6 +----- apps/openmw/mwrender/renderingmanager.hpp | 4 +--- apps/openmw/mwworld/scene.cpp | 12 ++++++------ apps/openmw/mwworld/scene.hpp | 3 ++- apps/openmw/mwworld/world.cpp | 8 ++++++-- apps/openmw/mwworld/world.hpp | 2 ++ 9 files changed, 35 insertions(+), 36 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index e1a16accf..ee3a6181a 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -147,7 +147,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) mEnvironment.mWorld->advanceTime ( mEnvironment.mFrameDuration*mEnvironment.mWorld->getTimeScaleFactor()/3600); - + if (changed) // keep change flag for another frame, if cell changed happend in local script mEnvironment.mWorld->markCellAsUnchanged(); @@ -158,6 +158,9 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) if (mEnvironment.mWindowManager->getMode()==MWGui::GM_Game) mEnvironment.mWorld->doPhysics (movement, mEnvironment.mFrameDuration); + // update world + mEnvironment.mWorld->update (evt.timeSinceLastFrame); + // report focus object (for debugging) if (mReportFocus) updateFocusReport (mEnvironment.mFrameDuration); @@ -343,7 +346,7 @@ void OMW::Engine::go() // Set up the GUI system mGuiManager = new OEngine::GUI::MyGUIManager(mOgre->getWindow(), mOgre->getScene(), false, mCfgMgr.getLogPath().string() + std::string("/")); - + // Create window manager - this manages all the MW-specific GUI windows MWScript::registerExtensions (mExtensions); diff --git a/apps/openmw/mwrender/actors.cpp b/apps/openmw/mwrender/actors.cpp index 3b94b19f7..acc655404 100644 --- a/apps/openmw/mwrender/actors.cpp +++ b/apps/openmw/mwrender/actors.cpp @@ -12,15 +12,11 @@ void Actors::setMwRoot(Ogre::SceneNode* root){ mMwRoot = root; } void Actors::insertNPC(const MWWorld::Ptr& ptr){ - + insertBegin(ptr, true, true); NpcAnimation* anim = new MWRender::NpcAnimation(ptr, mEnvironment, mRend); - - // - - mAllActors[ptr] = anim; - - + + mAllActors[ptr] = anim; } void Actors::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){ Ogre::SceneNode* cellnode; @@ -61,7 +57,7 @@ void Actors::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){ } void Actors::insertCreature (const MWWorld::Ptr& ptr){ - + insertBegin(ptr, true, true); CreatureAnimation* anim = new MWRender::CreatureAnimation(ptr, mEnvironment, mRend); //mAllActors.insert(std::pair(ptr,anim)); @@ -75,7 +71,7 @@ bool Actors::deleteObject (const MWWorld::Ptr& ptr) mAllActors.erase(ptr); if (Ogre::SceneNode *base = ptr.getRefData().getBaseNode()) { - + Ogre::SceneNode *parent = base->getParentSceneNode(); for (std::map::const_iterator iter ( @@ -110,7 +106,7 @@ void Actors::removeCell(MWWorld::Ptr::CellStore* store){ mAllActors.erase(iter); } } - + } void Actors::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number){ @@ -121,10 +117,9 @@ void Actors::skipAnimation (const MWWorld::Ptr& ptr){ if(mAllActors.find(ptr) != mAllActors.end()) mAllActors[ptr]->stopScript(); } -void Actors::addTime(){ - //std::cout << "Adding time in actors\n"; +void Actors::update (float duration){ for(std::map::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++) { - (iter->second)->runAnimation(mEnvironment.mFrameDuration); + (iter->second)->runAnimation(duration); } } diff --git a/apps/openmw/mwrender/actors.hpp b/apps/openmw/mwrender/actors.hpp index 93ec07f98..7179c08fb 100644 --- a/apps/openmw/mwrender/actors.hpp +++ b/apps/openmw/mwrender/actors.hpp @@ -26,7 +26,7 @@ namespace MWRender{ MWWorld::Environment& mEnvironment; std::map mAllActors; - + public: Actors(OEngine::Render::OgreRenderer& _rend, MWWorld::Environment& _env): mRend(_rend), mEnvironment(_env){} @@ -52,8 +52,8 @@ namespace MWRender{ ///< Skip the animation for the given MW-reference for one frame. Calls to this function for /// references that are currently not in the rendered scene should be ignored. - void addTime(); - + void update (float duration); + }; } -#endif \ No newline at end of file +#endif diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 6215c1913..c5cf8be5d 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -121,7 +121,7 @@ void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Ve void RenderingManager::update (float duration){ - + mActors.update (duration); } void RenderingManager::skyEnable () @@ -240,9 +240,5 @@ void RenderingManager::skipAnimation (const MWWorld::Ptr& ptr) { mActors.skipAnimation(ptr); } -void RenderingManager::addTime(){ - mActors.addTime(); - //Notify each animation that time has passed -} } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 747a3e0ee..084f89cb0 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -105,14 +105,12 @@ class RenderingManager: private RenderingInterface { ///< Skip the animation for the given MW-reference for one frame. Calls to this function for /// references that are currently not in the rendered scene should be ignored. - void addTime(); - private: void setAmbientMode(); SkyManager* mSkyManager; OEngine::Render::OgreRenderer &mRendering; - + MWRender::Objects mObjects; MWRender::Actors mActors; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index b08a52aac..2f0d33c97 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -52,8 +52,8 @@ void insertCellRefList(MWRender::RenderingManager& rendering, MWWorld::Environme namespace MWWorld { - void Scene::advanceTime(){ - mRendering.addTime(); + void Scene::update (float duration){ + mRendering.update (duration); } void Scene::unloadCell (CellStoreCollection::iterator iter) { @@ -61,9 +61,9 @@ namespace MWWorld ListHandles functor; MWWorld::Ptr::CellStore* active = *iter; - - - + + + active->forEach(functor); @@ -83,7 +83,7 @@ namespace MWWorld mEnvironment.mMechanicsManager->dropActors (active); mEnvironment.mSoundManager->stopSound (active); mActiveCells.erase(active); - + } void Scene::loadCell (Ptr::CellStore *cell) diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index d3df7c0f5..4d1bd6fb5 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -101,7 +101,8 @@ namespace MWWorld void markCellAsUnchanged(); void insertCell(ESMS::CellStore &cell, MWWorld::Environment& environment); - void advanceTime(); + + void update (float duration); }; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 2232e8a1d..ce66861b8 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -348,14 +348,13 @@ namespace MWWorld void World::advanceTime (double hours) { hours += mGlobalVariables->getFloat ("gamehour"); - + setHour (hours); int days = hours / 24; if (days>0) mGlobalVariables->setInt ("dayspassed", days + mGlobalVariables->getInt ("dayspassed")); - mWorldScene->advanceTime(); } void World::setHour (double hour) @@ -691,4 +690,9 @@ namespace MWWorld void World::setObjectPhysicsPosition(const std::string& handle, Ogre::Vector3 vec){ mPhysics->moveObject(handle, vec); } + + void World::update (float duration) + { + mWorldScene->update (duration); + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 235d203a6..a3daa16da 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -220,6 +220,8 @@ namespace MWWorld /// references that are currently not in the rendered scene should be ignored. void setObjectPhysicsRotation(const std::string& handle,Ogre::Quaternion quat); void setObjectPhysicsPosition(const std::string& handle,Ogre::Vector3 vector); + + void update (float duration); }; } From 26c328e73f8da4866105a7a7a0ac4429f4f09113 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 23 Jan 2012 14:55:00 +0100 Subject: [PATCH 23/47] added some more comments to avoid further confusion --- apps/openmw/mwworld/world.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index a3daa16da..22860b883 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -140,12 +140,16 @@ namespace MWWorld void disable (Ptr reference); void advanceTime (double hours); + ///< Advance in-game time. void setHour (double hour); + ///< Set in-game time hour. void setMonth (int month); + ///< Set in-game time month. void setDay (int day); + ///< Set in-game time day. bool toggleSky(); ///< \return Resulting mode From 258ab0218a78a73a362eb17ffdb24470a0219c0a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 23 Jan 2012 23:32:00 +0100 Subject: [PATCH 24/47] submodule update (issue #131) --- libs/openengine | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/openengine b/libs/openengine index 2f5eca9d8..6c7e5d00e 160000 --- a/libs/openengine +++ b/libs/openengine @@ -1 +1 @@ -Subproject commit 2f5eca9d878526bdd9dce93ece7f42093b481545 +Subproject commit 6c7e5d00e4f5bf954afe15f10e56f03520abfee4 From 4b6cd582a7b2562a2c436981654f02c1960b51de Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 24 Jan 2012 10:45:40 +0100 Subject: [PATCH 25/47] removed some redundant (and misplaced) functions --- apps/openmw/mwrender/npcanimation.cpp | 18 +----------------- apps/openmw/mwworld/world.cpp | 6 ------ apps/openmw/mwworld/world.hpp | 2 -- 3 files changed, 1 insertion(+), 25 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index ef5c10559..863f7577b 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -269,22 +269,6 @@ void NpcAnimation::runAnimation(float timepassed){ handleAnimationTransforms(); Ogre::Vector3 current = insert->_getWorldAABB().getCenter(); - //This is the attempt at npc physics - //mEnvironment.mWorld->setObjectPhysicsPosition(insert->getName(), current); - - - - /*if(base->hasSkeleton()) - { - - Ogre::Quaternion boneQuat = rotate; - Ogre::Vector3 boneTrans = trans; - mEnvironment.mWorld->setObjectPhysicsPosition(insert->getName(), boneTrans + insert->getPosition()); - //mEnvironment.mWorld->setObjectPhysicsRotation(insert->getName(), boneQuat * insert->getOrientation()); - - }*/ - - std::vector*>::iterator shapepartsiter = shapeparts.begin(); std::vector::iterator entitypartsiter = entityparts.begin(); while(shapepartsiter != shapeparts.end()) @@ -301,7 +285,7 @@ void NpcAnimation::runAnimation(float timepassed){ handleShapes(shapes, theentity, theentity->getSkeleton()); shapepartsiter++; entitypartsiter++; - } + } } } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index ce66861b8..e66dc01dc 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -684,12 +684,6 @@ namespace MWWorld { mRendering.skipAnimation (ptr); } - void World::setObjectPhysicsRotation(const std::string& handle, Ogre::Quaternion quat){ - mPhysics->rotateObject(handle, quat); - } - void World::setObjectPhysicsPosition(const std::string& handle, Ogre::Vector3 vec){ - mPhysics->moveObject(handle, vec); - } void World::update (float duration) { diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 22860b883..13e06cc39 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -222,8 +222,6 @@ namespace MWWorld void skipAnimation (const MWWorld::Ptr& ptr); ///< Skip the animation for the given MW-reference for one frame. Calls to this function for /// references that are currently not in the rendered scene should be ignored. - void setObjectPhysicsRotation(const std::string& handle,Ogre::Quaternion quat); - void setObjectPhysicsPosition(const std::string& handle,Ogre::Vector3 vector); void update (float duration); }; From ec6243dd77433b3bbc9617a93e1bfe57faa0cdae Mon Sep 17 00:00:00 2001 From: Nikolay Kasyanov Date: Tue, 24 Jan 2012 16:01:29 +0400 Subject: [PATCH 26/47] fixed compilation problem with llvm clang: constant type explicitly set to float --- components/nifogre/ogre_nif_loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index c62f59ea3..c286d9514 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1268,7 +1268,7 @@ void NIFLoader::loadResource(Resource *resource) Nif::Node *o = dynamic_cast(f->target.getPtr()); Nif::NiKeyframeDataPtr data = f->data; - if (f->timeStart == 10000000000000000) + if (f->timeStart == 10000000000000000.0f) continue; data->setBonename(o->name.toString()); data->setStartTime(f->timeStart); From 6ada405af0ce8b648e62b23e0ae84ad21f888059 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 25 Jan 2012 16:08:55 +0100 Subject: [PATCH 27/47] removing last bits of old D code --- old_d_version/.gitignore | 66 -- old_d_version/bullet/bindings.d | 85 -- old_d_version/bullet/bullet.d | 34 - old_d_version/bullet/cpp_bullet.cpp | 502 ---------- old_d_version/bullet/cpp_player.cpp | 381 -------- old_d_version/bullet/cpp_scale.cpp | 98 -- old_d_version/core/config.d | 437 --------- old_d_version/core/filefinder.d | 229 ----- old_d_version/esm/defs.d | 187 ---- old_d_version/esm/esmmain.d | 167 ---- old_d_version/esm/filereader.d | 783 --------------- old_d_version/esm/imports.d | 47 - old_d_version/esm/listkeeper.d | 330 ------- old_d_version/esm/loadcell.d | 189 ---- old_d_version/esm/loaddial.d | 289 ------ old_d_version/esm/records.d | 219 ----- old_d_version/esmtool.d | 377 -------- old_d_version/input/events.d | 336 ------- old_d_version/input/ois.d | 428 --------- old_d_version/ogre/cpp_framelistener.cpp | 41 - old_d_version/ogre/cpp_interface.cpp | 135 --- old_d_version/ogre/meshloader.d | 391 -------- old_d_version/openmw.d | 471 --------- old_d_version/terrain/archive.d | 461 --------- old_d_version/terrain/bindings.d | 27 - old_d_version/terrain/cachewriter.d | 337 ------- old_d_version/terrain/cpp_baseland.cpp | 101 -- old_d_version/terrain/cpp_mesh.cpp | 286 ------ old_d_version/terrain/cpp_terrain.cpp | 413 -------- old_d_version/terrain/esmland.d | 158 --- old_d_version/terrain/generator.d | 1114 ---------------------- old_d_version/terrain/myfile.d | 71 -- old_d_version/terrain/outbuffer.d | 94 -- old_d_version/terrain/quad.d | 286 ------ old_d_version/terrain/terrain.d | 103 -- 35 files changed, 9673 deletions(-) delete mode 100644 old_d_version/.gitignore delete mode 100644 old_d_version/bullet/bindings.d delete mode 100644 old_d_version/bullet/bullet.d delete mode 100644 old_d_version/bullet/cpp_bullet.cpp delete mode 100644 old_d_version/bullet/cpp_player.cpp delete mode 100644 old_d_version/bullet/cpp_scale.cpp delete mode 100644 old_d_version/core/config.d delete mode 100644 old_d_version/core/filefinder.d delete mode 100644 old_d_version/esm/defs.d delete mode 100644 old_d_version/esm/esmmain.d delete mode 100644 old_d_version/esm/filereader.d delete mode 100644 old_d_version/esm/imports.d delete mode 100644 old_d_version/esm/listkeeper.d delete mode 100644 old_d_version/esm/loadcell.d delete mode 100644 old_d_version/esm/loaddial.d delete mode 100644 old_d_version/esm/records.d delete mode 100644 old_d_version/esmtool.d delete mode 100644 old_d_version/input/events.d delete mode 100644 old_d_version/input/ois.d delete mode 100644 old_d_version/ogre/cpp_framelistener.cpp delete mode 100644 old_d_version/ogre/cpp_interface.cpp delete mode 100644 old_d_version/ogre/meshloader.d delete mode 100644 old_d_version/openmw.d delete mode 100644 old_d_version/terrain/archive.d delete mode 100644 old_d_version/terrain/bindings.d delete mode 100644 old_d_version/terrain/cachewriter.d delete mode 100644 old_d_version/terrain/cpp_baseland.cpp delete mode 100644 old_d_version/terrain/cpp_mesh.cpp delete mode 100644 old_d_version/terrain/cpp_terrain.cpp delete mode 100644 old_d_version/terrain/esmland.d delete mode 100644 old_d_version/terrain/generator.d delete mode 100644 old_d_version/terrain/myfile.d delete mode 100644 old_d_version/terrain/outbuffer.d delete mode 100644 old_d_version/terrain/quad.d delete mode 100644 old_d_version/terrain/terrain.d diff --git a/old_d_version/.gitignore b/old_d_version/.gitignore deleted file mode 100644 index 23e6b6fd2..000000000 --- a/old_d_version/.gitignore +++ /dev/null @@ -1,66 +0,0 @@ - -# / -/cache -/later -/openmw.ini.* -/rr.sh -/fontdump -/MyGUI.log -/upm.sh -/raw.txt -/vids -/include -/includes -/.thumbnails -/*.jpg -/*.dll -/*.exe -/*.def -/*.a -/*.map -/*.rsp -/ogre.cfg -/openmw -/bored -/bsatool -/niftool -/esmtool -/bored.highscores -/Ogre.log -/openmw.ini -/openmw.ini.old -/dsss_* -/dsss.last -/objs -/nifobjs - -# /bullet/ -/bullet/OgreOpcode* -/bullet/demo -/bullet/*.a - -# /media_mygui/ -/media_mygui/core.skin.orig -/media_mygui/.thumbnails - -# /monster/ -/monster/*openmw_last - -# /mscripts/ -/mscripts/draft - -# /nif/ -/nif/bumpmap -/nif/*.nif - -# /ogre/ -/ogre/*.nif -/ogre/cs - -# /util/ -/util/iconv - -*.o -*.patch -*.diff -.directory diff --git a/old_d_version/bullet/bindings.d b/old_d_version/bullet/bindings.d deleted file mode 100644 index 9dbd76197..000000000 --- a/old_d_version/bullet/bindings.d +++ /dev/null @@ -1,85 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (bindings.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module bullet.bindings; - -/* - * This module is the interface between D and the C++ code that - * handles Bullet. - */ - -typedef void* BulletShape; - -extern(C): - -// Initialize the dynamic world. Returns non-zero if an error occurs. -int bullet_init(); - -// Set physics modes -void bullet_nextMode(); -void bullet_walk(); -void bullet_fly(); -void bullet_ghost(); - -// Warp the player to a specific location. -void bullet_movePlayer(float x, float y, float z); - -// Request that the player moves in this direction -void bullet_setPlayerDir(float x, float y, float z); - -// Get the current player position, after physics and collision have -// been applied. -void bullet_getPlayerPos(float *x, float *y, float *z); - -// Create a box shape. Used for bounding boxes. The box is a trimesh -// and is hollow (you can walk inside it.) -void bullet_createBoxShape(float minX, float minY, float minZ, - float maxX, float maxY, float maxZ, - float *trans,float *matrix); - -// Create a triangle shape. This is cumulative, all meshes created -// with this function are added to the same shape. Since the various -// parts of a mesh can be differently transformed and we are putting -// them all in one shape, we must transform the vertices manually. -void bullet_createTriShape(int numFaces, - void *triArray, - int numVerts, - void *vertArray, - float *trans,float *matrix); - -// "Flushes" the meshes created with createTriShape, returning the -// pointer to the final shape object. -BulletShape bullet_getFinalShape(); - -// Insert a static mesh with the given translation, quaternion -// rotation and scale. The quaternion is assumed to be in Ogre format, -// ie. with the W first. -void bullet_insertStatic(BulletShape shp, float *pos, - float *quat, float scale); - -// Move the physics simulation 'delta' seconds forward in time -void bullet_timeStep(float delta); - -// Deallocate objects -void bullet_cleanup(); - diff --git a/old_d_version/bullet/bullet.d b/old_d_version/bullet/bullet.d deleted file mode 100644 index d33a22b7c..000000000 --- a/old_d_version/bullet/bullet.d +++ /dev/null @@ -1,34 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (bullet.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module bullet.bullet; - -import bullet.bindings; - -void initBullet() -{ - if(bullet_init()) - throw new Exception("Bullet setup failed"); -} - -void cleanupBullet() { bullet_cleanup(); } diff --git a/old_d_version/bullet/cpp_bullet.cpp b/old_d_version/bullet/cpp_bullet.cpp deleted file mode 100644 index 50af01b57..000000000 --- a/old_d_version/bullet/cpp_bullet.cpp +++ /dev/null @@ -1,502 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (cpp_bullet.cpp) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -#include "btBulletDynamicsCommon.h" - -#include - -#include "../util/dbg.h" - -using namespace std; - -class CustomOverlappingPairCallback; - -enum - { - MASK_PLAYER = 1, - MASK_STATIC = 2 - }; - -// System variables -btDefaultCollisionConfiguration* g_collisionConfiguration; -btCollisionDispatcher *g_dispatcher; -//btBroadphaseInterface *g_broadphase; -btAxisSweep3 *g_broadphase; -btSequentialImpulseConstraintSolver* g_solver; -btDynamicsWorld *g_dynamicsWorld; - -// Player variables -btCollisionObject* g_playerObject; -btConvexShape *g_playerShape; - -// Player position. This is updated automatically by the physics -// system based on g_walkDirection and collisions. It is read by D -// code through bullet_getPlayerPos(). -btVector3 g_playerPosition; - -// Walking vector - defines direction and speed that the player -// intends to move right now. This is updated from D code each frame -// through bullet_setPlayerDir(), based on player input (and later, AI -// decisions.) The units of the vector are points per second. -btVector3 g_walkDirection; - -// The current trimesh shape being built. All new inserted meshes are -// added into this, until bullet_getFinalShape() is called. -btTriangleIndexVertexArray *g_currentMesh; - -// These variables and the class below are used in player collision -// detection. The callback is injected into the broadphase and keeps a -// continuously updated list of what objects are colliding with the -// player (in g_pairCache). This list is used in the function called -// recoverFromPenetration(). -btHashedOverlappingPairCache* g_pairCache; -CustomOverlappingPairCallback *g_customPairCallback; - -// Three physics modes: walking (with gravity and collision), flying -// (collision but no gravity) and ghost mode (fly through walls) -enum - { - PHYS_WALK, - PHYS_FLY, - PHYS_GHOST - }; -int g_physMode; - -// Include the player physics -#include "cpp_player.cpp" - -// Include the uniform shape scaler -#include "cpp_scale.cpp" - -class CustomOverlappingPairCallback : public btOverlappingPairCallback -{ -public: - virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, - btBroadphaseProxy* proxy1) - { - if (proxy0->m_clientObject==g_playerObject || - proxy1->m_clientObject==g_playerObject) - return g_pairCache->addOverlappingPair(proxy0,proxy1); - return 0; - } - - virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0, - btBroadphaseProxy* proxy1, - btDispatcher* dispatcher) - { - if (proxy0->m_clientObject==g_playerObject || - proxy1->m_clientObject==g_playerObject) - return g_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); - - return 0; - } - - void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0, - btDispatcher* dispatcher) - { if (proxy0->m_clientObject==g_playerObject) - g_pairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher); - } -}; - -extern "C" int32_t bullet_init() -{ - // ------- SET UP THE WORLD ------- - - // Set up basic objects - g_collisionConfiguration = new btDefaultCollisionConfiguration(); - g_dispatcher = new btCollisionDispatcher(g_collisionConfiguration); - //g_broadphase = new btDbvtBroadphase(); - g_solver = new btSequentialImpulseConstraintSolver; - - // TODO: Figure out what to do with this. We need the user callback - // function used below (I think), but this is only offered by this - // broadphase implementation (as far as I can see.) Maybe we can - // scan through the cell first and find good values that covers all - // the objects before we set up the dynamic world. Another option is - // to create a custom broadphase designed for our purpose. (We - // should probably use different ones for interior and exterior - // cells in any case.) - btVector3 worldMin(-20000,-20000,-20000); - btVector3 worldMax(20000,20000,20000); - g_broadphase = new btAxisSweep3(worldMin,worldMax); - - g_dynamicsWorld = - new btDiscreteDynamicsWorld(g_dispatcher, - g_broadphase, - g_solver, - g_collisionConfiguration); - - //g_dynamicsWorld->setGravity(btVector3(0,-10,0)); - - - // ------- SET UP THE PLAYER ------- - - // Create the player collision shape. - float width = 30; - - /* - float height = 50; - btVector3 spherePositions[2]; - btScalar sphereRadii[2]; - sphereRadii[0] = width; - sphereRadii[1] = width; - spherePositions[0] = btVector3 (0,0,0); - spherePositions[1] = btVector3 (0,0,-height); - - // One possible shape is the convex hull around two spheres - g_playerShape = new btMultiSphereShape(btVector3(width/2.0, height/2.0, - width/2.0), &spherePositions[0], &sphereRadii[0], 2); - */ - - // Other posibilities - most are too slow, except the sphere - //g_playerShape = new btCylinderShapeZ(btVector3(width, width, height)); - g_playerShape = new btSphereShape(width); - //g_playerShape = new btCapsuleShapeZ(width, height); - - // Create the collision object - g_playerObject = new btCollisionObject (); - g_playerObject->setCollisionShape (g_playerShape); - g_playerObject->setCollisionFlags (btCollisionObject::CF_NO_CONTACT_RESPONSE); - - - // ------- OTHER STUFF ------- - - // Create a custom callback to pick out all the objects colliding - // with the player. We use this in the collision recovery phase. - g_pairCache = new btHashedOverlappingPairCache(); - g_customPairCallback = new CustomOverlappingPairCallback(); - g_broadphase->setOverlappingPairUserCallback(g_customPairCallback); - - // Set up the callback that moves the player at the end of each - // simulation step. - g_dynamicsWorld->setInternalTickCallback(playerStepCallback); - - // Add the character collision object to the world. - g_dynamicsWorld->addCollisionObject(g_playerObject, - MASK_PLAYER, - MASK_STATIC); - - // Make sure these is zero at startup - g_currentMesh = NULL; - - // Start out walking - g_physMode = PHYS_WALK; - - // Success! - return 0; -} - -// Set physics modes -extern "C" void bullet_walk() -{ - g_physMode = PHYS_WALK; - cout << "Walk mode\n"; -} - -extern "C" void bullet_fly() -{ - g_physMode = PHYS_FLY; - cout << "Fly mode\n"; -} - -extern "C" void bullet_ghost() -{ - g_physMode = PHYS_GHOST; - cout << "Ghost mode\n"; -} - -// Switch to the next physics mode -extern "C" void bullet_nextMode() -{ - switch(g_physMode) - { - case PHYS_WALK: - bullet_fly(); - break; - case PHYS_FLY: - bullet_ghost(); - break; - case PHYS_GHOST: - bullet_walk(); - break; - } -} - -// Warp the player to a specific location. We do not bother setting -// rotation, since it's completely irrelevant for collision detection, -// and doubly so since the collision mesh is a sphere. -extern "C" void bullet_movePlayer(float x, float y, float z) -{ - btTransform tr; - tr.setIdentity(); - tr.setOrigin(btVector3(x,y,z)); - g_playerObject->setWorldTransform(tr); -} - -// Request that the player moves in this direction -extern "C" void bullet_setPlayerDir(float x, float y, float z) -{ g_walkDirection.setValue(x,y,z); } - -// Get the current player position, after physics and collision have -// been applied. -extern "C" void bullet_getPlayerPos(float *x, float *y, float *z) -{ - *x = g_playerPosition.getX(); - *y = g_playerPosition.getY(); - *z = g_playerPosition.getZ(); -} - -void* copyBuffer(const void *buf, int elemSize, int len) -{ - int size = elemSize * len; - void *res = malloc(size); - memcpy(res, buf, size); - - return res; -} - -// Internal version that does not copy buffers -void createTriShape(int32_t numFaces, const void *triArray, - int32_t numVerts, const void *vertArray, - const float *trans, const float *matrix) -{ - // This struct holds the index and vertex buffers of a single - // trimesh. - btIndexedMesh im; - - // Set up the triangles - int numTriangles = numFaces / 3; - im.m_numTriangles = numTriangles; - im.m_triangleIndexStride = 6; // 3 indices * 2 bytes per short - im.m_triangleIndexBase = (unsigned char*)triArray; - - // Set up the vertices - im.m_numVertices = numVerts; - im.m_vertexStride = 12; // 4 bytes per float * 3 floats per vertex - im.m_vertexBase = (unsigned char*)vertArray; - - // Transform vertex values in vb according to 'trans' and 'matrix' - float *vb = (float*)im.m_vertexBase; - for(int i=0; iaddIndexedMesh(im, PHY_SHORT); -} - -// Define a cube with coordinates 0,0,0 - 1,1,1. -const float cube_verts[] = - { - 0,0,0, 1,0,0, 0,1,0, - 1,1,0, 0,0,1, 1,0,1, - 0,1,1, 1,1,1 - }; - -// Triangles of the cube. The orientation of each triange doesn't -// matter. -const short cube_tris[] = - { - // bottom side - 0, 1, 2, - 1, 2, 3, - // top side - 4, 5, 6, - 5, 6, 7, - // front side - 0, 4, 5, - 0, 1, 5, - // back side - 2, 3, 7, - 2, 6, 7, - // left side - 0, 2, 4, - 2, 4, 6, - // right side - 1, 3, 5, - 3, 5, 7 - }; - -const int cube_num_verts = 8; -const int cube_num_tris = 12; - -// Create a (trimesh) box with the given dimensions. Used for bounding -// boxes. TODO: I guess we should use the NIF-specified bounding box -// for this, not our automatically calculated one. -extern "C" void bullet_createBoxShape(float xmin, float ymin, float zmin, - float xmax, float ymax, float zmax, - float *trans, float *matrix) -{ - // Make a copy of the vertex buffer, since we need to change it - float *vbuffer = (float*)copyBuffer(cube_verts, 12, cube_num_verts); - - // Calculate the widths - float xwidth = xmax-xmin; - float ywidth = ymax-ymin; - float zwidth = zmax-zmin; - - // Transform the cube to (xmin,xmax) etc - float *vb = vbuffer; - for(int i=0; isetCollisionShape(shape); - obj->setWorldTransform(trafo); - g_dynamicsWorld->addCollisionObject(obj, MASK_STATIC, MASK_PLAYER); -} - -// Move the physics simulation 'delta' seconds forward in time -extern "C" void bullet_timeStep(float delta) -{ - TRACE("bullet_timeStep"); - // TODO: We might experiment with the number of time steps. Remember - // that the function also returns the number of steps performed. - g_dynamicsWorld->stepSimulation(delta,2); -} - -// Cleanup in the reverse order of creation/initialization -extern "C" void bullet_cleanup() -{ - // Remove the rigidbodies from the dynamics world and delete them - for (int i=g_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--) - { - btCollisionObject* obj = g_dynamicsWorld->getCollisionObjectArray()[i]; - btRigidBody* body = btRigidBody::upcast(obj); - - if (body && body->getMotionState()) - delete body->getMotionState(); - - g_dynamicsWorld->removeCollisionObject( obj ); - delete obj; - } - - delete g_dynamicsWorld; - delete g_solver; - delete g_broadphase; - delete g_dispatcher; - delete g_collisionConfiguration; -} diff --git a/old_d_version/bullet/cpp_player.cpp b/old_d_version/bullet/cpp_player.cpp deleted file mode 100644 index 14b04bf84..000000000 --- a/old_d_version/bullet/cpp_player.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - (see additional copyrights for this file below) - - This file (cpp_player.cpp) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - ---- - - Parts of this file is based on the kinematic character controller - demo included with the Bullet library. The copyright statement for - these parts follow: - - Bullet Continuous Collision Detection and Physics Library - Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any - damages arising from the use of this software. Permission is - granted to anyone to use this software for any purpose, including - commercial applications, and to alter it and redistribute it freely, - subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any source - distribution. -*/ - - -// This file handles player-specific physics and collision detection - -// TODO: Later we might handle various physics modes, eg. dynamic -// (full physics), player_walk, player_fall, player_swim, -// player_float, player_levitate, player_ghost. These would be -// applicable to any object (through Monster script), allowing the -// physics code to be shared between NPCs, creatures and the player. - -// Variables used internally in this file. Once we make per-object -// player collision, these will be member variables. -bool g_touchingContact; -btVector3 g_touchingNormal; -btScalar g_currentStepOffset; -float g_stepHeight = 5; - -// Returns the reflection direction of a ray going 'direction' hitting -// a surface with normal 'normal' -btVector3 reflect (const btVector3& direction, const btVector3& normal) -{ return direction - (btScalar(2.0) * direction.dot(normal)) * normal; } - -// Returns the portion of 'direction' that is perpendicular to -// 'normal' -btVector3 perpComponent (const btVector3& direction, const btVector3& normal) -{ return direction - normal * direction.dot(normal); } - -btManifoldArray manifoldArray; - -// Callback used for collision detection sweep tests. It prevents self -// collision and is used in calls to convexSweepTest(). TODO: It might -// be enough to just set the filters on this. If we set the group and -// mask so that we only collide with static objects, self collision -// would never happen. The sweep test function should have had a -// version where you only specify the filters - I might add that -// myself. -class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback -{ -public: - ClosestNotMeConvexResultCallback() - : btCollisionWorld::ClosestConvexResultCallback - (btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) - { - m_collisionFilterGroup = g_playerObject-> - getBroadphaseHandle()->m_collisionFilterGroup; - - m_collisionFilterMask = g_playerObject-> - getBroadphaseHandle()->m_collisionFilterMask; - } - - btScalar addSingleResult(btCollisionWorld::LocalConvexResult& - convexResult, bool normalInWorldSpace) - { - if (convexResult.m_hitCollisionObject == g_playerObject) return 1.0; - - return ClosestConvexResultCallback::addSingleResult - (convexResult, normalInWorldSpace); - } -}; - -// Used to step up small steps and slopes. -void stepUp() -{ - // phase 1: up - btVector3 targetPosition = g_playerPosition + - btVector3(0.0, 0.0, g_stepHeight); - btTransform start, end; - - start.setIdentity (); - end.setIdentity (); - - // FIXME: Handle penetration properly - start.setOrigin (g_playerPosition + btVector3(0.0, 0.1, 0.0)); - end.setOrigin (targetPosition); - - ClosestNotMeConvexResultCallback callback; - g_dynamicsWorld->convexSweepTest (g_playerShape, start, end, callback); - - if (callback.hasHit()) - { - // we moved up only a fraction of the step height - g_currentStepOffset = g_stepHeight * callback.m_closestHitFraction; - g_playerPosition.setInterpolate3(g_playerPosition, targetPosition, - callback.m_closestHitFraction); - } - else - { - g_currentStepOffset = g_stepHeight; - g_playerPosition = targetPosition; - } -} - -void updateTargetPositionBasedOnCollision (const btVector3& hitNormal, - btVector3 &targetPosition) -{ - btVector3 movementDirection = targetPosition - g_playerPosition; - btScalar movementLength = movementDirection.length(); - - if (movementLength <= SIMD_EPSILON) - return; - - // Is this needed? - movementDirection.normalize(); - - btVector3 reflectDir = reflect(movementDirection, hitNormal); - reflectDir.normalize(); - - btVector3 perpendicularDir = perpComponent (reflectDir, hitNormal); - - targetPosition = g_playerPosition; - targetPosition += perpendicularDir * movementLength; -} - -// This covers all normal forward movement and collision, including -// walking sideways when hitting a wall at an angle. It does NOT -// handle walking up slopes and steps, or falling/gravity. -void stepForward(btVector3& walkMove) -{ - btVector3 originalDir = walkMove.normalized(); - - // If no walking direction is given, we still run the function. This - // allows moving forces to push the player around even if she is - // standing still. - if (walkMove.length() < SIMD_EPSILON) - originalDir.setValue(0.f,0.f,0.f); - - btTransform start, end; - btVector3 targetPosition = g_playerPosition + walkMove; - start.setIdentity (); - end.setIdentity (); - - btScalar fraction = 1.0; - btScalar distance2 = (g_playerPosition-targetPosition).length2(); - - if (g_touchingContact) - if (originalDir.dot(g_touchingNormal) > btScalar(0.0)) - updateTargetPositionBasedOnCollision (g_touchingNormal, targetPosition); - - int maxIter = 10; - - while (fraction > btScalar(0.01) && maxIter-- > 0) - { - start.setOrigin (g_playerPosition); - end.setOrigin (targetPosition); - - ClosestNotMeConvexResultCallback callback; - g_dynamicsWorld->convexSweepTest (g_playerShape, start, end, callback); - - fraction -= callback.m_closestHitFraction; - - if (callback.hasHit()) - { - // We moved only a fraction - btScalar hitDistance = (callback.m_hitPointWorld - g_playerPosition).length(); - // If the distance is further than the collision margin, - // move - if (hitDistance > 0.05) - g_playerPosition.setInterpolate3(g_playerPosition, targetPosition, - callback.m_closestHitFraction); - - updateTargetPositionBasedOnCollision(callback.m_hitNormalWorld, - targetPosition); - btVector3 currentDir = targetPosition - g_playerPosition; - distance2 = currentDir.length2(); - - if (distance2 <= SIMD_EPSILON) - break; - - currentDir.normalize(); - - if (currentDir.dot(originalDir) <= btScalar(0.0)) - break; - } - else - // we moved the whole way - g_playerPosition = targetPosition; - } -} - -void stepDown (btScalar dt) -{ - btTransform start, end; - - // phase 3: down - btVector3 step_drop = btVector3(0,0,g_currentStepOffset); - btVector3 gravity_drop = btVector3(0,0,g_stepHeight); - - btVector3 targetPosition = g_playerPosition - step_drop - gravity_drop; - - start.setIdentity (); - end.setIdentity (); - - start.setOrigin (g_playerPosition); - end.setOrigin (targetPosition); - - ClosestNotMeConvexResultCallback callback; - g_dynamicsWorld->convexSweepTest(g_playerShape, start, end, callback); - - if (callback.hasHit()) - // we dropped a fraction of the height -> hit floor - g_playerPosition.setInterpolate3(g_playerPosition, targetPosition, - callback.m_closestHitFraction); - else - // we dropped the full height - g_playerPosition = targetPosition; -} - -// Check if the player currently collides with anything, and adjust -// its position accordingly. Returns true if collisions were found. -bool recoverFromPenetration() -{ - bool penetration = false; - - // Update the collision pair cache - g_dispatcher->dispatchAllCollisionPairs(g_pairCache, - g_dynamicsWorld->getDispatchInfo(), - g_dispatcher); - - btScalar maxPen = 0.0; - for (int i = 0; i < g_pairCache->getNumOverlappingPairs(); i++) - { - manifoldArray.resize(0); - - btBroadphasePair* collisionPair = &g_pairCache->getOverlappingPairArray()[i]; - // Get the contact points - if (collisionPair->m_algorithm) - collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); - - // And handle them - for (int j=0;jgetBody0() == - g_playerObject ? btScalar(-1.0) : btScalar(1.0); - - for (int p=0;pgetNumContacts();p++) - { - const btManifoldPoint &pt = manifold->getContactPoint(p); - - if (pt.getDistance() < 0.0) - { - // Pick out the maximum penetration normal and store - // it - if (pt.getDistance() < maxPen) - { - maxPen = pt.getDistance(); - g_touchingNormal = pt.m_normalWorldOnB * directionSign;//?? - - } - g_playerPosition += pt.m_normalWorldOnB * directionSign * - pt.getDistance() * btScalar(0.2); - - penetration = true; - } - } - } - } - - btTransform newTrans = g_playerObject->getWorldTransform(); - newTrans.setOrigin(g_playerPosition); - g_playerObject->setWorldTransform(newTrans); - - return penetration; -} - -// Callback called at the end of each simulation cycle. This is the -// main function is responsible for player movement. -void playerStepCallback(btDynamicsWorld* dynamicsWorld, btScalar timeStep) -{ - // The walking direction is set from D code each frame, and the - // final player position is read back from D code after the - // simulation. - btVector3 walkStep = g_walkDirection * timeStep; - - float len = walkStep.length(); - - // In walk mode, it shouldn't matter whether or not we look up or - // down. Rotate the vector back to the horizontal plane. - if(g_physMode == PHYS_WALK) - { - walkStep.setZ(0); - float len2 = walkStep.length(); - if(len2 > 0) - walkStep *= len/len2; - } - - // Get the player position - g_playerPosition = g_playerObject->getWorldTransform().getOrigin(); - - if(g_physMode == PHYS_GHOST) - { - // Ghost mode - just move, no collision - g_playerPosition += walkStep; - } - else - { - // Collision detection is active - - // Before moving, recover from current penetrations - int numPenetrationLoops = 0; - g_touchingContact = false; - while (recoverFromPenetration()) - { - numPenetrationLoops++; - g_touchingContact = true; - - // Make sure we don't stay here indefinitely - if (numPenetrationLoops > 4) - break; - } - - // recoverFromPenetration updates g_playerPosition and the - // collision mesh, so they are still in sync at this point - - // Next, do the walk. The following functions only updates - // g_playerPosition, they do not move the collision object. - - if(g_physMode == PHYS_WALK) - { - stepUp(); - stepForward(walkStep); - stepDown(timeStep); - } - else if(g_physMode == PHYS_FLY) - stepForward(walkStep); - else - cout << "WARNING: Unknown physics mode " << g_physMode << "!\n"; - } - - // Move the player collision mesh - btTransform xform = g_playerObject->getWorldTransform (); - xform.setOrigin (g_playerPosition); - g_playerObject->setWorldTransform (xform); -} diff --git a/old_d_version/bullet/cpp_scale.cpp b/old_d_version/bullet/cpp_scale.cpp deleted file mode 100644 index 3dfd34a30..000000000 --- a/old_d_version/bullet/cpp_scale.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (cpp_scale.cpp) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - -*/ - -// WARNING: This file does NOT work, and it is not used yet. - -class ScaleCallback : public btTriangleCallback -{ - btTriangleCallback *call; - float factor; - -public: - ScaleCallback(btTriangleCallback *c, float f) - { call = c; factor = f; } - - void processTriangle(btVector3 *tri, int partid, int triindex) - { - btVector3 vecs[3]; - vecs[0] = tri[0]*factor; - vecs[1] = tri[1]*factor; - vecs[2] = tri[2]*factor; - - call->processTriangle(vecs, partid, triindex); - } -}; - -// This class is used to uniformly scale a triangle mesh by a -// factor. It wraps around an existing shape and does not copy the -// data. -class ScaleShape : public btConcaveShape -{ - btConcaveShape* child; - float factor, fact3, facthalf; - -public: - - ScaleShape(btConcaveShape* ch, float ft) - { - child = ch; - factor = ft; - fact3 = factor*factor*factor; - facthalf = factor*0.5; - } - - void calculateLocalInertia(btScalar mass,btVector3& inertia) const - { - btVector3 tmpInertia; - child->calculateLocalInertia(mass,tmpInertia); - inertia = tmpInertia * fact3; - } - - const char* getName()const { return "ScaleShape"; } - - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const - { - child->getAabb(t,aabbMin,aabbMax); - btVector3 aabbCenter = (aabbMax+aabbMin)*0.5; - btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*facthalf; - - aabbMin = aabbCenter - scaledAabbHalfExtends; - aabbMax = aabbCenter + scaledAabbHalfExtends; - } - - void processAllTriangles(btTriangleCallback *callback,const btVector3& aabbMin,const btVector3& aabbMax) const - { - ScaleCallback scb(callback, factor); - - child->processAllTriangles(&scb, aabbMin, aabbMax); - } - - void setLocalScaling(const btVector3& scaling) - { child->setLocalScaling(scaling); } - - const btVector3& getLocalScaling() const - { return child->getLocalScaling(); } - - int getShapeType() const - { return TRIANGLE_MESH_SHAPE_PROXYTYPE; } -}; diff --git a/old_d_version/core/config.d b/old_d_version/core/config.d deleted file mode 100644 index 55daa2be1..000000000 --- a/old_d_version/core/config.d +++ /dev/null @@ -1,437 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (config.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module core.config; - -import std.string; -import std.file; -import std.path; -import std.stdio; - -import monster.monster; -import monster.util.string; - -import core.inifile; -import core.filefinder; - -import sound.audio; - -import input.keys; -import input.ois; - -import ogre.ogre; - -ConfigManager config; - -/* - * Structure that handles all user adjustable configuration options, - * including things like file paths, plugins, graphics resolution, - * game settings, window positions, etc. It is also responsible for - * reading and writing configuration files, for importing settings - * from Morrowind.ini and for configuring OGRE. It doesn't currently - * DO all of this, but it is supposed to in the future. - */ - -struct ConfigManager -{ - MonsterObject *mo; - - IniWriter iniWriter; - - // Mouse sensitivity - float *mouseSensX; - float *mouseSensY; - bool *flipMouseY; - - // Ogre configuration - bool showOgreConfig; // The configuration setting - // The actual result, overridable by a command line switch, and also - // set to true if firstRun is true. - bool finalOgreConfig; - - // Other settings - bool firstRun; - - // Set to true if sound is completely disabled - bool noSound = false; - - // Number of current screen shot. Saved upon exit, so that shots - // from separate sessions don't overwrite each other. - int screenShotNum; - - // Game files to load (max 255) - char[][] gameFiles; - - // Directories - char[] dataDir; - char[] esmDir; - char[] bsaDir; - char[] sndDir; - char[] fontDir; - char[] musDir; // Explore music - char[] musDir2; // Battle music - - // Configuration file - char[] confFile = "openmw.ini"; - - // Cell to load at startup - char[] defaultCell; - - // These set the volume to a new value and updates all sounds to - // take notice. - void setMusicVolume(float vol) - { - stack.pushFloat(vol); - mo.call("setMusicVolume"); - } - float getMusicVolume() - { return mo.getFloat("musicVolume"); } - - void setSfxVolume(float vol) - { - stack.pushFloat(vol); - mo.call("setSfxVolume"); - } - float getSfxVolume() - { return mo.getFloat("sfxVolume"); } - - void setMainVolume(float vol) - { - stack.pushFloat(vol); - mo.call("setMainVolume"); - } - float getMainVolume() - { return mo.getFloat("mainVolume"); } - - // Initialize the config manager. Send a 'true' parameter to reset - // all keybindings to the default. A lot of this stuff will be moved - // to script code at some point. In general, all input mechanics and - // distribution of key events should happen in native code, while - // all setup and control should be handled in script code. - void initialize(bool reset = false) - { - // Initialize variables from Monster. - assert(mo !is null); - mouseSensX = mo.getFloatPtr("mouseSensX"); - mouseSensY = mo.getFloatPtr("mouseSensY"); - flipMouseY = mo.getBoolPtr("flipMouseY"); - - // Initialize the key binding manager - keyBindings.initKeys(); - - /* Disable this at the moment. It's a good idea to put - configuration in a central location, but it's useless as long - as Ogre expects to find it's files in the current working - directory. The best permanent solution would be to let the - locations of ogre.cfg and plugins.cfg be determined by - openmw.ini - I will fix that later. - - version(Posix) - { - if(!exists(confFile)) - confFile = expandTilde("~/.openmw/openmw.ini"); - } - */ - - readIni(reset); - } - - // Read config from morro.ini, if it exists. The reset parameter is - // set to true if we should use default key bindings instead of the - // ones from the config file. - void readIni(bool reset) - { - // Read configuration file, if it exists. - IniReader ini; - - ini.readFile(confFile); - - screenShotNum = ini.getInt("General", "Screenshots", 0); - float mainVolume = saneVol(ini.getFloat("Sound", "Main Volume", 0.7)); - float musicVolume = saneVol(ini.getFloat("Sound", "Music Volume", 0.5)); - float sfxVolume = saneVol(ini.getFloat("Sound", "SFX Volume", 0.5)); - bool useMusic = ini.getBool("Sound", "Enable Music", true); - - - lightConst = ini.getInt("LightAttenuation", "UseConstant", 0); - lightConstValue = ini.getFloat("LightAttenuation", "ConstantValue", 0.0); - - lightLinear = ini.getInt("LightAttenuation", "UseLinear", 1); - lightLinearMethod = ini.getInt("LightAttenuation", "LinearMethod", 1); - lightLinearValue = ini.getFloat("LightAttenuation", "LinearValue", 3.0); - lightLinearRadiusMult = ini.getFloat("LightAttenuation", "LinearRadiusMult", 1.0); - - lightQuadratic = ini.getInt("LightAttenuation", "UseQuadratic", 0); - lightQuadraticMethod = ini.getInt("LightAttenuation", "QuadraticMethod", 2); - lightQuadraticValue = ini.getFloat("LightAttenuation", "QuadraticValue", 16.0); - lightQuadraticRadiusMult = ini.getFloat("LightAttenuation", "QuadraticRadiusMult", 1.0); - - lightOutQuadInLin = ini.getInt("LightAttenuation", "OutQuadInLin", 0); - - - *mouseSensX = ini.getFloat("Controls", "Mouse Sensitivity X", 0.2); - *mouseSensY = ini.getFloat("Controls", "Mouse Sensitivity Y", 0.2); - *flipMouseY = ini.getBool("Controls", "Flip Mouse Y Axis", false); - - mo.setFloat("mainVolume", mainVolume); - mo.setFloat("musicVolume", musicVolume); - mo.setFloat("sfxVolume", sfxVolume); - mo.setBool("useMusic", useMusic); - - defaultCell = ini.getString("General", "Default Cell", "Assu"); - - firstRun = ini.getBool("General", "First Run", true); - showOgreConfig = ini.getBool("General", "Show Ogre Config", false); - - // This flag determines whether we will actually show the Ogre - // config dialogue. The EITHER of the following are true, the - // config box will be shown: - // - The program is being run for the first time - // - The "Show Ogre Config" option in openmw.ini is set. - // - The -oc option is specified on the command line - // - The file ogre.cfg is missing - - finalOgreConfig = showOgreConfig || firstRun || - !exists("ogre.cfg"); - - // Set default key bindings first. - with(keyBindings) - { - // Bind some default keys - bind(Keys.MoveLeft, KC.A, KC.LEFT); - bind(Keys.MoveRight, KC.D, KC.RIGHT); - bind(Keys.MoveForward, KC.W, KC.UP); - bind(Keys.MoveBackward, KC.S, KC.DOWN); - bind(Keys.MoveUp, KC.LSHIFT); - bind(Keys.MoveDown, KC.LCONTROL); - - bind(Keys.MainVolUp, KC.ADD); - bind(Keys.MainVolDown, KC.SUBTRACT); - bind(Keys.MusVolDown, KC.N1); - bind(Keys.MusVolUp, KC.N2); - bind(Keys.SfxVolDown, KC.N3); - bind(Keys.SfxVolUp, KC.N4); - bind(Keys.Mute, KC.M); - - bind(Keys.Fullscreen, KC.F); - - bind(Keys.ToggleBattleMusic, KC.SPACE); - bind(Keys.PhysMode, KC.T); - bind(Keys.Nighteye, KC.N); - bind(Keys.ToggleGui, KC.Mouse1); - bind(Keys.Console, KC.F1, KC.GRAVE); - bind(Keys.Debug, KC.G); - - bind(Keys.Pause, KC.PAUSE, KC.P); - bind(Keys.ScreenShot, KC.SYSRQ); - bind(Keys.Exit, KC.Q, KC.ESCAPE); - } - - // Unless the ini file was missing or we were asked to reset all - // keybindings to default, replace all present bindings with the - // values from the ini. - if(!reset && ini.wasRead) - { - // Read key bindings - for(int i; i - WWW: http://openmw.snaptoad.com/ - - This file (filefinder.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module core.filefinder; - -import std.file; -import std.string; - -import monster.util.string; -import monster.util.aa; - -import core.memory; - -import std.stdio; - -class FileFinderException : Exception -{ - this(char[] msg, char[] ext, char[] dir) - { - if(ext.length) super(format("FileFinder for %s files in %s: %s", ext, dir, msg)); - else super(format("FileFinder for %s: %s", dir, msg)); - } -} - -// Do we traverse directories recursively? Default is yes. -enum Recurse { Yes, No } - -// The file finder is used to list all files in a directory so we can -// look up files without searching the filesystem each time. It is -// case insensitive on all platforms, and transparently converts to -// the right directory separator character (\ or /). We might extend -// it later with code from other projects. -class FileFinder -{ - private: - char[][] files; // Use GC for this, it's not too big and we don't - // have to manage roots pointing to the filenames. - HashTable!(char[], int, ESMRegionAlloc, FilenameHasher) lookup; - - char[] dir; // Base directory to search - char[] ext; // Extensions to pick out - - void fail(char[] err) - { - throw new FileFinderException(err, ext, dir); - } - - // Removes the part of a path that is stored in 'dir' - char[] removeDir(char[] path) - { - //TODO: Should this be case insensitive? - assert(path[0..dir.length] == dir); - - return path[dir.length..$]; - } - - void insert(char[] filename) - { - // Only keep the part of the filename not given in 'dir'. - char[] name = removeDir(filename); - - if(!name.iEnds(ext)) return; - - // We start counting from 1 - uint newVal = files.length+1; - - // Insert it, or get the old value if it already exists - uint oldVal = lookup[name, newVal]; - if(oldVal != newVal) - fail("Already have " ~ name ~ "\nPreviously inserted as " ~ files[oldVal-1]); - - // Store it - files ~= filename; - } - - public: - - static char[] addSlash(char[] dir) - { - // Add a trailing slash - version(Windows) if(!dir.ends("\\")) dir ~= '\\'; - version(Posix) if(!dir.ends("/")) dir ~= '/'; - return dir; - } - - int length() { return lookup.length; } - - this(char[] dir, char[] ext = null, Recurse r = Recurse.Yes) - in - { - if(!dir.length) fail("'dir' can not be empty"); - } - out - { - assert(files.length == lookup.length); - } - body - { - // Add a trailing slash - dir = addSlash(dir); - - this.dir = dir; - - if(ext.length && ext[0] != '.') ext = "." ~ ext; - this.ext = ext; - - bool callback(DirEntry* de) - { - if (de.isdir) - { - if(r == Recurse.Yes) - listdir(de.name, &callback); - } - else - insert(de.name); - return true; - } - - try listdir(dir, &callback); - catch(FileException e) - fail(e.toString); - } - - char[] opIndex(int i) { return files[i-1]; } - - int opIndex(char[] file) - { - int i; - - // Get value if it exists - if(lookup.inList(file, i)) - return i; - return 0; - } - - bool has(char[] file) - { - return lookup.inList(file); - } - - int opApply(int delegate(ref char[]) del) - { - int res = 0; - - foreach(char[] s; files) - { - char[] tmp = removeDir(s); - res = del(tmp); - if(res) break; - } - return res; - } - - char[] toString() - { - char[] result; - foreach(char[] s; this) - result ~= s ~ "\n"; - return result; - } -} - -// Hash functions that does not differentiate between linux and -// windows file names. This means that it is case insensitive, and -// treats '\' and '/' as the same character. Only needed in linux, in -// windows just use CITextHasher. -version(Posix) -struct FilenameHasher -{ - static const char conv = 'a'-'A'; - - static int isEqual(char[] aa, char[] bb) - { - if(aa.length != bb.length) return 0; - - foreach(int i, char a; aa) - { - char b = bb[i]; - - if(a == b) - continue; - - // Convert both to lowercase and "/ case" - if(a <= 'Z' && a >= 'A') a += conv; - else if(a == '\\') a = '/'; - if(b <= 'Z' && b >= 'A') b += conv; - else if(b == '\\') b = '/'; - - if(a != b) return 0; - } - - // No differences were found - return 1; - } - - static uint hash(char[] s) - { - uint hash; - foreach (char c; s) - { - if(c <= 'Z' && c >= 'A') c += conv; - else if(c == '\\') c = '/'; - hash = (hash * 37) + c; - } - return hash; - } -} - -version(Windows) alias CITextHash FilenameHasher; diff --git a/old_d_version/esm/defs.d b/old_d_version/esm/defs.d deleted file mode 100644 index 337db02fc..000000000 --- a/old_d_version/esm/defs.d +++ /dev/null @@ -1,187 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (defs.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module esm.defs; - -public import std.string; -public import monster.util.string; -import monster.monster; - -/* - * Types and definitions related to parsing esm and esp files - */ - -alias char[4] NAME; -alias char[32] NAME32; -alias char[256] NAME256; - -union Color -{ - align(1) struct - { - ubyte red, green, blue, alpha; - } - - ubyte[4] array; - uint value; - - char[] toString() { return format("RGBA:%s", array); } -} -static assert(Color.sizeof==4); - -// State of a record struct -enum LoadState - { - Unloaded, // This record is not loaded, it has just been - // referenced. - Loaded, // This record has been loaded by the current file - Previous // The record has been loaded by a previous file - - // Finalized - might be the case for some record types, but I - // don't know if this actual state value would be used for - // anything. - } - -enum VarType { Unknown, None, Short, Int, Long, Float, String, Ignored } - -enum SpellSchool : int - { - Alteration = 0, - Conjuration = 1, - Destruction = 2, - Illusion = 3, - Mysticism = 4, - Restoration = 5, - Length - } - -enum Attribute : int - { - Strength = 0, - Intelligence = 1, - Willpower = 2, - Agility = 3, - Speed = 4, - Endurance = 5, - Personality = 6, - Luck = 7, - Length - } - -enum SkillEnum : int - { - Block = 0, - Armorer = 1, - MediumArmor = 2, - HeavyArmor = 3, - BluntWeapon = 4, - LongBlade = 5, - Axe = 6, - Spear = 7, - Athletics = 8, - Enchant = 9, - Destruction = 10, - Alteration = 11, - Illusion = 12, - Conjuration = 13, - Mysticism = 14, - Restoration = 15, - Alchemy = 16, - Unarmored = 17, - Security = 18, - Sneak = 19, - Acrobatics = 20, - LightArmor = 21, - ShortBlade = 22, - Marksman = 23, - Mercantile = 24, - Speechcraft = 25, - HandToHand = 26, - Length - } - -// Shared between SPEL (Spells), ALCH (Potions) and ENCH (Item -// enchantments) records -align(1) struct ENAMstruct -{ - // Magical effect - short effectID; // ID of magic effect - - // Which skills/attributes are affected (for restore/drain spells etc.) - byte skill, attribute; // -1 if N/A - - // Other spell parameters - int range; // 0 - self, 1 - touch, 2 - target - int area, duration, magnMin, magnMax; - - static assert(ENAMstruct.sizeof==24); -} - -// Common stuff for all the load* structs -template LoadTT(T) -{ - LoadState state; - char[] name, id; - - MonsterObject *proto; - static MonsterClass mc; - - void makeProto(char[] clsName = null) - { - // Set up a prototype object - if(mc is null) - { - // Use the template type name as the Monster class name if - // none is specified. - if(clsName == "") - { - clsName = typeid(T).toString; - - // Remove the module name - int i = clsName.rfind('.'); - if(i != -1) - clsName = clsName[i+1..$]; - } - - // All the game objects are in the 'game' package - clsName = "game." ~ clsName; - mc = vm.load(clsName); - } - - proto = mc.createObject(); - - proto.setString8("id", id); - proto.setString8("name", name); - - static if(is(typeof(data.weight) == float)) - { - proto.setFloat("weight", data.weight); - proto.setInt("value", data.value); - } - - static if(is(typeof(data.enchant)==int)) - proto.setInt("enchant", data.enchant); - } -} - -template LoadT() { mixin LoadTT!(typeof(*this)); } diff --git a/old_d_version/esm/esmmain.d b/old_d_version/esm/esmmain.d deleted file mode 100644 index 2340ea59e..000000000 --- a/old_d_version/esm/esmmain.d +++ /dev/null @@ -1,167 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (esmmain.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module esm.esmmain; - -public import esm.records; - -import ogre.ogre; - -/* This file is the main module for loading from ESM, ESP and ESS - files. It stores all the data in the appropriate data structures - for later referal. TODO: Put this in a class or whatever? Nah, we - definately only need one structure like this at any one - time. However, we have to deal with unloading and reloading it, - even though that should be the exceptional case (change of plugins, - etc), not the rule (loading a savegame should not alter the base - data set, I think, but it's to early do decide.)*/ - -// Load a set of esm and esp files. For now, we just traverse in the -// order given. Later, we should sort these into 'masters' and -// 'plugins', because esms are always supposed to be loaded -// first. TODO: I'm not sure if I should load all these in one -// function. Do we need to be able to respond to errors in each file? -// Nah, if anything fails, give a general error message, remove the -// file from the list and try again. We have to be able to get a list -// of which files depend upon which, though... this can be done before -// this function is called. -void loadTESFiles(char[][] files) -{ - // Set up all the lists to hold our data - initializeLists(); - - foreach(char[] filename; files) - { - esFile.open(filename, esmRegion); - while(esFile.hasMoreRecs()) - { - uint flags; - - // Read record header - char[] recName = esFile.getRecName(); - esFile.getRecHeader(flags); - - if(flags & RecordFlags.Unknown) - esFile.fail(format("UNKNOWN record flags: %xh", flags)); - - loadRecord(recName); - } - - // We have to loop through the lists and check for broken - // references at this point, and if all forward references were - // loaded. There might be other end-of-file things to do also. - endFiles(); - } - - esFile.close(); - - // Put all inventory items into one list - items.addList(appas, ItemType.Apparatus); - items.addList(lockpicks, ItemType.Pick); - items.addList(probes, ItemType.Probe); - items.addList(repairs, ItemType.Repair); - items.addList(lights, ItemType.Light); - items.addList(ingreds, ItemType.Ingredient); - items.addList(potions, ItemType.Potion); - items.addList(armors, ItemType.Armor); - items.addList(weapons, ItemType.Weapon); - items.addList(books, ItemType.Book); - items.addList(clothes, ItemType.Clothing); - items.addList(miscItems, ItemType.Misc); - items.addList(itemLists, ItemType.ItemList); // Leveled item lists - - // Same with all actors - actors.addList(creatures, ItemType.Creature); - actors.addList(creatureLists, ItemType.CreatureList); - actors.addList(npcs, ItemType.NPC); - - // Finally, add everything that might be looked up in a cell into - // one list - cellRefs.addList(items); - cellRefs.addList(actors); - cellRefs.addList(doors, ItemType.Door); - cellRefs.addList(activators, ItemType.Activator); - cellRefs.addList(statics, ItemType.Static); - cellRefs.addList(containers, ItemType.Container); - - // Check that all references are resolved - items.endMerge(); - actors.endMerge(); - cellRefs.endMerge(); - - // Put all NPC dialogues into the hyperlink list - foreach(char[] id, ref Dialogue dl; dialogues.names) - hyperlinks.add(id, &dl); - - // Finally, sort the hyperlink lists - hyperlinks.sort(); -} - -// Contains the small bits of information that we currently extract -// from savegames. -struct PlayerSaveInfo -{ - char[] cellName; - char[] playerName; - Placement pos; -} - -// Load a TES savegame file (.ess). Currently VERY limited, reads the -// player's cell name and position -PlayerSaveInfo importSavegame(char[] file) -{ - PlayerSaveInfo pi; - - esFile.open(file, esmRegion); - scope(exit) esFile.close(); - - if(esFile.getFileType != FileType.Ess) - throw new TES3FileException(file ~ " is not a savegame"); - - with(esFile.saveData) - { - pi.cellName = stripz(cell); - pi.playerName = stripz(player); - } - - with(esFile) - { - while(hasMoreRecs()) - { - if(isNextHRec("REFR")) - { - while(hasMoreSubs()) - { - getSubName(); - if(retSubName() == "DATA") - readHExact(&pi.pos, pi.pos.sizeof); - else - skipHSub(); - } - } - else - skipHRecord(); - } - } - return pi; -} diff --git a/old_d_version/esm/filereader.d b/old_d_version/esm/filereader.d deleted file mode 100644 index 4d1dfb2d9..000000000 --- a/old_d_version/esm/filereader.d +++ /dev/null @@ -1,783 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (filereader.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module esm.filereader; - -private: -import std.stdio; -import std.stream; -import std.string; - -import util.regions; -import util.utfconvert; -import monster.util.string; -import core.resource; - -import esm.listkeeper; -import esm.defs; - -public: - -/* - * Exception class for TES3File - */ - -class TES3FileException: Exception -{ - this(char[] msg) {super("Error reading TES3 file: " ~ msg);} - this() {this("Unknown error");} -} - -// Some flags are in use that we don't know. But we don't really know -// any of them. -enum RecordFlags : uint - { - Flag6 = 0x20, // Eg. adventurers_v2.0.esp (only once per file?) - Persistent = 0x400, - Flag13 = 0x1000, // Eg. Astarsis_BR.esm (several times per file?) - Blocked = 0x2000, - - Unknown = 0xffffffff - 0x3420 - } - -enum FileType - { - Unknown, - Esp, Plugin = Esp, - Esm, Master = Esm, - Ess, Savegame = Ess - } - -// Special files -enum SpecialFile - { - Other, - Morrowind, - Tribunal, - Bloodmoon - } - -enum Version { Unknown, v12, v13 } - -// This struct should contain enough data to put a TES3File object -// back into a specific file position and state. We use it to save the -// "position" of objects in a file (eg. a cell), so we can return -// there later and continue where we stopped (eg. when we want to load -// that specific cell.) -struct TES3FileContext -{ - char[] filename; - uint leftRec, leftSub; - ulong leftFile; - NAME recName, subName; - FileType type; - Version ver; - - ulong filepos; -} - -/** - * Instance used to read TES3 files. Since we will only be reading one - * file at a time, we might as well make one global instance. - */ -TES3File esFile; - -/** - * This struct reads an Elder Scrolls 3 file (esp, esm or ess) - * - * Makes heavy use of private variables to represent current - * state. - * - * Relevant exceptions are - * TES3FileException - error interpreting file - * StreamFileException - file IO error - */ -struct TES3File -{ - private: - BufferedFile file;// Input file - - // These are only used by getRecHeader and getSubHeader for - // asserting the file's integrity. - ulong leftFile; // Number of unread bytes in file - uint leftRec; // Number of unread bytes in record - - // This is used by sub-record readers for integrity checking. - uint leftSub; // Number of bytes in subrecord - - // Name of current record and current sub-record. - NAME recName, subName; - - char[] filename; // Filename - FileType type; // File type - Version ver; // File format version - char[] author; // File author (max 32 bytes (with null?)) - char[] desc; // Description (max 256 bytes (ditto?)) - uint records; // Number of records in the file (doesn't seem to be right?) - SpecialFile spf; // Is this a file we have to treat in a special way? - - struct _mast - { - char[] name; // File name of an esm master for this file - ulong size; // The master file's size in bytes (used for - // version control) - } - - // List of esm masters for this file. For savegames this list also - // contains all plugins. - _mast masters[]; - - - // TES3.HEDR, file header struct - align(1) struct HEDRstruct - { - union - { - float ver; // File format version, 1.2 and 1.3 supported. - uint verHex; // 1.2 = 0x3f99999a, 1.3 = 0x3fa66666 - } - int type; // 0=esp, 1=esm, 32=ess - NAME32 author; // Author's name - NAME256 desc; // File description blurb - uint records; // Number of records in file (?) - } - - static assert(HEDRstruct.sizeof == 300); - - // Which memory region to use for allocations. - RegionManager region; - - public: - - // A struct found in the headers of savegame files. Contains quick - // information to get us going, like the cell name and the player - // name. - struct _saveData - { - float[6] unknown; - char[64] cell; // Cell name - float unk2; // Unknown value - char[32] player; // Player name - } - static assert(_saveData.sizeof == 124); - _saveData saveData; - - // Get file information - char[] getFilename() { return filename; } - ulong getFileSize() { return file.size; } - ulong getPosition() { return file.position; } - SpecialFile getSpecial() { return spf; } - - char[] retSubName() { return subName; } - - bool isVer12() { return ver == Version.v12;} - bool isVer13() { return ver == Version.v13;} - FileType getFileType() { return type; } - _mast[] getMasters() { return masters; } - uint getRecords() { return records; } - char[] getAuthor() { return author; } - RegionManager getRegion() { return region; } - - // Store the current file state (position, file name, version, debug - // info). The info should be enough to get us back on track for - // reading from a file, without having to reread the header or any - // previous records. - void getContext(ref TES3FileContext c) - { - c.filename = filename; - c.leftFile = leftFile; - c.leftRec = leftRec; - c.leftSub = leftSub; - c.recName[] = recName; - c.subName[] = subName; - c.type = type; - c.ver = ver; - c.filepos = file.position; - } - - // Opens the file if it is not already opened. A region manager has - // to be specified. - void restoreContext(TES3FileContext c, RegionManager r) - { - if(filename != c.filename) - openFile(c.filename, r); - file.seekSet(cast(long)c.filepos); - - // File is now open, copy state information - filename = c.filename; - leftFile = c.leftFile; - leftRec = c.leftRec; - leftSub = c.leftSub; - recName[] = c.recName; - subName[] = c.subName; - type = c.type; - ver = c.ver; - } - - // Open a new file and assign a region - private void openFile(char[] filename, RegionManager r) - { - close(); - debug writefln("Opening file"); - if(file is null) file = new BufferedFile(new File()); - file.open(filename); - - region = r; - } - - void open(char[] filename, RegionManager r) - { - uint flags; - - debug writefln("openFile(%s, %s)", filename, r); - openFile(filename, r); - - if(iEnds(filename, "Morrowind.esm")) spf = SpecialFile.Morrowind; - else if(iEnds(filename, "Tribunal.esm")) spf = SpecialFile.Tribunal; - else if(iEnds(filename, "Bloodmoon.esm")) spf = SpecialFile.Bloodmoon; - else spf = SpecialFile.Other; - - debug writefln("Reading header"); - - // Do NOT .dup this filename, since it is referenced outside the - // GC's reach and might be deleted. - this.filename = filename; - - leftFile = file.size; - - // First things first - if(getRecName() != "TES3") - fail("Not a valid Morrowind file"); - - // Record header - getRecHeader(flags); - if(flags) - writefln("WARNING: Header flags are non-zero"); - - // Read and analyse the header data - HEDRstruct hedr; - readHNExact(&hedr, hedr.sizeof, "HEDR"); - - // The float hedr.ver signifies the file format version. It can - // take on these two values: - // 0x3f99999a = 1.2 - // 0x3fa66666 = 1.3 - if( hedr.verHex == 0x3f99999a ) - ver = Version.v12; - else if( hedr.verHex == 0x3fa66666 ) - ver = Version.v13; - else - { - ver = Version.Unknown; - writefln("WARNING: Unknown version: ", hedr.ver); - writefln(" Hex: %X h", *(cast(uint*)&hedr.ver)); - } - - switch(hedr.type) - { - case 0: type = FileType.Esp; break; - case 1: type = FileType.Esm; break; - case 32: type = FileType.Ess; break; - default: - type = FileType.Unknown; - writefln("WARNING: Unknown file type: ", hedr.type); - } - - author = region.copy(stripz(hedr.author)); - desc = region.copy(stripz(hedr.desc)); - records = hedr.records; - - masters = null; - // Reads a MAST and a DATA fields - while(isNextSub("MAST")) - { - _mast ma; - - // MAST entry - master file name - ma.name = getHString(); - - // DATA entry - master file size - ma.size = getHNUlong("DATA"); - - // Add to the master list! - masters ~= ma; - } - - if(type == FileType.Savegame) - { - // Savegame-related data - - // Cell name, player name and player position - readHNExact(&saveData, 124, "GMDT"); - - // Contains eg. 0xff0000, 0xff00, 0xff, 0x0, 0x20. No idea. - getSubNameIs("SCRD"); - skipHSubSize(20); - - // Screenshot. Fits with 128x128x4 bytes - getSubNameIs("SCRS"); - skipHSubSize(65536); - } - } - - // Close the file. We do not clear any object data at this point. - void close() - { - debug writefln("close()"); - if(file !is null) - file.close(); - leftFile = leftRec = leftSub = 0; - debug writefln("Clearing strings"); - - recName[] = '\0'; - subName[] = '\0'; - - // This tells restoreContext() that we have to reopen the file - filename = null; - - debug writefln("exit close()"); - } - - /* - * Error reporting - */ - - void fail(char[] msg) - { - throw new TES3FileException - (msg ~ "\nFile: " ~ filename ~ "\nRecord name: " ~ recName - ~ "\nSubrecord name: " ~ subName); - } - - /************************************************************************ - * - * Highest level readers, reads a name and looks it up in the given - * list. - * - ************************************************************************/ - - // This should be more than big enough for references. - private char lookupBuffer[200]; - - // Get a temporary string. This is faster and more memory efficient - // that the other string functions (because it is allocation free), - // but the returned string is only valid until tmpHString() is - // called again. - char[] tmpHString() - { - getSubHeader(); - assert(leftSub <= lookupBuffer.length, "lookupBuffer wasn't large enough"); - - // Use this to test the difference in memory consumption. - return getString(lookupBuffer[0..leftSub]); - } - - // These are used for file lookups - MeshIndex getMesh() - { getSubNameIs("MODL"); return resources.lookupMesh(tmpHString()); } - SoundIndex getSound() - { getSubNameIs("FNAM"); return resources.lookupSound(tmpHString()); } - IconIndex getIcon(char[] s = "ITEX") - { getSubNameIs(s); return resources.lookupIcon(tmpHString()); } - TextureIndex getTexture() - { getSubNameIs("DATA"); return resources.lookupTexture(tmpHString()); } - - // The getO* functions read optional records. If they are not - // present, return null. - - MeshIndex getOMesh() - { return isNextSub("MODL") ? resources.lookupMesh(tmpHString()) : MeshIndex.init; } - /* - SoundIndex getOSound() - { return isNextSub("FNAM") ? resources.lookupSound(tmpHString()) : SoundIndex.init; } - */ - IconIndex getOIcon() - { return isNextSub("ITEX") ? resources.lookupIcon(tmpHString()) : IconIndex.init; } - TextureIndex getOTexture(char[] s="TNAM") - { return isNextSub(s) ? resources.lookupTexture(tmpHString()) : TextureIndex.init; } - - // Reference with name s - template getHNPtr(Type) - { - Type* getHNPtr(char[] s, ListKeeper list) - { getSubNameIs(s); return cast(Type*) list.lookup(tmpHString()); } - } - - // Reference, only get header - template getHPtr(Type) - { - Type* getHPtr(ListKeeper list) - { return cast(Type*) list.lookup(tmpHString()); } - } - - // Optional reference with name s - template getHNOPtr(Type) - { - Type* getHNOPtr(char[] s, ListKeeper list) - { return isNextSub(s) ? cast(Type*)list.lookup(tmpHString()) : null; } - } - - /************************************************************************ - * - * Somewhat high level reading methods. Knows about headers and - * leftFile/leftRec/leftSub. - * - ************************************************************************/ - - // "Automatic" versions. Sets and returns recName and subName and - // updates leftFile/leftRec. - char[] getRecName() - { - if(!hasMoreRecs()) - fail("No more records, getRecName() failed"); - getName(recName); - leftFile-= 4; - return recName; - } - - // This is specially optimized for LoadINFO - bool isEmptyOrGetName() - { - if(leftRec) - { - file.readBlock(subName.ptr, 4); - leftRec -= 4; - return false; - } - return true; - } - - // I've tried to optimize this slightly, since it gets called a LOT. - void getSubName() - { - if(leftRec <= 0) - fail("No more sub-records, getSubName() failed"); - - // Don't bother with error checking, we will catch an EOF upon - // reading the subrecord data anyway. - file.readBlock(subName.ptr, 4); - - leftRec -= 4; - } - - // We often expect a certain subrecord type, this makes it easy to - // check. - void getSubNameIs(char[] s) - { - getSubName(); - if( subName != s ) - fail("Expected subrecord "~s~" but got "~subName); - } - - // Checks if the next sub-record is called s. If it is, run - // getSubName, if not, return false. - bool isNextSub(char[] s) - { - if(!leftRec) return false; - - getName(subName); - if(subName != s) - { - file.seekCur(-4); - return false; - } - leftRec -= 4; - - //getSubName(); - return true; - } - - // Same as isNextSub, only it works on records instead of - // sub-records. It also loads the record header. - bool isNextHRec(char[] s) - { - if(!leftFile) return false; - getName(recName); - if(recName != s) - { - file.seekCur(-4); - return false; - } - leftFile -= 4; - - uint flags; - getRecHeader(flags); - - return true; - } - - bool hasMoreSubs() { return leftRec > 0; } - bool hasMoreRecs() { return leftFile > 0; } - - // Remaining size of current record - uint getRecLeft() { return leftRec; } - // Size of current sub record - uint getSubSize() { return leftSub; } - - // Skip the rest of this record. Assumes the name and header have - // already been read - void skipRecord() - { - file.seekCur(leftRec); - leftRec = 0; - } - - // Skip an entire record - void skipHRecord() - { - if(!leftFile) return; - - uint flags; - - getRecName(); - getRecHeader(flags); - skipRecord(); - } - - // Skip current sub record and return size - uint skipHSub() - { - getSubHeader(); - file.seekCur(leftSub); - return leftSub; - } - - // Skip sub record and check it's size - void skipHSubSize(uint size) - { - getSubHeader(); - if(leftSub != size) - fail(format("Size mismatch: got %d, wanted %d", leftSub, size)); - file.seekCur(leftSub); - } - - // Check the name and size before skipping - void skipHNSub(char[] name, uint size) - { - getSubNameIs(name); - skipHSubSize(size); - } - - // These read an entire sub-record, including the header. They also - // adjust and check leftSub and leftRecord variables through calling - // getSubHeader(). - void readHExact(void * p, uint size) - { - getSubHeader(); - if(leftSub != size) - fail(format("Size mismatch: got %d, wanted %d", leftSub, size)); - readExact(p, leftSub); - } - - template TgetHType(T) - { T TgetHType() { T t; readHExact(&t, t.sizeof); return t;} } - - // To make these easier to use (and to further distinguish them from - // the above "raw" versions), these return their value instead of - // using an ref argument. - alias TgetHType!(uint) getHUint; - alias TgetHType!(int) getHInt; - alias TgetHType!(float) getHFloat; - alias TgetHType!(ulong) getHUlong; - alias TgetHType!(byte) getHByte; - - // Reads a string sub-record, including header - char[] getHString() - { - getSubHeader(); - - // Hack to make MultiMark.esp load. Zero-length strings do not - // occur in any of the official mods, but MultiMark makes use of - // them. For some reason, they break the rules, and contain a - // byte (value 0) even if the header says there is no data. If - // Morrowind accepts it, so should we. - if(leftSub == 0) - { - // Skip the following zero byte - leftRec--; - assert(file.getc() == 0); - // TODO: Report this by setting a flag or something? - return null; - } - - return getString(region.getString(leftSub)); - } - - // Other quick aliases (this is starting to get messy) - // Get string sub record string with name s - char[] getHNString(char[] s) - { getSubNameIs(s); return getHString(); } - - // Get optional sub record string with name s - char[] getHNOString(char[] s) - { return isNextSub(s) ? getHString() : null; } - - template TgetHNType(T) - { T TgetHNType(char[] s) { T t; readHNExact(&t, t.sizeof, s); return t;} } - - template TgetHNOType(T) - { - T TgetHNOType(char[] s, T def) - { - if(isNextSub(s)) - { - T t; - readHExact(&t, t.sizeof); - return t; - } - else return def; - } - } - - alias TgetHNType!(uint) getHNUint; - alias TgetHNType!(int) getHNInt; - alias TgetHNType!(float) getHNFloat; - alias TgetHNType!(ulong) getHNUlong; - alias TgetHNType!(byte) getHNByte; - alias TgetHNType!(short) getHNShort; - alias TgetHNType!(byte) getHNByte; - - alias TgetHNOType!(float) getHNOFloat; - alias TgetHNOType!(int) getHNOInt; - alias TgetHNOType!(byte) getHNOByte; - - void readHNExact(void* p, uint size, char[] s) - { getSubNameIs(s); readHExact(p,size); } - - // Record header - // This updates the leftFile variable BEYOND the data that follows - // the header, ie beyond the entire record. You are supposed to use - // the leftRec variable when reading record data. - void getRecHeader(out uint flags) - { - // General error checking - if(leftFile < 12) - fail("End of file while reading record header"); - if(leftRec) - fail(format("Previous record contains %d unread bytes", leftRec)); - - getUint(leftRec); - getUint(flags);// This header entry is always zero - assert(flags == 0); - getUint(flags); - leftFile -= 12; - - // Check that sizes add up - if(leftFile < leftRec) - fail(format(leftFile, " bytes left in file, but next record contains ", - leftRec," bytes")); - - // Adjust number of bytes left in file - leftFile -= leftRec; - } - - // Sub-record head - // This updates leftRec beyond the current sub-record as - // well. leftSub contains size of current sub-record. - void getSubHeader() - { - if(leftRec < 4) - fail("End of record while reading sub-record header"); - - if(file.readBlock(&leftSub, 4) != 4) - fail("getSubHeader could not read header length"); - - leftRec -= 4; - - // Adjust number of record bytes left - leftRec -= leftSub; - - // Check that sizes add up - if(leftRec < 0) - fail(format(leftRec+leftSub, - " bytes left in record, but next sub-record contains ", - leftSub," bytes")); - } - - void getSubHeaderIs(uint size) - { - getSubHeader(); - if(leftSub != size) - fail(format("Expected header size to be ", size, ", not ", leftSub)); - } - - /************************************************************************* - * - * Low level reading methods - * - *************************************************************************/ - - /// Raw data of any size - void readExact(void *buf, uint size) - { - assert(size != 0); - file.readExact(buf,size); - } - - // One byte - void getByte(out byte b) { file.read(b); } - void getUByte(out ubyte b) { file.read(b); } - // Two bytes - void getUShort(out ushort s) { file.read(s); } - // Four bytes - void getUint(out uint u) { file.read(u); } - void getInt(out int i) { file.read(i); } - void getFloat(out float f) { file.read(f); } - // Eight bytes - void getUlong(out ulong l) { file.read(l); } - - // Get a record or subrecord name, four bytes - void getName(NAME name) - { - file.readBlock(name.ptr, 4); - /* - if(file.readBlock(name.ptr, 4) != 4) - fail("getName() could not find more data"); - */ - } - - // Fill buffer of predefined length. If actual string is shorter - // (ie. null terminated), the buffer length is set - // accordingly. Chopped string is returned. All strings pass through - // this function, so any character encoding conversions should - // happen here. - char[] getString(char[] str) - { - if(str.length != file.readBlock(str.ptr,str.length)) - fail("getString() could not find enough data in stream"); - - str = stripz(str); - makeUTF8(str); // TODO: A hack. Will replace non-utf characters - // with question marks. This is neither a very - // desirable result nor a very optimized - // implementation of it. - return str; - } - - // Use this to allocate and read strings of predefined length - char[] getString(int l) - { - char[] str = region.getString(l); - return getString(str); - } -} diff --git a/old_d_version/esm/imports.d b/old_d_version/esm/imports.d deleted file mode 100644 index 69f1d33dc..000000000 --- a/old_d_version/esm/imports.d +++ /dev/null @@ -1,47 +0,0 @@ -module esm.imports; - -/* This is a file that imports common modules used by the load*.d - record loaders. It is really a cut down version of what used to be - the start of records.d. - - This file MUST NOT import records.d - directly or indirectly - - because that will trigger a nice three page long list of template - forwarding errors from the compiler. - - What happens is that when DMD/GDC compiles one of the load* files, - it is forced to read records.d first (since it is an imported - module) - but then it sees a template that referes to a struct in - the current load* file, before that struct is defined. Curriously - enough, DMD has no problems when you specify all the source files - on the command line simultaneously. This trick doesn't work with - GDC though, and DSSS doesn't use it either. - - This file was created to work around this compiler bug. -*/ - -public -{ -import esm.defs; -import esm.filereader; -import esm.listkeeper; - -import core.resource; -import core.memory; - -import util.regions; -import monster.util.aa; - -import std.stdio; -import std.string; - -alias RegionBuffer!(ENAMstruct) EffectList; - -// Records that are cross referenced often -import esm.loadscpt; -import esm.loadsoun; -import esm.loadspel; -import esm.loadench; - -import monster.monster; -} - diff --git a/old_d_version/esm/listkeeper.d b/old_d_version/esm/listkeeper.d deleted file mode 100644 index 3722a5d12..000000000 --- a/old_d_version/esm/listkeeper.d +++ /dev/null @@ -1,330 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (listkeeper.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module esm.listkeeper; - -import monster.util.aa; - -import core.memory; - -import esm.filereader; -import esm.defs; - -import std.stdio; - -// Item types, used in the lookup table for inventory items, creature -// lists and leveled lists. We also use it for all types of references -// that can exist in cells. -enum ItemType - { - // Items - None = 0, Potion, Apparatus, Armor, Weapon, Book, Clothing, - Light, Ingredient, Pick, Probe, Repair, Misc, ItemList, - - // Used for creature lists - Creature, CreatureList, NPC, - - // Other cell references - Door, Activator, Static, Container//, SoundGen - } - -abstract class ListKeeper -{ - int listIndex; - - new(uint size) - { - return esmRegion.allocate(size).ptr; - } - - delete(void *p) { assert(0); } - - this() - { - // Store our index for later use - listIndex = recordLists.length; - - // Add the class to the global list - recordLists ~= this; - } - - // Load a record from a master or plugin file - void load(); - - // Looks up a reference. If it does not exist it is assumed to be a - // forward reference within a file, and is inserted. - void* lookup(char[] s); - - // Tell the loader that current file has ended, so it can do things - // like check that all referenced objects have been loaded. - void endFile(); - - // Number of inserted elements - uint length(); - - void addToList(ref ItemBaseList l, ItemType t) { assert(0); } -} - -ListKeeper recordLists[]; - -// Keep the list of Type structures for records where the first -// subrecord is an id string called NAME. This id is used for -// lookup. Although almost all lookups match in case, there are a few -// sounds that don't, so we treat these id lookups as generally case -// insensitive. This hasn't posed any problems so far. -class ListID(Type) : ListKeeper -{ - HashTable!(char[], Type, ESMRegionAlloc, CITextHash) names; - - this(uint size) - { - names = names.init; - if(size) names.rehash(size); - } - - // Reads the id for this header. Override if the id is not simply - // getHNString("NAME") - char[] getID() - { - return esFile.getHNString("NAME"); - } - - // Load a record from a master of plugin file - void load() - { - assert(esFile.getFileType == FileType.Esm || - esFile.getFileType == FileType.Esp); - - // Get the identifier of this record - char[] id = getID(); - - // Get pointer to a new or existing object. - Type *p; - if(names.insertEdit(id, p)) - // A new item was inserted - { - p.state = LoadState.Unloaded; - p.id = id; - p.load(); - p.state = LoadState.Loaded; - } - else - // Item already existed, either from a previous file or as a - // forward reference from this file. Load on top of it. The - // LoadState tells the struct whether it contains loaded data. - { - /* - if(p.state == LoadState.Loaded) - // Make a special case for this, perhaps, or just ignore it. - writefln("WARNING: Duplicate record in file %s: '%s'", - esFile.getFilename(), id); - */ - - assert(icmp(p.id, id) == 0); - p.load(); - p.state = LoadState.Loaded; - } - } - - // Looks up a reference. If it does not exist it is assumed to be a - // forward reference within a file, and is inserted. - void* lookup(char[] id) - { - if(!id.length) return null; // Empty reference - - Type *p = names.lookup(id); - // Is the value in the list? - if(!p) - // No, assume it is a forward reference. - { - // Since the lookup name is stored in an internal buffer in - // esFile, we have to copy it. - id = esmRegion.copy(id); - - // To avoid copying the string on every lookup, we have to - // insert in a separate step. But a double lookup isn't - // really THAT expensive. Besides, my tests show that this - // is used in less than 10% of the cases. - names.insertEdit(id, p); - p.id = id; - p.state = LoadState.Unloaded; - } - return cast(void*)p; - } - - // Check that all referenced objects are actually loaded. - void endFile() - in - { - // We can skip this in release builds - names.validate(); - } - body - { - foreach(char[] id, ref Type t; names) - // Current file is now counted as done - if(t.state == LoadState.Loaded) t.state = LoadState.Previous; - else if(t.state == LoadState.Unloaded) - //writefln("WARNING: Unloaded reference " ~ id); - esFile.fail("Unloaded reference " ~ id); - } - - // Number of inserted elements - uint length() {return names.length;} - - // Add the names in this list to an ItemList - void addToList(ref ItemBaseList l, ItemType t) - { - foreach(char[] id, ref Type s; names) - l.insert(id, &s, t); - } -} - -// A pointer to an item -struct ItemBase -{ - ItemType type; - void *p; -} - -struct ItemBaseList -{ - HashTable!(char[],ItemBase,ESMRegionAlloc) list; - - void addList(ItemBaseList l) - { - foreach(char[] id, ItemBase b; l.list) - insert(id, b.p, b.type); - } - - void addList(ListKeeper source, ItemType type) - { - source.addToList(*this, type); - } - - void insert(char[] id, void* p, ItemType type) - { - ItemBase *b; - if(!list.insertEdit(id, b)) - { - //writefln("Replacing item ", id); - if(b.type != ItemType.None) - esFile.fail("Replaced valid item: " ~ id); - } - //else writefln("Inserting new item ", id); - - b.type = type; - b.p = p; - } - - // Called at the end to check that all referenced items have been resolved - void endMerge() - { - foreach(char[] id, ref ItemBase t; list) - // Current file is now counted as done - if(t.type == ItemType.None) - // TODO: Don't use esFile.fail for this - esFile.fail("ItemBaseList: Unresolved forward reference: " ~ id); - } - - // Look up an item, return a pointer to the ItemBase representing - // it. If it does not exist, it is inserted. - ItemBase *lookup(char[] id) - { - if(!id.length) return null; // Empty reference - ItemBase *b = list.lookup(id); - // Is the value in the list? - if(!b) - // No, assume it is a forward reference. - { - // Since the lookup name is stored in an internal buffer in - // esFile, we have to copy it. - id = esmRegion.copy(id); - - // To avoid copying the string on every lookup, we have to - // insert in a separate step. But a double lookup isn't - // really THAT expensive. - list.insertEdit(id, b); - - b.p = null; - b.type = ItemType.None; - } - return b; - } -} - -// An item. Contains a reference to an ItemBase, which again is a -// reference to an item. The ItemBase might change after we have -// looked it up (for forward references), so we have to use a pointer. -struct Item -{ - ItemBase *i; - - void* getPtr(ItemType type) - { - if(i != null && i.type == type) return i.p; - return null; - } - - T* getType(T, ItemType Type)() - { - return cast(T*)getPtr(Type); - } -} - -struct ItemList -{ - private: - ItemBaseList list; - - public: - void addList(ItemList l) - { list.addList(l.list); } - - void addList(ListKeeper source, ItemType type) - { list.addList(source, type); } - - Item lookup(char[] id) - { - Item i; - i.i = list.lookup(id); - return i; - } - - void endMerge() - { list.endMerge(); } - - void endFile() - in { list.list.validate(); } - body {} - - void rehash(uint size) - { list.list.rehash(size); } - - uint length() { return list.list.length(); } -} - -// Aggregate lists, made by concatinating several other lists. -ItemList items; // All inventory items, including leveled item lists -ItemList actors; // All actors, ie. NPCs, creatures and leveled lists -ItemList cellRefs; // All things that are referenced from cells diff --git a/old_d_version/esm/loadcell.d b/old_d_version/esm/loadcell.d deleted file mode 100644 index 6f987e2e0..000000000 --- a/old_d_version/esm/loadcell.d +++ /dev/null @@ -1,189 +0,0 @@ -/* - This file contains some leftovers which have not yet been ported to - C++. - */ - -align(1) struct AMBIStruct -{ - Color ambient, sunlight, fog; - float fogDensity; - - static assert(AMBIStruct.sizeof == 16); -} - -int max(int x, int y) -{ return x>=y?x:y; } - -struct ExtCellHash -{ - // This is a pretty good hash, gives no collisions for all of - // Morrowind.esm when the table size is 2048, and it gives very few - // collisions overall. Not that it matters that much. - static uint hash(uint val) - { - uint res = cast(ushort)val; - res += *(cast(ushort*)&val+1)*41; - return res; - } - - static bool isEqual(uint a, uint b) { return a==b; } -} - -class CellList : ListKeeper -{ - // Again, these are here to avoid DMD template bugs - alias _aaNode!(char[], InteriorCell) _unused1; - alias _aaNode!(uint, ExteriorCell) _unused2; - - HashTable!(char[], InteriorCell, ESMRegionAlloc) in_cells; - HashTable!(uint, ExteriorCell, ESMRegionAlloc, ExtCellHash) ex_cells; - - // Store the maximum x or y coordinate (in absolute value). This is - // used in the landscape pregen process. - int maxXY; - - this() - { - in_cells = in_cells.init; - in_cells.rehash(1600); - - ex_cells = ex_cells.init; - ex_cells.rehash(1800); - } - - align(1) struct DATAstruct - { - CellFlags flags; - int gridX, gridY; - static assert(DATAstruct.sizeof==12); - } - - DATAstruct data; - - // Look up an interior cell, throws an error if not found (might - // change later) - InteriorCell *getInt(char[] s) - { - return in_cells.getPtr(s); - } - - // Exterior cell, same as above - ExteriorCell *getExt(int x, int y) - { - return ex_cells.getPtr(compound(x,y)); - } - - // Check whether we have a given exterior cell - bool hasExt(int x, int y) - { - return ex_cells.inList(compound(x,y)); - } - - void *lookup(char[] s) - { assert(0); } - - void endFile() - out - { - in_cells.validate(); - ex_cells.validate(); - } - body - { - foreach(id, ref c; in_cells) - { - if(c.state == LoadState.Loaded) c.state = LoadState.Previous; - // We never forward reference cells! - assert(c.state != LoadState.Unloaded); - } - - foreach(id, ref c; ex_cells) - { - if(c.state == LoadState.Loaded) c.state = LoadState.Previous; - // We never forward reference cells! - assert(c.state != LoadState.Unloaded); - } - } - - uint length() { return numInt() + numExt(); } - uint numInt() { return in_cells.length; } - uint numExt() { return ex_cells.length; } - - // Turn an exterior cell grid position into a unique number - static uint compound(int gridX, int gridY) - { - return cast(ushort)gridX + ((cast(ushort)gridY)<<16); - } - - static void decompound(uint val, out int gridX, out int gridY) - { - gridX = cast(short)(val&0xffff); - gridY = cast(int)(val&0xffff0000) >> 16; - } - - void load() - {with(esFile){ - char[] id = getHNString("NAME"); - - // Just ignore this, don't know what it does. I assume it - // deletes the cell, but we can't handle that yet. - if(isNextSub("DELE")) getHInt(); - - readHNExact(&data, data.sizeof, "DATA"); - - if(data.flags & CellFlags.Interior) - { - InteriorCell *p; - if(in_cells.insertEdit(id, p)) - // New item was inserted - { - p.state = LoadState.Unloaded; - p.id = id; - p.flags = data.flags; - p.load(); - p.state = LoadState.Loaded; - } - else - // Overloading an existing cell - { - if(p.state != LoadState.Previous) - fail("Duplicate interior cell " ~ id); - - assert(id == p.id); - p.load(); - p.state = LoadState.Loaded; - } - } - else // Exterior cell - { - uint key = compound(data.gridX, data.gridY); - - ExteriorCell *p; - if(ex_cells.insertEdit(key, p)) - // New cell - { - p.state = LoadState.Unloaded; - p.name = id; - p.flags = data.flags; - p.gridX = data.gridX; - p.gridY = data.gridY; - p.load(); - p.state = LoadState.Loaded; - - int mx = max(abs(p.gridX), abs(p.gridY)); - maxXY = max(maxXY, mx); - } - else - { - if(p.state != LoadState.Previous) - fail(format("Duplicate exterior cell %d %d", - data.gridX, data.gridY)); - assert(p.gridX == data.gridX); - assert(p.gridY == data.gridY); - p.load(); - p.state = LoadState.Loaded; - } - } - }} -} -CellList cells; diff --git a/old_d_version/esm/loaddial.d b/old_d_version/esm/loaddial.d deleted file mode 100644 index 6e36f0b88..000000000 --- a/old_d_version/esm/loaddial.d +++ /dev/null @@ -1,289 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (loaddial.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module esm.loaddial; -import esm.imports; -import esm.loadinfo; - -/* - * Dialogue topic and journal entries. The acutal data is contained in - * the following INFO records. - */ - -// Keep a list of possible hyper links. This list is used when parsing -// text and finding references to topic names. Eg. if a character says -// "Would you like to join the mages guild?", we must be able to pick -// out the phrase "join the mages guild?" and make a hyperlink of -// it. Each link is indexed by their first word. The structure -// contains the rest of the phrase, so the phrase above would be -// indexed by "join" and contain the string "the mages guild?", for -// quick comparison with the text are currently parsing. It also -// contains a pointer to the corresponding dialogue struct. The lists -// are sorted by descending string length, in order to match the -// longest possible term first. - -struct Hyperlink -{ - Dialogue *ptr; - char[] rest; - - // Returns a < b if a.length > b.length. - int opCmp(Hyperlink *h) {return h.rest.length - rest.length;} -} - -alias RegionBuffer!(Hyperlink) HyperlinkArray; - -// This is much nicer now that we use our own AA. -struct HyperlinkList -{ - // Make a case insensitive hash table of Hyperlink arrays. - HashTable!(char[], HyperlinkArray, ESMRegionAlloc, CITextHash) list; - - void add(char[] topic, Dialogue* ptr) - { - // Only add dialogues - if(ptr.type != Dialogue.Type.Topic) return; - - Hyperlink l; - l.ptr = ptr; - l.rest = topic; - - // Use the first word as the index - topic = nextWord(l.rest); - - // Insert a new array, or get an already existing one - HyperlinkArray ha = list.get(topic, - // Create a new array - delegate void (ref HyperlinkArray a) - { a = esmRegion.getBuffer!(Hyperlink)(0,1); } - ); - - // Finally, add it to the list - ha ~= l; - } - - Hyperlink[] getList(char[] word) - { - HyperlinkArray p; - if(list.inList(word, p)) return p.array(); - return null; - } - - void rehash(uint size) - { - list.rehash(size); - } - - // We wouldn't need this if we only dealt with one file, since the - // topics are already sorted in Morrowind.esm. However, other files - // might add items out of order later, so we have to sort it. To - // understand why this is needed, consider the following example: - // - // Morrowind.esm contains the topic 'join us'. When ever the text - // ".. join us blahblah ..." is encountered, this match is - // found. However, if a plugin adds the topic 'join us today', we - // have to place this _before_ 'join us' in the list, or else it - // will never be matched. - void sort() - { - foreach(char[] s, HyperlinkArray l; list) - { - l.array().sort; - /* - writefln("%s: ", s, l.length); - foreach(Hyperlink h; l.array()) - writefln(" %s (%s)", h.rest, h.ptr.id); - */ - } - } -} - -// List of dialogue hyperlinks -HyperlinkList hyperlinks; - -struct Dialogue -{ - enum Type - { - Topic = 0, - Voice = 1, - Greeting = 2, - Persuasion = 3, - Journal = 4, - Deleted = -1 - } - - //Type type; - DialogueType type; - - DialInfoList infoList; - - char[] id; // This is the 'dialogue topic' that the user actually - // sees. - LoadState state; - - void load() - {with(esFile){ - getSubNameIs("DATA"); - - getSubHeader(); - int si = getSubSize(); - if(si == 1) - { - byte b; - getByte(b); - DialogueType t = cast(DialogueType)b; - - // Meet the new type, same as the old type - if(t != this.type && state == LoadState.Previous) - fail("Type changed in dialogue " ~ id); - - this.type = t; - } - else if(si == 4) - { - // These are just markers, their values are not used. - int i; - getInt(i); - //writefln("In file %s:", getFilename()); - //writefln(" WARNING: DIAL.DATA was size 4 and contains: ", i); - i = getHNInt("DELE"); - //writefln(" DELE contains ", i); - this.type = Type.Deleted; - } - else fail("Unknown sub record size " ~ toString(si)); - - infoList.state = state; - while(isNextHRec("INFO")) - infoList.load(this.type); - //skipRecord(); - }} -} - -typedef Dialogue.Type DialogueType; - -/+ - // I don't remember when I commented out this code or what state - // it is in. Probably highly experimental. - // -------------- - - // Loop through the info blocks in this dialogue, and update the - // master as necessary. - - // TODO: Note that the dialogue system in Morrowind isn't very - // robust. If several mods insert dialogues at exactly the same - // place, the mods loaded last might overwrite the previous mods, - // completely removing the previous entry even if the two entries - // do not have the same id. This is because a change also - // overwrites the previous and the next entry, in order to update - // their "previous" and "next" fields. Furthermore, we might put - // ourselves in a situation where the forward and backward chains - // do not match, or in a situation where we update a deleted - // info. For now I do nothing about it, but I will have to develop - // a "conflict manager" later on. It SHOULD be possible to merge - // these info lists automatically in most cases, but it - // complicates the code. - - // Whoa, seems we have a case study already with just tribunal and - // bloodmoon loaded! See comments below. - - foreach(char[] id, ref DialInfoLoad m; mod.infoList) - { - // Remove the response if it is marked as deleted. - if(m.deleted) - { - if((id in master.infoList) == null) - writefln("Cannot delete info %s, does not exist", id); - else master.infoList.remove(id); - } - else - // Just plain copy it in. - master.infoList[id] = m; - } - } - - // Here we have to fix inconsistencies. A good case example is the - // dialogue "Apelles Matius" in trib/blood. Trib creates a - // dialogue of a few items, bloodmoon adds another. But since the - // two are independent, the list in bloodmoon does not change the - // one in trib but rather creates a new one. In other words, we - // will have to deal with the possibility of several "independent" - // lists within each topic. We can do this by looking for several - // start points (ie. infos with prev="") and just latch them onto - // each other. I'm not sure it gives the correct result, - // though. For example, which list comes first would be rather - // arbitrarily decided by the order we traverse the infoList AA. I - // will just have to assume that they truly are "independent". - - // There still seems to be a problem though. Bloodmoon overwrites - // some stuff added by Tribunal, see "Boots of the Apostle" for an - // example. Looks like the editor handles it just fine... We need - // to make sure that all the items in our AA are put into the - // list, and in the right place too. We obviously cannot fully - // trust the 'next' and 'prev' fields, but they are the only - // guidance we have. Deal with it later! - - // At this point we assume "master" to contain the final dialogue - // list, so at this point we can set it in stone. - infoList.length = master.infoList.length; - - // Find the first entry - DialInfoLoad* starts[]; // starting points for linked lists - DialInfoLoad *current; - foreach(char[] id, ref DialInfoLoad l; master.infoList) - if(l.prev == "") starts ~= &l; - - foreach(int num, ref DialInfo m; infoList) - { - if(current == null) - { - if(starts.length == 0) - { - writefln("Error: No starting points!"); - infoList.length = num; - break; - } - // Pick the next starting point - current = starts[0]; - starts = starts[1..$]; - } - m.copy(*current, this); - - if((*current).next == "") - current = null; - else - { - current = (*current).next in master.infoList; - if(current == null) - { - writefln("Error in dialouge info lookup!"); - break; - } - } - } - if(infoList.length != master.infoList.length) - writefln("Dialogue list lengths do not match, %d != %d", - infoList.length, master.infoList.length); - } -} -+/ diff --git a/old_d_version/esm/records.d b/old_d_version/esm/records.d deleted file mode 100644 index d5dd211a1..000000000 --- a/old_d_version/esm/records.d +++ /dev/null @@ -1,219 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (records.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ -module esm.records; - -public -{ - import monster.util.aa; - import util.regions; - - import core.memory; - import core.resource; - - import esm.filereader; - import esm.defs; - import esm.listkeeper; - - import std.stdio; // Remove later -} - -public import - esm.loadacti, esm.loaddoor, esm.loadglob, esm.loadscpt, esm.loadsoun, esm.loadgmst, - esm.loadfact, esm.loadstat, esm.loadspel, esm.loadalch, esm.loadappa, esm.loadarmo, - esm.loadbody, esm.loadench, esm.loadbook, esm.loadbsgn, esm.loadltex, esm.loadmgef, - esm.loadweap, esm.loadlocks,esm.loadcell, esm.loadregn, esm.loadligh, esm.loadskil, - esm.loadsndg, esm.loadrace, esm.loadmisc, esm.loadclot, esm.loadingr, esm.loadclas, - esm.loadcont, esm.loadcrea, esm.loadnpc, esm.loaddial, esm.loadinfo, esm.loadsscr, - esm.loadlevlist; - -void loadRecord(char[] recName) -{ - switch(recName) - { - case "ACTI": activators.load(); break; - case "DOOR": doors.load(); break; - case "GLOB": globals.load(); break; - case "SCPT": scripts.load(); break; - case "SOUN": sounds.load(); break; - case "GMST": gameSettings.load(); break; - case "FACT": factions.load(); break; - case "STAT": statics.load(); break; - case "SPEL": spells.load(); break; - case "ALCH": potions.load(); break; - case "APPA": appas.load(); break; - case "ARMO": armors.load(); break; - case "BODY": bodyParts.load(); break; - case "ENCH": enchants.load(); break; - case "BOOK": books.load(); break; - case "BSGN": birthSigns.load(); break; - case "LTEX": landTextures.load(); break; - case "MGEF": effects.load(); break; - case "WEAP": weapons.load(); break; - case "REPA": repairs.load(); break; - case "LOCK": lockpicks.load(); break; - case "PROB": probes.load(); break; - case "CELL": cells.load(); break; - case "REGN": regions.load(); break; - case "LIGH": lights.load(); break; - case "SKIL": skills.load(); break; - case "SNDG": soundGens.load(); break; - case "RACE": races.load(); break; - case "MISC": miscItems.load(); break; - case "CLOT": clothes.load(); break; - case "INGR": ingreds.load(); break; - case "CLAS": classes.load(); break; - case "CONT": containers.load(); break; - case "CREA": creatures.load(); break; - case "LEVI": itemLists.load(); break; - case "LEVC": creatureLists.load(); break; - case "NPC_": npcs.load(); break; - case "DIAL": dialogues.load(); break; - case "SSCR": startScripts.load(); break; - /* - - // Tribunal / Bloodmoon only - case "SSCR": loadSSCR.load(); break; - - */ - // For save games: - // case "NPCC": loadNPCC; - // case "CNTC": loadCNTC; - // case "CREC": loadCREC; - - // These should never be looked up - case "TES3": - case "INFO": - case "LAND": - case "PGRD": - esFile.fail("Misplaced record " ~ recName); - default: - esFile.fail("Unknown record type " ~ recName); - } - //*/ -} - -// Um, this has to be in this file for some reason. -ListID!(Dialogue) dialogues; - -struct ItemT -{ - Item item; - ItemBase *i; - - T* getType(T, ItemType Type)() - { - return item.getType!(T, Type)(); - } - - alias getType!(Potion, ItemType.Potion) getPotion; - alias getType!(Apparatus, ItemType.Apparatus) getApparatus; - alias getType!(Armor, ItemType.Armor) getArmor; - alias getType!(Weapon, ItemType.Weapon) getWeapon; - alias getType!(Book, ItemType.Book) getBook; - alias getType!(Clothing, ItemType.Clothing) getClothing; - alias getType!(Light, ItemType.Light) getLight; - alias getType!(Ingredient, ItemType.Ingredient) getIngredient; - alias getType!(Tool, ItemType.Pick) getPick; - alias getType!(Tool, ItemType.Probe) getProbe; - alias getType!(Tool, ItemType.Repair) getRepair; - alias getType!(Misc, ItemType.Misc) getMisc; - alias getType!(LeveledItems, ItemType.ItemList) getItemList; - alias getType!(Creature, ItemType.Creature) getCreature; - alias getType!(LeveledCreatures, ItemType.CreatureList) getCreatureList; - alias getType!(NPC, ItemType.NPC) getNPC; - alias getType!(Door, ItemType.Door) getDoor; - alias getType!(Activator, ItemType.Activator) getActivator; - alias getType!(Static, ItemType.Static) getStatic; - alias getType!(Container, ItemType.Container) getContainer; - - static ItemT opCall(Item it) - { - ItemT itm; - itm.item = it; - itm.i = it.i; - return itm; - } -} - -void endFiles() -{ - foreach(ListKeeper l; recordLists) - l.endFile(); - - items.endFile(); -} - -void initializeLists() -{ - recordLists = null; - - // Initialize all the lists here. The sizes have been chosen big - // enough to hold the main ESM files and a large number of mods - // without rehashing. - - activators = new ListID!(Activator)(1400); - doors = new ListID!(Door)(300); - globals = new ListID!(Global)(300); - scripts = new ScriptList(1800); - sounds = new ListID!(Sound)(1000); - gameSettings = new ListID!(GameSetting)(1600); - factions = new ListID!(Faction)(30); - statics = new ListID!(Static)(4000); - spells = new ListID!(Spell)(1300); - potions = new ListID!(Potion)(300); - appas = new ListID!(Apparatus)(30); - armors = new ListID!(Armor)(500); - bodyParts = new ListID!(BodyPart)(2300); - enchants = new ListID!(Enchantment)(1000); - books = new ListID!(Book)(700); - birthSigns = new ListID!(BirthSign)(30); - landTextures = new LandTextureList; - effects = new MagicEffectList; - weapons = new ListID!(Weapon)(700); - lockpicks = new ListID!(Tool)(10); - probes = new ListID!(Tool)(10); - repairs = new ListID!(Tool)(10); - cells = new CellList; - regions = new ListID!(Region)(20); - lights = new ListID!(Light)(1000); - skills = new SkillList; - soundGens = new ListID!(SoundGenerator)(500); - races = new ListID!(Race)(100); - miscItems = new ListID!(Misc)(700); - clothes = new ListID!(Clothing)(700); - ingreds = new ListID!(Ingredient)(200); - classes = new ListID!(Class)(100); - containers = new ListID!(Container)(1200); - creatures = new ListID!(Creature)(800); - itemLists = new ListID!(LeveledItems)(600); - creatureLists = new ListID!(LeveledCreatures)(400); - npcs = new ListID!(NPC)(3500); - dialogues = new ListID!(Dialogue)(3000); - startScripts.init(); - - hyperlinks.rehash(1600); - - items.rehash(5500); - actors.rehash(5000); - cellRefs.rehash(17000); -} diff --git a/old_d_version/esmtool.d b/old_d_version/esmtool.d deleted file mode 100644 index a43361803..000000000 --- a/old_d_version/esmtool.d +++ /dev/null @@ -1,377 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (esmtool.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module esmtool; - -import std.stdio; - -import core.memory; -import esm.esmmain; -import monster.util.string; -import mscripts.setup; - -import std.gc; -import gcstats; - - -// Not used, but we have to link it in along with the C++ stuff. -import input.events; - -void poolSize() -{ - GCStats gc; - getStats(gc); - writefln("Pool size: ", comma(gc.poolsize)); - writefln("Used size: ", comma(gc.usedsize)); -} - -//alias int[Dialogue*] TopicList; - -void main(char[][] args) -{ - char[][] files; - bool raw; - - bool scptList; // List scripts - bool scptShow; // Show a script - char[] scptName; // Script to show - - bool ciList; // List interior cells - bool ceList; // List exterior cells that have names - - bool weList; // List weapons - - bool gmst; // List game settings - - bool numbers; // List how many there are of each record type - - foreach(char[] a; args[1..$]) - if(a == "-r") raw = true; - - else if(a == "-sl") scptList = true; - else if(a == "-s") scptShow = true; - else if(scptShow && scptName == "") scptName = a; - - else if(a == "-g") gmst = true; - else if(a == "-cil") ciList = true; - else if(a == "-cel") ceList = true; - - else if(a == "-wl") weList = true; - - else if(a == "-n") numbers = true; - - else if(a.begins("-")) writefln("Ignoring unknown option %s", a); - else files ~= a; - - int help(char[] msg) - { - writefln("%s", msg); - writefln("Syntax: %s [options] esm-file [esm-file ... ]", args[0]); - writefln(" Options:"); - writefln(" -r Display all records in raw format"); - writefln(" -n List the number of each record type"); - writefln(" -sl List scripts"); - writefln(" -g List game settings (GMST)"); - writefln(" -s name Show given script"); - writefln(" -cil List interior cells"); - writefln(" -cel List exterior cells with names"); - writefln(" -wl List weapons"); - return 1; - } - if(files.length == 0) return help("No input files given"); - - if(scptShow && scptName == "") return help("No script name given"); - - initializeMemoryRegions(); - initMonsterScripts(); - - if(raw) - { - foreach(int fileNum, char[] filename; files) - { - try - { - esFile.open(filename, esmRegion); - printRaw(); - } - catch(Exception e) - { - try {writefln(e);} - catch {} - writefln("Error on file %s", filename); - } - catch - { - writefln("Error: Unkown failure on file %s", filename); - } - } - return; - } - - // Disable resource lookups. - resources.dummy = true; - - try loadTESFiles(files); - catch(Exception e) - { - writefln(e); - } - catch { writefln("Error: Unkown failure"); } - - // List weapons - if(weList) foreach(n, m; weapons.names) - { - alias Weapon.Type WT; - switch(m.data.type) - { - case WT.ShortBladeOneHand: writef("Short Sword"); break; - case WT.LongBladeOneHand: writef("Long Sword, One-Handed"); break; - case WT.LongBladeTwoHand: writef("Long Sword, Two-Handed"); break; - case WT.BluntOneHand: writef("Blunt, One-Handed"); break; - case WT.BluntTwoClose: writef("Blunt, Two-Handed"); break; - case WT.BluntTwoWide: writef("Blunt, Two-Handed Wide"); break; - case WT.SpearTwoWide: writef("Spear, Two-Handed"); break; - case WT.AxeOneHand: writef("Axe, One-Handed"); break; - case WT.AxeTwoHand: writef("Axe, Two-Handed"); break; - case WT.MarksmanBow: writef("Bow"); break; - case WT.MarksmanCrossbow: writef("Crossbow"); break; - case WT.MarksmanThrown: writef("Thrown weapon"); break; - case WT.Arrow: writef("Arrow"); break; - case WT.Bolt: writef("Bolt"); break; - default: assert(0); - } - writefln(" id '%s': name '%s'", n, m.name); - - if(m.data.flags & Weapon.Flags.Magical) - writefln("Magical"); - if(m.data.flags & Weapon.Flags.Silver) - writefln("Silver"); - - writefln("Weight: ", m.data.weight); - writefln("Value: ", m.data.value); - writefln("Health: ", m.data.health); - writefln("Speed: ", m.data.speed); - writefln("Reach: ", m.data.reach); - writefln("Enchantment points: ", m.data.enchant); - writefln("Combat: ", m.data.chop, m.data.slash, m.data.thrust); - - if(m.enchant) writefln("Has enchantment '%s'", m.enchant.id); - if(m.script) writefln("Has script '%s'", m.script.id); - - writefln(); - } - - if(numbers) - { - writefln("Activators: ", activators.length); - writefln("Doors: ", doors.length); - writefln("Globals: ", globals.length); - writefln("Sounds: ", sounds.length); - writefln("Game Settings: ", gameSettings.length); - writefln("Factions: ", factions.length); - writefln("Statics: ", statics.length); - writefln("Spells: ", spells.length); - writefln("Potions: ", potions.length); - writefln("Apparatus: ", appas.length); - writefln("Armors: ", armors.length); - writefln("Body parts: ", bodyParts.length); - writefln("Enchantments: ", enchants.length); - writefln("Books: ", books.length); - writefln("Birth signs: ", birthSigns.length); - writefln("Land texture files: ", landTextures.length); - writefln("Weapons: ", weapons.length); - writefln("Lockpicks: ", lockpicks.length); - writefln("Probes: ", probes.length); - writefln("Repairs: ", repairs.length); - writefln("Cells: ", cells.length); - writefln(" Interior: ", cells.numInt); - writefln(" Exterior: ", cells.numExt); - writefln("Regions: ", regions.length); - writefln("Lights: ", lights.length); - writefln("Skills: ", skills.length); - writefln("Sound generators: ", soundGens.length); - writefln("Races: ", races.length); - writefln("Misc items: ", miscItems.length); - writefln("Cloths: ", clothes.length); - writefln("Ingredients: ", ingreds.length); - writefln("Classes: ", classes.length); - writefln("Containers: ", containers.length); - writefln("Creatures: ", creatures.length); - writefln("Leveled item lists: ", itemLists.length); - writefln("Leveled creature lists: ", creatureLists.length); - writefln("NPCs: ", npcs.length); - writefln("Scripts: ", scripts.length); - writefln("Dialogues: ", dialogues.length); - writefln("Hyperlinks: ", hyperlinks.list.length); - writefln("Start scripts: ", startScripts.length); - writefln("\nTotal items: ", items.length); - writefln("Total actors: ", actors.length); - writefln("Total cell placable items: ", cellRefs.length); - } - if(gmst) - { - foreach(a, b; gameSettings.names) - { - writef(a, " ("); - if(b.type == VarType.Int) writefln("int) = ", b.i); - else if(b.type == VarType.Float) writefln("float) = ", b.f); - else if(b.type == VarType.String) writefln("string) = '%s'", b.str); - else writefln("no value)", cast(int)b.type); - } - } - - if(scptList) foreach(a, b; scripts.names) writefln(a); - if(ciList) - foreach(a, b; cells.in_cells) - writefln(a); - if(ceList) - foreach(uint i, c; .cells.ex_cells) - { - int x, y; - CellList.decompound(i, x, y); - if(c.name.length) - writefln("%s,%s: %s", x, y, c.name); - } - - if(scptShow) - { - Script *p = scripts.names.lookup(scptName); - if(p) - writefln("Script '%s', text is:\n-------\n%s\n-------", p.id, p.scriptText); - else writefln("Script '%s' not found", scptName); - writefln(); - } - - writefln(esmRegion); - - poolSize(); -} - -// Quick function that simply iterates through an ES file and prints -// out all the records and subrecords. Some of this code is really old -// (about 2004-2005) -void printRaw() -{ - with(esFile) - { - // Variable length integer (this only works for unsigned ints!) - ulong getHVUint() - { - ulong l; - - getSubHeader(); - if( (getSubSize != 4) && - (getSubSize != 2) && - (getSubSize != 8) ) - fail(format("Unknown integer size: ", getSubSize)); - - readExact(&l, getSubSize); - return l; - } - - writefln("Filename: ", getFilename); - writef("Filetype: "); - switch(getFileType()) - { - case FileType.Plugin: writefln("Plugin"); break; - case FileType.Master: writefln("Master"); break; - case FileType.Savegame: writefln("Savegame"); break; - case FileType.Unknown: writefln("Unknown"); break; - default: assert(0); - } - writef("Version: "); - if(isVer12()) writefln("1.2"); - else if(isVer13()) writefln("1.3"); - else writefln("Unknown"); - - writefln("Records: ", getRecords); - writefln("Master files:"); - for(int i; i - WWW: http://openmw.snaptoad.com/ - - This file (events.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module input.events; - -import std.stdio; -import std.string; - -import sound.audio; - -import core.config; - -import scene.soundlist; -import scene.player; - -import bullet.bindings; - -import monster.monster; -import monster.vm.dbg; - -import ogre.bindings; -import gui.bindings; -import gui.gui; - -import input.keys; -import input.ois; - -// Debug output -//debug=printMouse; // Mouse button events -//debug=printMouseMove; // Mouse movement events -//debug=printKeys; // Keypress events - -// TODO: Jukebox controls and other state-related data will later be -// handled entirely in script code, as will some of the key bindings. - -// Pause? -bool pause = false; -int *guiMode; - -const float volDiff = 0.05; - -void musVolume(bool increase) -{ - float diff = -volDiff; - if(increase) diff = -diff; - config.setMusicVolume(diff + config.getMusicVolume); - writefln(increase?"Increasing":"Decreasing", " music volume to ", config.getMusicVolume); -} - -void sfxVolume(bool increase) -{ - float diff = -volDiff; - if(increase) diff = -diff; - config.setSfxVolume(diff + config.getSfxVolume); - writefln(increase?"Increasing":"Decreasing", " sound effect volume to ", config.getSfxVolume); -} - -void mainVolume(bool increase) -{ - float diff = -volDiff; - if(increase) diff = -diff; - config.setMainVolume(diff + config.getMainVolume); - writefln(increase?"Increasing":"Decreasing", " main volume to ", config.getMainVolume); -} - -void updateMouseSensitivity() -{ - effMX = *config.mouseSensX; - effMY = *config.mouseSensY; - if(*config.flipMouseY) effMY = -effMY; -} - -void togglePause() -{ - pause = !pause; - if(pause) writefln("Pause"); - else writefln("Pause off"); -} - -extern(C) void d_handleMouseButton(MouseState *state, int button) -{ - debug(printMouse) - writefln("handleMouseButton %s: Abs(%s, %s, %s)", button, - state.X.abs, state.Y.abs, state.Z.abs); - - // For the moment, just treat mouse clicks as normal key presses. - d_handleKey(cast(KC) (KC.Mouse0 + button)); -} - -// Handle a keyboard event through key bindings. Direct movement -// (eg. arrow keys) is not handled here, see d_frameStarted() below. -extern(C) void d_handleKey(KC keycode, dchar text = 0) -{ - // Do some preprocessing on the data to account for OIS - // shortcommings. - - // Some keys (especially international keys) have no key code but - // return a character instead. - if(keycode == 0) - { - // If no character is given, just drop this event since OIS did - // not manage to give us any useful data at all. - if(text == 0) return; - - keycode = KC.CharOnly; - } - - // Debug output - debug(printKeys) - { - char[] str; - if(keycode >= 0 && keycode < keysymToString.length) - str = keysymToString[keycode]; - else str = "OUT_OF_RANGE"; - writefln("Key %s, text '%s', name '%s'", keycode, text, str); - } - - // Look up the key binding. We have to send both the keycode and the - // text. - Keys k = keyBindings.findMatch(keycode, text); - - // These are handled even if we are in gui mode: - if(k) - switch(k) - { - case Keys.ToggleGui: gui_toggleGui(); return; - case Keys.Console: gui_toggleConsole(); return; - case Keys.ScreenShot: takeScreenShot(); return; - default: - } - - if(*guiMode) return; - - if(k) - switch(k) - { - case Keys.ToggleBattleMusic: - Music.toggle(); - return; - - case Keys.MainVolUp: mainVolume(true); return; - case Keys.MainVolDown: mainVolume(false); return; - case Keys.MusVolUp: musVolume(true); return; - case Keys.MusVolDown: musVolume(false); return; - case Keys.SfxVolUp: sfxVolume(true); return; - case Keys.SfxVolDown: sfxVolume(false); return; - case Keys.Mute: Music.toggleMute(); return; - case Keys.Fullscreen: toggleFullscreen(); return; - - case Keys.PhysMode: bullet_nextMode(); return; - case Keys.Nighteye: ogre_toggleLight(); return; - - case Keys.Debug: return; - case Keys.Pause: togglePause(); return; - case Keys.Exit: exitProgram(); return; - default: - assert(k >= 0 && k < keyToString.length); - writefln("WARNING: Event %s has no effect", keyToString[k]); - } - return; -} - -// Refresh rate for sfx placements, in seconds. -const float sndRefresh = 0.17; - -// Refresh rate for music fadeing, seconds. -const float musRefresh = 0.05; - -// Walking / floating speed, in points per second. -float speed = 300; - -float sndCumTime = 0; -float musCumTime = 0; - -// Move the player according to playerData.position -void movePlayer() -{ - // Move the player into place. TODO: This isn't really input-related - // at all, and should be moved. - with(*playerData.position) - { - ogre_moveCamera(position[0], position[1], position[2]); - ogre_setCameraRotation(rotation[0], rotation[1], rotation[2]); - - bullet_movePlayer(position[0], position[1], position[2]); - } -} - -void initializeInput() -{ - movePlayer(); - - // TODO/FIXME: This should have been in config, but DMD's module - // system is on the brink of collapsing, and it won't compile if I - // put another import in core.config. I should probably check the - // bug list and report it. - updateMouseSensitivity(); - - // Get a pointer to the 'guiMode' flag in cpp_ogre.cpp - guiMode = gui_getGuiModePtr(); -} - -extern(C) int ois_isPressed(int keysym); - -// Check if a key is currently down -bool isPressed(Keys key) -{ - KeyBind *b = &keyBindings.bindings[key]; - foreach(i; b.syms) - if(i != 0 && ois_isPressed(i)) return true; - return false; -} - -// Enable superman mode, ie. flight and super-speed. Only used for -// debugging the terrain mode. -extern(C) void d_terr_superman() -{ - bullet_fly(); - speed = 8000; - - with(*playerData.position) - { - position[0] = 20000; - position[1] = -70000; - position[2] = 30000; - } - movePlayer(); -} - -extern(C) int d_frameStarted(float time) -{ - if(doExit) return 0; - - dbg.trace("d_frameStarted"); - scope(exit) dbg.untrace(); - - // Run the Monster scheduler - vm.frame(time); - - musCumTime += time; - if(musCumTime > musRefresh) - { - Music.updateBuffers(); - musCumTime -= musRefresh; - } - - // The rest is ignored in pause or GUI mode - if(pause || *guiMode > 0) return 1; - - // Check if the movement keys are pressed - float moveX = 0, moveY = 0, moveZ = 0; - float x, y, z, ox, oy, oz; - - if(isPressed(Keys.MoveLeft)) moveX -= speed; - if(isPressed(Keys.MoveRight)) moveX += speed; - if(isPressed(Keys.MoveForward)) moveZ -= speed; - if(isPressed(Keys.MoveBackward)) moveZ += speed; - - // TODO: These should be enabled for floating modes (like swimming - // and levitation) and disabled for everything else. - if(isPressed(Keys.MoveUp)) moveY += speed; - if(isPressed(Keys.MoveDown)) moveY -= speed; - - // This isn't very elegant, but it's simple and it works. - - // Get the current coordinates - ogre_getCameraPos(&ox, &oy, &oz); - - // Move camera using relative coordinates. TODO: We won't really - // need to move the camera here (since it's moved below anyway), we - // only want the transformation from camera space to world - // space. This can likely be done more efficiently. - ogre_moveCameraRel(moveX, moveY, moveZ); - - // Get the result - ogre_getCameraPos(&x, &y, &z); - - // The result is the real movement direction, in world coordinates - moveX = x-ox; - moveY = y-oy; - moveZ = z-oz; - - // Tell Bullet that this is where we want to go - bullet_setPlayerDir(moveX, moveY, moveZ); - - // Perform a Bullet time step - bullet_timeStep(time); - - // Get the final (actual) player position and update the camera - bullet_getPlayerPos(&x, &y, &z); - ogre_moveCamera(x,y,z); - - // Store it in the player object - playerData.position.position[0] = x; - playerData.position.position[1] = y; - playerData.position.position[2] = z; - - if(!config.noSound) - { - // Tell the sound scene that the player has moved - sndCumTime += time; - if(sndCumTime > sndRefresh) - { - float fx, fy, fz; - float ux, uy, uz; - - ogre_getCameraOrientation(&fx, &fy, &fz, &ux, &uy, &uz); - - soundScene.update(x,y,z,fx,fy,fz,ux,uy,uz); - sndCumTime -= sndRefresh; - } - } - return 1; -} - -bool collides = false; diff --git a/old_d_version/input/ois.d b/old_d_version/input/ois.d deleted file mode 100644 index 60129cadf..000000000 --- a/old_d_version/input/ois.d +++ /dev/null @@ -1,428 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (ois.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module input.ois; - -// Mouse buttons -enum MB : int - { - Button0 = 0, - Left = Button0, - Button1 = 1, - Right = Button1, - Button2 = 2, - Middle = Button2, - - Button3 = 3, - Button4 = 4, - Button5 = 5, - Button6 = 6, - Button7 = 7, - - LastMouse - } - - // Keyboard scan codes -enum KC : int - { - UNASSIGNED = 0x00, - ESCAPE = 0x01, - N1 = 0x02, - N2 = 0x03, - N3 = 0x04, - N4 = 0x05, - N5 = 0x06, - N6 = 0x07, - N7 = 0x08, - N8 = 0x09, - N9 = 0x0A, - N0 = 0x0B, - MINUS = 0x0C, // - on main keyboard - EQUALS = 0x0D, - BACK = 0x0E, // backspace - TAB = 0x0F, - Q = 0x10, - W = 0x11, - E = 0x12, - R = 0x13, - T = 0x14, - Y = 0x15, - U = 0x16, - I = 0x17, - O = 0x18, - P = 0x19, - LBRACKET = 0x1A, - RBRACKET = 0x1B, - RETURN = 0x1C, // Enter on main keyboard - LCONTROL = 0x1D, - A = 0x1E, - S = 0x1F, - D = 0x20, - F = 0x21, - G = 0x22, - H = 0x23, - J = 0x24, - K = 0x25, - L = 0x26, - SEMICOLON = 0x27, - APOSTROPHE = 0x28, - GRAVE = 0x29, // accent - LSHIFT = 0x2A, - BACKSLASH = 0x2B, - Z = 0x2C, - X = 0x2D, - C = 0x2E, - V = 0x2F, - B = 0x30, - N = 0x31, - M = 0x32, - COMMA = 0x33, - PERIOD = 0x34, // . on main keyboard - SLASH = 0x35, // / on main keyboard - RSHIFT = 0x36, - MULTIPLY = 0x37, // * on numeric keypad - LMENU = 0x38, // left Alt - SPACE = 0x39, - CAPITAL = 0x3A, - F1 = 0x3B, - F2 = 0x3C, - F3 = 0x3D, - F4 = 0x3E, - F5 = 0x3F, - F6 = 0x40, - F7 = 0x41, - F8 = 0x42, - F9 = 0x43, - F10 = 0x44, - NUMLOCK = 0x45, - SCROLL = 0x46, // Scroll Lock - NUMPAD7 = 0x47, - NUMPAD8 = 0x48, - NUMPAD9 = 0x49, - SUBTRACT = 0x4A, // - on numeric keypad - NUMPAD4 = 0x4B, - NUMPAD5 = 0x4C, - NUMPAD6 = 0x4D, - ADD = 0x4E, // + on numeric keypad - NUMPAD1 = 0x4F, - NUMPAD2 = 0x50, - NUMPAD3 = 0x51, - NUMPAD0 = 0x52, - DECIMAL = 0x53, // . on numeric keypad - OEM_102 = 0x56, // < > | on UK/Germany keyboards - F11 = 0x57, - F12 = 0x58, - F13 = 0x64, // (NEC PC98) - F14 = 0x65, // (NEC PC98) - F15 = 0x66, // (NEC PC98) - KANA = 0x70, // (Japanese keyboard) - ABNT_C1 = 0x73, // / ? on Portugese (Brazilian) keyboards - CONVERT = 0x79, // (Japanese keyboard) - NOCONVERT = 0x7B, // (Japanese keyboard) - YEN = 0x7D, // (Japanese keyboard) - ABNT_C2 = 0x7E, // Numpad . on Portugese (Brazilian) keyboards - NUMPADEQUALS= 0x8D, // = on numeric keypad (NEC PC98) - PREVTRACK = 0x90, // Previous Track (CIRCUMFLEX on Japanese keyboard) - AT = 0x91, // (NEC PC98) - COLON = 0x92, // (NEC PC98) - UNDERLINE = 0x93, // (NEC PC98) - KANJI = 0x94, // (Japanese keyboard) - STOP = 0x95, // (NEC PC98) - AX = 0x96, // (Japan AX) - UNLABELED = 0x97, // (J3100) - NEXTTRACK = 0x99, // Next Track - NUMPADENTER = 0x9C, // Enter on numeric keypad - RCONTROL = 0x9D, - MUTE = 0xA0, // Mute - CALCULATOR = 0xA1, // Calculator - PLAYPAUSE = 0xA2, // Play / Pause - MEDIASTOP = 0xA4, // Media Stop - VOLUMEDOWN = 0xAE, // Volume - - VOLUMEUP = 0xB0, // Volume + - WEBHOME = 0xB2, // Web home - NUMPADCOMMA = 0xB3, // , on numeric keypad (NEC PC98) - DIVIDE = 0xB5, // / on numeric keypad - SYSRQ = 0xB7, // Also called print screen - RMENU = 0xB8, // right Alt - PAUSE = 0xC5, // Pause - HOME = 0xC7, // Home on arrow keypad - UP = 0xC8, // UpArrow on arrow keypad - PGUP = 0xC9, // PgUp on arrow keypad - LEFT = 0xCB, // LeftArrow on arrow keypad - RIGHT = 0xCD, // RightArrow on arrow keypad - END = 0xCF, // End on arrow keypad - DOWN = 0xD0, // DownArrow on arrow keypad - PGDOWN = 0xD1, // PgDn on arrow keypad - INSERT = 0xD2, // Insert on arrow keypad - DELETE = 0xD3, // Delete on arrow keypad - LWIN = 0xDB, // Left Windows key - RWIN = 0xDC, // Right Windows key - APPS = 0xDD, // AppMenu key - POWER = 0xDE, // System Power - SLEEP = 0xDF, // System Sleep - WAKE = 0xE3, // System Wake - WEBSEARCH = 0xE5, // Web Search - WEBFAVORITES= 0xE6, // Web Favorites - WEBREFRESH = 0xE7, // Web Refresh - WEBSTOP = 0xE8, // Web Stop - WEBFORWARD = 0xE9, // Web Forward - WEBBACK = 0xEA, // Web Back - MYCOMPUTER = 0xEB, // My Computer - MAIL = 0xEC, // Mail - MEDIASELECT = 0xED, // Media Select - - CharOnly = 0xFF, // Set when the keysym is 0 but the - // character is set. This happens with many - // international characters or reassigned - // characters. - - Mouse0 = 0x100, // Mouse button events can be handled as - Mouse1 = 0x101, // keypresses too. - Mouse2 = 0x102, - Mouse3 = 0x103, - Mouse4 = 0x104, - Mouse5 = 0x105, - Mouse6 = 0x106, - Mouse7 = 0x107, - } - -// Sigh. I guess we have to do this for Monster at some poing anyway, -// so this work isn't completely wasted. Later we can make a generic -// conversion between OIS-keysyms, SDL-keysyms and others to the -// Monster keysyms. It sucks that everybody tries to reinvent the -// wheel as often as they can, but that's the way it goes. - -const char[][] keysymToString = -[ - KC.UNASSIGNED : "UNASSIGNED", - KC.ESCAPE : "escape", - KC.N1 : "1", - KC.N2 : "2", - KC.N3 : "3", - KC.N4 : "4", - KC.N5 : "5", - KC.N6 : "6", - KC.N7 : "7", - KC.N8 : "8", - KC.N9 : "9", - KC.N0 : "0", - KC.MINUS : "minus", - KC.EQUALS : "equals", - KC.BACK : "backspace", - KC.TAB : "tab", - KC.Q : "q", - KC.W : "w", - KC.E : "e", - KC.R : "r", - KC.T : "t", - KC.Y : "y", - KC.U : "u", - KC.I : "i", - KC.O : "o", - KC.P : "p", - KC.LBRACKET : "{", - KC.RBRACKET : "}", - KC.RETURN : "enter", - KC.LCONTROL : "left_ctrl", - KC.A : "a", - KC.S : "s", - KC.D : "d", - KC.F : "f", - KC.G : "g", - KC.H : "h", - KC.J : "j", - KC.K : "k", - KC.L : "l", - KC.SEMICOLON : "semicolon", - KC.APOSTROPHE : "apostrophe", - KC.GRAVE : "grave", - KC.LSHIFT : "left_shift", - KC.BACKSLASH : "backslash", - KC.Z : "z", - KC.X : "x", - KC.C : "c", - KC.V : "v", - KC.B : "b", - KC.N : "n", - KC.M : "m", - KC.COMMA : "comma", - KC.PERIOD : "period", - KC.SLASH : "slash", - KC.RSHIFT : "right_shift", - KC.MULTIPLY : "numpad_mult", - KC.LMENU : "left_alt", - KC.SPACE : "space", - KC.CAPITAL : "capital", - KC.F1 : "f1", - KC.F2 : "f2", - KC.F3 : "f3", - KC.F4 : "f4", - KC.F5 : "f5", - KC.F6 : "f6", - KC.F7 : "f7", - KC.F8 : "f8", - KC.F9 : "f9", - KC.F10 : "f10", - KC.NUMLOCK : "numlock", - KC.SCROLL : "scroll", - KC.NUMPAD7 : "numpad_7", - KC.NUMPAD8 : "numpad_8", - KC.NUMPAD9 : "numpad_9", - KC.SUBTRACT : "numpad_minus", - KC.NUMPAD4 : "numpad_4", - KC.NUMPAD5 : "numpad_5", - KC.NUMPAD6 : "numpad_6", - KC.ADD : "numpad_plus", - KC.NUMPAD1 : "numpad_1", - KC.NUMPAD2 : "numpad_2", - KC.NUMPAD3 : "numpad_3", - KC.NUMPAD0 : "numpad_0", - KC.DECIMAL : "numpad_period", - KC.OEM_102 : "oem102", - KC.F11 : "f11", - KC.F12 : "f12", - KC.F13 : "f13", - KC.F14 : "f14", - KC.F15 : "f15", - KC.KANA : "kana", - KC.ABNT_C1 : "abnt_c1", - KC.CONVERT : "convert", - KC.NOCONVERT : "noconvert", - KC.YEN : "yen", - KC.ABNT_C2 : "abnt_c2", - KC.NUMPADEQUALS: "numpad_equals", - KC.PREVTRACK : "prev_track", - KC.AT : "at", - KC.COLON : "colon", - KC.UNDERLINE : "underline", - KC.KANJI : "kanji", - KC.STOP : "stop", - KC.AX : "ax", - KC.UNLABELED : "unlabeled", - KC.NEXTTRACK : "next_track", - KC.NUMPADENTER : "numpad_enter", - KC.RCONTROL : "right_control", - KC.MUTE : "mute", - KC.CALCULATOR : "calculator", - KC.PLAYPAUSE : "play_pause", - KC.MEDIASTOP : "media_stop", - KC.VOLUMEDOWN : "volume_down", - KC.VOLUMEUP : "volume_up", - KC.WEBHOME : "webhome", - KC.NUMPADCOMMA : "numpad_comma", - KC.DIVIDE : "numpad_divide", - KC.SYSRQ : "print_screen", - KC.RMENU : "right_alt", - KC.PAUSE : "pause", - KC.HOME : "home", - KC.UP : "up", - KC.PGUP : "page_up", - KC.LEFT : "left", - KC.RIGHT : "right", - KC.END : "end", - KC.DOWN : "down", - KC.PGDOWN : "page_down", - KC.INSERT : "insert", - KC.DELETE : "delete", - KC.LWIN : "left_win", - KC.RWIN : "right_win", - KC.APPS : "app_menu", - KC.POWER : "power", - KC.SLEEP : "sleep", - KC.WAKE : "wake", - KC.WEBSEARCH : "web_search", - KC.WEBFAVORITES: "web_favorites", - KC.WEBREFRESH : "web_refresh", - KC.WEBSTOP : "web_stop", - KC.WEBFORWARD : "web_forward", - KC.WEBBACK : "web_back", - KC.MYCOMPUTER : "my_computer", - KC.MAIL : "mail", - KC.MEDIASELECT : "media_select", - - - KC.CharOnly : "CHAR_ONLY", // Set when the keysym is 0 but the - // character is set. This happens - // with many international - // characters or reassigned - // characters in OIS (and it - // SUCKS.) - - KC.Mouse0 : "mouse0", - KC.Mouse1 : "mouse1", - KC.Mouse2 : "mouse2", - KC.Mouse3 : "mouse3", - KC.Mouse4 : "mouse4", - KC.Mouse5 : "mouse5", - KC.Mouse6 : "mouse6", - KC.Mouse7 : "mouse7", - ]; - -enum ComponentType : int - { - Unknown = 0, - Button = 1, // ie. Key, mouse button, joy button, etc - Axis = 2, // ie. A joystick or mouse axis - Slider = 3, // - POV = 4, // ie. Arrow direction keys - Vector3 = 5 // ie. WiiMote orientation - } - -align(4) struct Axis -{ - ComponentType type; - int abs, rel; - bool absOnly; -} - -// The C++ size of Axis is 16 -static assert(Axis.sizeof == 16); - -struct MouseState -{ - /* Represents the height/width of your display area.. used if mouse - clipping or mouse grabbed in case of X11 - defaults to 50.. Make - sure to set this and change when your size changes.. */ - int width, height; - - // X Axis component - Axis X; - - // Y Axis Component - Axis Y; - - // Z Axis Component - Axis Z; - - // represents all buttons - bit position indicates button down - int buttons; - - // Button down test - bool buttonDown( MB button ) - { - return (buttons & ( 1 << button )) != 0; - } -} - -// Check that we match the C++ size -static assert(MouseState.sizeof == 60); diff --git a/old_d_version/ogre/cpp_framelistener.cpp b/old_d_version/ogre/cpp_framelistener.cpp deleted file mode 100644 index 8c7a37044..000000000 --- a/old_d_version/ogre/cpp_framelistener.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// Get current camera orientation, in the form of 'front' and 'up' -// vectors. -extern "C" void ogre_getCameraOrientation(float *fx, float *fy, float *fz, - float *ux, float *uy, float *uz) -{ - Vector3 front = mCamera->getDirection(); - Vector3 up = mCamera->getUp(); - *fx = front[0]; - *fy = -front[2]; - *fz = front[1]; - *ux = up[0]; - *uy = -up[2]; - *uz = up[1]; -} - -// Move camera -extern "C" void ogre_moveCamera(float x, float y, float z) -{ - // Transforms Morrowind coordinates to OGRE coordinates. The camera - // is not affected by the rotation of the root node, so we must - // transform this manually. - mCamera->setPosition(Vector3(x,z+90,-y)); -} - -// Rotate camera using Morrowind rotation specifiers -extern "C" void ogre_setCameraRotation(float r1, float r2, float r3) -{ - // TODO: This translation is probably not correct, but for now I - // have no reference point. Fix it later when we teleport from one - // cell to another, so we have something to compare against. - - // Rotate around X axis - Quaternion xr(Radian(-r1), Vector3::UNIT_X); - // Rotate around Y axis - Quaternion yr(Radian(r3+3.14), Vector3::UNIT_Y); - // Rotate around Z axis - Quaternion zr(Radian(-r2), Vector3::UNIT_Z); - - // Rotates first around z, then y, then x - mCamera->setOrientation(xr*yr*zr); -} diff --git a/old_d_version/ogre/cpp_interface.cpp b/old_d_version/ogre/cpp_interface.cpp deleted file mode 100644 index 98df9125e..000000000 --- a/old_d_version/ogre/cpp_interface.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// Copy a scene node and all its children -void cloneNode(SceneNode *from, SceneNode *to, char* name) -{ - to->setPosition(from->getPosition()); - to->setOrientation(from->getOrientation()); - to->setScale(from->getScale()); - - SceneNode::ObjectIterator it = from->getAttachedObjectIterator(); - while(it.hasMoreElements()) - { - // We can't handle non-entities. - Entity *e = dynamic_cast (it.getNext()); - if(e) - { - e = e->clone(String(name) + ":" + e->getName()); - to->attachObject(e); - } - } - - // Recursively clone all child nodes - SceneNode::ChildNodeIterator it2 = from->getChildIterator(); - while(it2.hasMoreElements()) - { - cloneNode((SceneNode*)it2.getNext(), to->createChildSceneNode(), name); - } -} - -// Supposed to insert a copy of the node, for now it just inserts the -// actual node. -extern "C" SceneNode *ogre_insertNode(SceneNode *base, char* name, - float *pos, float *quat, - float scale) -{ - //std::cout << "ogre_insertNode(" << name << ")\n"; - SceneNode *node = mwRoot->createChildSceneNode(name); - - // Make a copy of the node - cloneNode(base, node, name); - - // Apply transformations - node->setPosition(pos[0], pos[1], pos[2]); - node->setOrientation(quat[0], quat[1], quat[2], quat[3]); - - node->setScale(scale, scale, scale); - - return node; -} - -// Get the world transformation of a node (the total transformation of -// this node and all parent nodes). Return it as a translation -// (3-vector) and a rotation / scaling part (3x3 matrix) -extern "C" void ogre_getWorldTransform(SceneNode *node, - float *trans, // Storage for translation - float *matrix)// For 3x3 matrix -{ - // Get the world transformation first - Matrix4 trafo; - node->getWorldTransforms(&trafo); - - // Extract the translation part and pass it to the caller - Vector3 tr = trafo.getTrans(); - trans[0] = tr[0]; - trans[1] = tr[1]; - trans[2] = tr[2]; - - // Next extract the matrix - Matrix3 mat; - trafo.extract3x3Matrix(mat); - matrix[0] = mat[0][0]; - matrix[1] = mat[0][1]; - matrix[2] = mat[0][2]; - matrix[3] = mat[1][0]; - matrix[4] = mat[1][1]; - matrix[5] = mat[1][2]; - matrix[6] = mat[2][0]; - matrix[7] = mat[2][1]; - matrix[8] = mat[2][2]; -} - -// Create the water plane. It doesn't really resemble "water" yet -// though. -extern "C" void ogre_createWater(float level) -{ - // Create a plane aligned with the xy-plane. - MeshManager::getSingleton().createPlane("water", - ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Plane(Vector3::UNIT_Z, level), - 150000,150000 - ); - Entity *ent = mSceneMgr->createEntity( "WaterEntity", "water" ); - mwRoot->createChildSceneNode()->attachObject(ent); - ent->setCastShadows(false); -} - -extern "C" SceneNode *ogre_getDetachedNode() -{ - SceneNode *node = mwRoot->createChildSceneNode(); - mwRoot->removeChild(node); - return node; -} - -extern "C" SceneNode* ogre_createNode( - char *name, - float *trafo, - SceneNode *parent, - int32_t noRot) -{ - //std::cout << "ogre_createNode(" << name << ")"; - SceneNode *node = parent->createChildSceneNode(name); - //std::cout << " ... done\n"; - - // First is the translation vector - - // TODO should be "if(!noRot)" only for exterior cells!? Yay for - // consistency. Apparently, the displacement of the base node in NIF - // files must be ignored for meshes in interior cells, but not for - // exterior cells. Or at least that's my hypothesis, and it seems - // work. There might be some other NIF trickery going on though, you - // never know when you're reverse engineering someone else's file - // format. We will handle this later. - if(!noRot) - node->setPosition(trafo[0], trafo[1], trafo[2]); - - // Then a 3x3 rotation matrix. - if(!noRot) - node->setOrientation(Quaternion(Matrix3(trafo[3], trafo[4], trafo[5], - trafo[6], trafo[7], trafo[8], - trafo[9], trafo[10], trafo[11] - ))); - - // Scale is at the end - node->setScale(trafo[12],trafo[12],trafo[12]); - - return node; -} diff --git a/old_d_version/ogre/meshloader.d b/old_d_version/ogre/meshloader.d deleted file mode 100644 index 5065cc87a..000000000 --- a/old_d_version/ogre/meshloader.d +++ /dev/null @@ -1,391 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (meshloader.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module ogre.meshloader; - -import std.stdio; -import std.stream; - -import nif.nif; -import nif.record; - -import core.resource; -import ogre.bindings; - -import bullet.bindings; - -import util.uniquename; - -/* - There are some problems that will have to be looked into later: - - - Some meshes crash Ogre when shadows are turned on. (Not tested in - newer versions of Ogre). Shadows are completely disabled for now. - - There are obviously some boundry problems, some times the mesh - disappears even though some part of it is inside the screen. This - is especially a problem with animated meshes, since the animation - might step outside the original bounding box. - */ - -MeshLoader meshLoader; - -struct MeshLoader -{ - // Not sure how to handle the bounding box, just ignore it for now. - - char[] baseName; // NIF file name. Used in scene node names etc. so - // that we can identify where they came from in - // case of error messages. - - // Load a NIF mesh. Assumes nifMesh is already opened. This creates - // a "template" scene node containing this mesh, and removes it from - // the main scene. This node can later be "cloned" so that multiple - // instances of the object can be inserted into the world without - // inserting the mesh more than once. - void loadMesh(char[] name, out NodePtr base, out BulletShape shape) - { - baseName = name; - - // Check if the first record is a node - Node n = cast(Node) nifMesh.records[0]; - - if(n is null) - { - // TODO: Figure out what to do in this case, we should - // probably throw. - writefln("NIF '%s' IS NOT A MESH", name); - return; - } - - // Get a fresh SceneNode and detatch it from the root. We use this - // as the base for our mesh. - base = ogre_getDetachedNode(); - - // Recursively insert nodes (don't rotate the first node) - insertNode(n, base, 0, true); - - // Get the final shape, if any - shape = bullet_getFinalShape(); - - return base; - } - - private: - - void insertNode(Node data, NodePtr parent, - int flags, - bool noRot = false) - { - // Add the flags to the previous node's flags - flags = data.flags | flags; - - // Create a scene node, move and rotate it into place. The name - // must be unique, however we might have to recognize some special - // names later, in order to attach arms and legs on NPCs - // etc. Always ignore transformation of the first node? This is a - // problem, I don't know when to do this and when not to. Neither - // is always right. Update: I originally thought noRot should be - // false for exteriors and true for interiors, but this isn't so. - NodePtr node = ogre_createNode(UniqueName(data.name).ptr, &data.trafo, - parent, cast(int)noRot); - - // Handle any general properties here - - // Call functions that do node-specific things, like handleNiNode - // or handleNiTriShape. - { - NiNode n = cast(NiNode)data; - if(n !is null) - // Handle the NiNode, and any children it might have - handleNiNode(n, node, flags); - } - - { - NiTriShape n = cast(NiTriShape)data; - if(n !is null) - // Trishape, with a mesh - handleNiTriShape(n, node, flags); - } - } - - void handleNiNode(NiNode data, NodePtr node, int flags) - { - // Ignore sound activators and similar objects. - NiStringExtraData d = cast(NiStringExtraData) data.extra; - if(d !is null) - { - // Marker objects are only visible in the editor. We - // completely ignore them. - if(d.string == "MRK") - return; - - // No collision - if(d.string == "NCO") - flags |= 0x800; // Temporary internal marker - } - - // Handle any effects here - - // In the cases where meshes have skeletal animations, we must - // insert the children as bones in a skeleton instead, like we - // originally did for all nodes. Update: A much better way is to - // first insert the nodes normally, and then create the - // skeleton. The nodes can then be moved one by one over to the - // appropriate bones. - - // Check the controller - auto cont = data.controller; - while(cont !is null) - { - auto kc = cast(NiKeyframeController)cont; - auto pc = cast(NiPathController)cont; - if(kc !is null) - { - /* - writefln("Found keyframe controller"); - writefln(" Node name was: %s", data.name); - assert(cont.target is data); - - auto kcd = kc.data; - writefln(" Types: %s %s %s", - kcd.rotType, kcd.traType, kcd.scaleType); - */ - - /* - Adding keyframes: - - Skeleton -> Animation -> NodeAnimationTrack nt; - - TransformKeyFrame * tf = nt->createNodeKeyFrame(time); - tf->setTranslate(Vector3); - tf->setScale(Vector3); - tf->setRotation(Quaternion); - - nt->applyToNode(node, time); - evt - Animation an; - an->apply(skeleton, time); - */ - } - else if(pc !is null) - { - //writefln("Found path controller"); - assert(cont.target is data); - } - //else writefln("Other controller (%s)", cont); - cont = cont.next; - } - - // Loop through children - foreach(Node n; data.children) - insertNode(n, node, flags); - } - - void handleNiTriShape(NiTriShape shape, NodePtr node, int flags) - { - char[] texture; - char[] material; - char[] newName = UniqueName(baseName); - NiMaterialProperty mp; - - // Special alpha settings, if the NiAlphaProperty is present - int alphaFlags = -1; - ubyte alphaTest; - - bool hidden = (flags & 0x01) != 0; // Not displayed - bool collide = (flags & 0x02) != 0; // Use this mesh for collision - bool bbcollide = (flags & 0x04) != 0; // Use bounding box for - // collision - // Always use mesh collision for now - if(bbcollide) collide = true; - bbcollide = false; - - // Things marked "NCO" should not collide with anything. - if(flags & 0x800) - { collide = false; bbcollide=false; } - - // Skip the entire material phase for hidden nodes - if(hidden) goto nomaterial; - - // Scan the property list for textures - foreach(Property p; shape.properties) - { - // NiTexturingProperty block - { - NiTexturingProperty t = cast(NiTexturingProperty) p; - if(t !is null && t.textures[0].inUse) - { - // Ignore all other options for now - NiSourceTexture st = t.textures[0].texture; - if(st.external) - { - // Find the resource for this texture - TextureIndex ti = resources.lookupTexture(st.filename); - // Insert a manual loader into OGRE - // ti.load(); - - // Get the resource name. We use getNewName to get - // the real texture name, not the lookup - // name. NewName has been converted to .dds if - // necessary, to match the file name in the bsa - // archives. - texture = ti.getNewName(); - } - else - { - // Internal textures - texture = "BLAH"; - writefln("Internal texture, cannot read this yet."); - writefln("Final resource name: '%s'", texture); - } - continue; - } - } - - // NiAlphaProperty - { - NiAlphaProperty a = cast(NiAlphaProperty) p; - if(a !is null) - { - alphaFlags = a.flags; - alphaTest = a.threshold; - } - } - - // NiMaterialProperty block - { - NiMaterialProperty tmp = cast(NiMaterialProperty) p; - if(tmp !is null) - { - if(mp !is null) writefln("WARNING: More than one material!"); - mp = tmp; - material = newName; - continue; - } - } - } - // Get a pointer to the texture name - char* texturePtr; - if(texture.length) texturePtr = toStringz(texture); - else texturePtr = null; - - // Create the material - if(material.length) - // A material is present. Use it. - ogre_createMaterial(material.ptr, mp.ambient.array.ptr, - mp.diffuse.array.ptr, - mp.specular.array.ptr, mp.emissive.array.ptr, - mp.glossiness, mp.alpha, texturePtr, - alphaFlags, alphaTest); - else if(texturePtr) - { - // Texture, but no material. Make a default one. - writefln("WARNING: Making default material for %s", texture); - float[3] zero; - float[3] one; - zero[] = 0.0; - one[] = 1.0; - - ogre_createMaterial(newName.ptr, one.ptr, one.ptr, zero.ptr, zero.ptr, - 0.0, 1.0, texturePtr, alphaFlags, alphaTest); - } - - nomaterial: - - with(shape.data) - { - //writefln("Number of vertices: ", vertices.length); - - float *normalsPtr; - float *colorsPtr; - float *uvsPtr; - short *facesPtr; - - // Point pointers into the correct arrays, if they are present. If - // not, the pointers retain their values of null. - if(normals.length) normalsPtr = normals.ptr; - if(colors.length) colorsPtr = colors.ptr; - if(uvlist.length) uvsPtr = uvlist.ptr; - if(triangles.length) facesPtr = triangles.ptr; - - float - minX = float.infinity, - minY = float.infinity, - minZ = float.infinity, - maxX = -float.infinity, - maxY = -float.infinity, - maxZ = -float.infinity; - - // Calculate the bounding box. TODO: This is really a - // hack. IIRC the bounding box supplied by the NIF could not - // be trusted, but I can't remember why :/ - for( int i; i < vertices.length; i+=3 ) - { - if( vertices[i] < minX ) minX = vertices[i]; - if( vertices[i+1] < minY ) minY = vertices[i+1]; - if( vertices[i+2] < minZ) minZ = vertices[i+2]; - - if( vertices[i] > maxX) maxX = vertices[i]; - if( vertices[i+1] > maxY) maxY = vertices[i+1]; - if( vertices[i+2] > maxZ) maxZ = vertices[i+2]; - } - - // Get the node world transformation, needed to set up - // the collision shape properly. - float[3] trans; - float[9] matrix; - ogre_getWorldTransform(node, trans.ptr, matrix.ptr); - - // Next we must create the actual OGRE mesh and the collision - // objects, based on the flags we have been given. TODO: I - // guess the NIF bounding box is better than the one we have - // calculated ourselves? This code definitely doesn't work, - // but I haven't look into why yet. - assert(!bbcollide); - if(bbcollide) - // Insert the bounding box into the collision system - bullet_createBoxShape(minX, minY, minZ, maxX, maxY, maxZ, - trans.ptr, matrix.ptr); - - // Create a bullet collision shape from the trimesh. Pass - // along the world transformation as well, since we must - // transform the trimesh data manually. - else if(collide) - { - assert(facesPtr !is null, - "cannot create collision shape without a mesh"); - bullet_createTriShape(triangles.length, facesPtr, - vertices.length, vertices.ptr, - trans.ptr, matrix.ptr); - } - - // Create the ogre mesh, associate it with the node. Skip for - // hidden nodes. - if(!hidden) - ogre_createMesh(newName.ptr, vertices.length, vertices.ptr, - normalsPtr, colorsPtr, uvsPtr, triangles.length, - facesPtr, radius, material.ptr, minX, minY, minZ, - maxX, maxY, maxZ, node); - } - } -} diff --git a/old_d_version/openmw.d b/old_d_version/openmw.d deleted file mode 100644 index 095e8cdd8..000000000 --- a/old_d_version/openmw.d +++ /dev/null @@ -1,471 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008-2009 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (openmw.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module openmw; - -import std.stdio; -import std.string; -import std.cstream; -import std.file; - -import ogre.ogre; -import ogre.bindings; -import gui.bindings; -import gui.gui; - -import bullet.bullet; - -import scene.celldata; -import scene.soundlist; -import scene.gamesettings; -import scene.player; - -import core.resource; -import core.memory; -import core.config; - -import monster.util.string; -import monster.vm.mclass; -import monster.vm.dbg; -import mscripts.setup; - -import sound.audio; - -import input.events; - -import terrain.terrain; - -// Set up exit handler -alias void function() c_func; -extern(C) int atexit(c_func); - -bool cleanExit = false; - -void exitHandler() -{ - // If we exit uncleanly, print the function stack. - if(!cleanExit) - writefln(dbg.getTrace()); -} - - -//* -import std.gc; -import gcstats; - -void poolSize() -{ - GCStats gc; - getStats(gc); - writefln("Pool size: ", comma(gc.poolsize)); - writefln("Used size: ", comma(gc.usedsize)); -} -//*/ - -void main(char[][] args) -{ - bool render = true; - bool help = false; - bool resetKeys = false; - bool showOgreFlag = false; - bool debugOut = false; - bool extTest = false; - bool doGen = false; - bool nextSave = false; - bool loadSave = false; - - // Some examples to try: - // - // "Abandoned Shipwreck, Upper Level"; - // "Gro-Bagrat Plantation"; - // "Abinabi"; - // "Abebaal Egg Mine"; - // "Ald-ruhn, Ald Skar Inn"; - // "Koal Cave"; - // "Ald-ruhn, Arobar Manor Bedrooms" - // "Sud"; - // "Vivec, The Lizard's Head"; - // "ToddTest"; - - // Cells to load - char[][] cells; - - // Savegame to load - char[] savefile; - - foreach(char[] a; args[1..$]) - if(a == "-n") render = false; - else if(a == "-ex") extTest = true; - else if(a == "-gen") doGen = true; - else if(a == "-h") help=true; - else if(a == "-rk") resetKeys = true; - else if(a == "-oc") showOgreFlag = true; - else if(a == "-ns") config.noSound = true; - else if(a == "-save") nextSave = true; - else if(a == "-debug") - { - // Enable Monster debug output - dbg.dbgOut = dout; - - // Tell OGRE to do the same later on - debugOut = true; - } - else if(nextSave) - { - savefile = a; - nextSave = false; - } - else cells ~= a; - - if(cells.length > 1) - { - writefln("More than one cell specified, rendering disabled"); - render=false; - } - - void showHelp() - { - writefln("Syntax: %s [options] cell-name [cell-name]", args[0]); - writefln(" Options:"); - writefln(" -n Only load, do not render"); - writefln(" -ex Test the terrain system"); - writefln(" -gen Generate landscape cache"); - writefln(" -rk Reset key bindings to default"); - writefln(" -oc Show the Ogre config dialogue"); - writefln(" -ns Completely disable sound"); - writefln(" -debug Print debug information"); - writefln(" -save Load cell/pos from savegame"); - writefln(" -h Show this help"); - writefln(""); - writefln("Specifying more than one cell implies -n"); - } - - if(help) - { - showHelp(); - return; - } - - initializeMemoryRegions(); - initMonsterScripts(); - - // This is getting increasingly hackish, but this entire engine - // design is now quickly outgrowing its usefulness, and a rewrite is - // coming soon anyway. - PlayerSaveInfo pi; - if(savefile != "") - { - if(cells.length) - { - writefln("Please don't specify both a savegame file (%s) and cell names (%s)", savefile, cells); - return; - } - - loadSave = true; - writefln("Loading savegame %s", savefile); - pi = importSavegame(savefile); - writefln(" Player name: %s", pi.playerName); - writefln(" Cell name: %s", pi.cellName); - writefln(" Pos: %s", pi.pos.position); - writefln(" Rot: %s", pi.pos.rotation); - - cells = [pi.cellName]; - } - - config.initialize(resetKeys); - scope(exit) config.writeConfig(); - - // Check if the data directory exists - if(!exists(config.dataDir) || !isdir(config.dataDir)) - { - writefln("Cannot find data directory '", config.dataDir, - "' - please edit openmw.ini."); - return; - } - - // If the -oc parameter is specified, we override any config - // setting. - if(showOgreFlag) config.finalOgreConfig = true; - - if(cells.length == 0) - if(config.defaultCell.length) - cells ~= config.defaultCell; - - if(cells.length == 1 && !loadSave) - config.defaultCell = cells[0]; - - if(cells.length == 0) - { - showHelp(); - return; - } - - if(!config.noSound) initializeSound(); - resources.initResources(); - - // Load all ESM and ESP files - loadTESFiles(config.gameFiles); - - scene.gamesettings.loadGameSettings(); - - CellData cd = cellList.get(); - - foreach(char[] cName; cells) - { - // Release the last cell data - cellList.release(cd); - - // Get a cell data holder and load an interior cell - cd = cellList.get(); - - try cd.loadIntCell(cName); - catch(Exception e) - { - writefln("\nUnable to load cell '%s'.", cName); - writefln("\nDetails: %s", e); - writefln(" -Perhaps this cell does not exist in your Morrowind language version? -Try specifying another cell name on the command line, or edit openmw.ini."); - return; - } - - // If we're loading from save, override the player position - if(loadSave) - *playerData.position = pi.pos; - } - - // Simple safety hack - NodePtr putObject(MeshIndex m, Placement *pos, float scale, - bool collide=false) - { - if(m is null) - writefln("WARNING: CANNOT PUT NULL OBJECT"); - else if(!m.isEmpty) - return placeObject(m, pos, scale, collide); - - //writefln("WARNING: CANNOT INSERT EMPTY MESH '%s'", m.getName); - return null; - } - - if(cd.inCell !is null) - // Set the name for the GUI (temporary hack) - gui_setCellName(cd.inCell.id.ptr); - - // Set up the exit handler - atexit(&exitHandler); - scope(exit) cleanExit = true; - - if(render) - { - // Warm up OGRE - setupOgre(debugOut); - scope(exit) cleanupOgre(); - - // Create the GUI system - initGUI(debugOut); - - // Set up Bullet - initBullet(); - scope(exit) cleanupBullet(); - - // Initialize the internal input and event manager. The - // lower-level input system (OIS) is initialized by the - // setupOgre() call further up. - initializeInput(); - - // Play some old tunes - if(extTest) - { - // Exterior cell - /* - Color c; - c.red = 180; - c.green = 180; - c.blue = 180; - setAmbient(c, c, c, 0); - - // Put in the water - ogre_createWater(cd.water); - - // Create an ugly sky - ogre_makeSky(); - */ - - initTerrain(doGen); - } - else - { - // Interior cell - assert(cd.inCell !is null); - setAmbient(cd.ambi.ambient, cd.ambi.sunlight, - cd.ambi.fog, cd.ambi.fogDensity); - - // Not all interior cells have water - if(cd.inCell.flags & CellFlags.HasWater) - ogre_createWater(cd.water); - - // Insert the meshes of statics into the scene - foreach(ref LiveStatic ls; cd.statics) - putObject(ls.m.model, ls.getPos(), ls.getScale(), true); - // Inventory lights - foreach(ref LiveLight ls; cd.lights) - { - NodePtr n = putObject(ls.m.model, ls.getPos(), ls.getScale()); - ls.lightNode = attachLight(n, ls.m.data.color, ls.m.data.radius); - if(!config.noSound) - { - Sound *s = ls.m.sound; - if(s) - { - ls.loopSound = soundScene.insert(s, true); - if(ls.loopSound) - { - auto p = ls.getPos(); - ls.loopSound.setPos(p.position[0], - p.position[1], - p.position[2]); - } - } - } - } - // Static lights - foreach(ref LiveLight ls; cd.statLights) - { - NodePtr n = putObject(ls.m.model, ls.getPos(), ls.getScale(), true); - ls.lightNode = attachLight(n, ls.m.data.color, ls.m.data.radius); - if(!config.noSound) - { - Sound *s = ls.m.sound; - if(s) - { - ls.loopSound = soundScene.insert(s, true); - if(ls.loopSound) - { - auto p = ls.getPos(); - ls.loopSound.setPos(p.position[0], - p.position[1], - p.position[2]); - } - } - } - } - // Misc items - foreach(ref LiveMisc ls; cd.miscItems) - putObject(ls.m.model, ls.getPos(), ls.getScale()); - /* - // NPCs (these are complicated, usually do not have normal meshes) - foreach(ref LiveNPC ls; cd.npcs) - putObject(ls.m.model, ls.getPos(), ls.getScale()); - */ - // Containers - foreach(ref LiveContainer ls; cd.containers) - putObject(ls.m.model, ls.getPos(), ls.getScale(), true); - // Doors - foreach(ref LiveDoor ls; cd.doors) - putObject(ls.m.model, ls.getPos(), ls.getScale()); - // Activators (including beds etc) - foreach(ref LiveActivator ls; cd.activators) - putObject(ls.m.model, ls.getPos(), ls.getScale(), true); - // Potions - foreach(ref LivePotion ls; cd.potions) - putObject(ls.m.model, ls.getPos(), ls.getScale()); - // Apparatus - foreach(ref LiveApparatus ls; cd.appas) - putObject(ls.m.model, ls.getPos(), ls.getScale()); - // Ingredients - foreach(ref LiveIngredient ls; cd.ingredients) - putObject(ls.m.model, ls.getPos(), ls.getScale()); - // Armors - foreach(ref LiveArmor ls; cd.armors) - putObject(ls.m.model, ls.getPos(), ls.getScale()); - // Weapons - foreach(ref LiveWeapon ls; cd.weapons) - putObject(ls.m.model, ls.getPos(), ls.getScale()); - // Books - foreach(ref LiveBook ls; cd.books) - putObject(ls.m.model, ls.getPos(), ls.getScale()); - // Clothes - foreach(ref LiveClothing ls; cd.clothes) - putObject(ls.m.model, ls.getPos(), ls.getScale()); - // Tools - foreach(ref LiveTool ls; cd.tools) - putObject(ls.m.model, ls.getPos(), ls.getScale()); - // Creatures (not displayed very well yet) - foreach(ref LiveCreature ls; cd.creatures) - putObject(ls.m.model, ls.getPos(), ls.getScale()); - - // End of interior cell - } - - // Run GUI system - startGUI(); - - // Play some old tunes - if(!config.noSound) - Music.play(); - - // Run it until the user tells us to quit - startRendering(); - } - else if(debugOut) writefln("Skipping rendering"); - - if(!config.noSound) - { - soundScene.kill(); - shutdownSound(); - } - - if(debugOut) - { - writefln(); - writefln("%d statics", cd.statics.length); - writefln("%d misc items", cd.miscItems.length); - writefln("%d inventory lights", cd.lights.length); - writefln("%d static lights", cd.statLights.length); - writefln("%d NPCs", cd.npcs.length); - writefln("%d containers", cd.containers.length); - writefln("%d doors", cd.doors.length); - writefln("%d activators", cd.activators.length); - writefln("%d potions", cd.potions.length); - writefln("%d apparatuses", cd.appas.length); - writefln("%d ingredients", cd.ingredients.length); - writefln("%d armors", cd.armors.length); - writefln("%d weapons", cd.weapons.length); - writefln("%d books", cd.books.length); - writefln("%d tools", cd.tools.length); - writefln("%d clothes", cd.clothes.length); - writefln("%d creatures", cd.creatures.length); - writefln(); - } - - // This isn't necessary but it's here for testing purposes. - cellList.release(cd); - - // Write some statistics - if(debugOut) - { - poolSize(); - writefln(esmRegion); - writefln("Total objects: ", MonsterClass.getTotalObjects); - } -} diff --git a/old_d_version/terrain/archive.d b/old_d_version/terrain/archive.d deleted file mode 100644 index 5f5d5fd80..000000000 --- a/old_d_version/terrain/archive.d +++ /dev/null @@ -1,461 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2009 Nicolay Korslund - WWW: http://openmw.sourceforge.net/ - - This file (archive.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - -*/ - -module terrain.archive; - -const float TEX_SCALE = 1.0/16; - -// This should be part of the generic cache system. -const int CACHE_MAGIC = 0x345AF815; - -import std.mmfile; -import std.string; -import std.stdio; -import terrain.myfile; - -version(Windows) - static int pageSize = 64*1024; -else - static int pageSize = 4*1024; - -extern(C) -{ - // Convert a texture index to string - char *d_terr_getTexName(int index) - { return g_archive.getString(index).ptr; } - - // Fill various hardware buffers from cache - void d_terr_fillVertexBuffer(MeshInfo *mi, float *buffer, ulong size) - { mi.fillVertexBuffer(buffer[0..size]); } - - void d_terr_fillIndexBuffer(MeshInfo *mi, ushort *buffer, ulong size) - { mi.fillIndexBuffer(buffer[0..size]); } - - void d_terr_fillAlphaBuffer(AlphaInfo *mi, ubyte *buffer, ulong size) - { mi.fillAlphaBuffer(buffer[0..size]); } - - // Get a given alpha map struct belonging to a mesh - AlphaInfo *d_terr_getAlphaInfo(MeshInfo *mi, int index) - { return mi.getAlphaInfo(index); } - - int d_terr_getAlphaSize() { return g_archive.alphaSize; } -} - -// Info about the entire quad. TODO: Some of this (such as the texture -// scale and probably the width and radius) can be generated at -// loadtime and is common for all quads on the same level. We could -// just make a QuadLevelInfo struct. -struct QuadInfo -{ - // Basic info - int cellX, cellY; - int level; - - // Bounding box info - float minHeight, maxHeight; - float worldWidth; - float boundingRadius; - - // True if we should make the given child - bool hasChild[4]; - - // Number of mesh segments in this quad - int meshNum; - - // Location of this quad in the main archive file. The size includes - // everything related to this quad, including mesh data, alpha maps, - // etc. - size_t offset, size; -} - -// Info about an alpha map belonging to a mesh -struct AlphaInfo -{ - // Position of the actual image data - ulong bufSize, bufOffset; - - // The texture name for this layer. The actual string is stored in - // the archive's string buffer. - int texName = -1; - int alphaName = -1; - - // Fill the alpha texture buffer - void fillAlphaBuffer(ubyte abuf[]) - { - assert(abuf.length == bufSize); - g_archive.copy(abuf.ptr, bufOffset, bufSize); - } -} -static assert(AlphaInfo.sizeof == 6*4); - -// Info about each submesh -// If you change this struct please check whether align(1) still fits. -align(1) -struct MeshInfo -{ - // Bounding box info - float minHeight, maxHeight; - float worldWidth; - - // Vertex and index numbers - int vertRows, vertCols; - - // Height offset to apply to all vertices - float heightOffset; - - // Size and offset of the vertex buffer - ulong vertBufSize, vertBufOffset; - - // Texture name. Index to the string table. - int texName = -1; - - // Number and offset of AlphaInfo blocks - int alphaNum; - ulong alphaOffset; - - // Fill the given vertex buffer - void fillVertexBuffer(float vdest[]) - { - // The height map and normals from the archive - byte *hmap = cast(byte*)g_archive.getRelSlice(vertBufOffset, vertBufSize).ptr; - // The generic part, containing the x,y coordinates and the uv - // maps. - float *gmap = g_archive.getVertexBuffer(getLevel()).ptr; - - // Destination pointer - float *vbuf = vdest.ptr; - assert(vdest.length == vertRows*vertCols*8); - - // Merge the two data sets together into the output buffer. - float offset = heightOffset; - for(int y=0; y= 0); - assert(getLevel() == 1); - AlphaInfo *res = cast(AlphaInfo*)g_archive.getRelSlice - (alphaOffset, alphaNum*AlphaInfo.sizeof); - res += num; - return res; - } -} -static assert(MeshInfo.sizeof == 14*4); - -// The first part of the .index file -struct ArchiveHeader -{ - // "Magic" number to make sure we're actually reading an archive - // file - int magic; - - // Total number of quads in the archive - int quads; - - // Level of the 'root' quad. There will only be one quad on this - // level. - int rootLevel; - - // Size of the alpha maps, in pixels along one side. - int alphaSize; - - // Number of strings in the string table - int stringNum; - - // Size of the string buffer - size_t stringSize; -} - -TerrainArchive g_archive; - -// This class handles the cached terrain data. -struct TerrainArchive -{ - MeshInfo *curMesh; - QuadInfo *curQuad; - QuadInfo *rootQuad; - - void openFile(char[] name) - { - mmf = new MmFile(name, - MmFile.Mode.Read, - 0, null, pageSize); - - // Read the index file first - MyFile ifile = new MyFile(name ~ ".index"); - - ArchiveHeader head; - ifile.fill(head); - - // Reads data into an array. Would be better if this was part of - // the stream. - - // Sanity check - assert(head.magic == CACHE_MAGIC); - assert(head.quads > 0 && head.quads < 8192); - - // Store header info - alphaSize = head.alphaSize; - - // Read all the quads - quadList = new QuadInfo[head.quads]; - ifile.fillArray(quadList); - - // Create an index of all the quads - foreach(int index, qn; quadList) - { - int x = qn.cellX; - int y = qn.cellY; - int l = qn.level; - - assert(l >= 1); - - quadMap[l][x][y] = index; - assert(index == quadMap[l][x][y]); - - // Store the root quad - if(l == head.rootLevel) - { - assert(rootQuad == null); - rootQuad = &quadList[index]; - } - else - assert(l < head.rootLevel); - } - - // Make sure the root was set - assert(rootQuad !is null); - - // Next read the string table. First read the main string buffer. - stringBuf = new char[head.stringSize]; - ifile.fillArray(stringBuf); - - // Then read the string offsets - int[] offsets = new int[head.stringNum]; - ifile.fillArray(offsets); - - // Set up the string table - char *strptr = stringBuf.ptr; - strings.length = head.stringNum; - foreach(int i, ref str; strings) - { - // toString(char*) returns the string up to the zero - // terminator byte - str = toString(strptr + offsets[i]); - assert(str.ptr + str.length <= - stringBuf.ptr + stringBuf.length); - } - delete offsets; - - // Read the vertex buffer data - int bufNum = head.rootLevel; - assert(bufNum == 7); - vertBufData.length = bufNum; - - // Fill the vertex buffers. Start at level 1. - for(int i=1;i=1 && level= 0); - assert(index < strings.length); - - return strings[index]; - } - - void doMap(size_t offset, size_t size) - { - assert(mmf !is null); - assert(size); - mapped = cast(ubyte[])mmf[offset..offset+size]; - assert(mapped.length == size); - } - - // Get a slice of a given buffer within the mapped window. The - // offset is relative to the start of the window, and the size must - // fit inside the window. - ubyte[] getRelSlice(size_t offset, size_t size) - { - assert(mapped.length); - - return mapped[offset..offset+size]; - } - - // Copy a given buffer from the file. The buffer might be a - // compressed stream, so it's important that the buffers are written - // in the same block sizes as they are read. (Ie. you can't write a - // buffer as one operation and read it as two, or vice versa. Also, - // buffers cannot overlap.) The offset is relative to the current - // mapped file window. - void copy(void *dst, size_t offset, size_t inSize) - { - ubyte source[] = getRelSlice(offset, inSize); - - // Just copy it for now - ubyte* dest = cast(ubyte*)dst; - dest[0..source.length] = source[]; - } -} diff --git a/old_d_version/terrain/bindings.d b/old_d_version/terrain/bindings.d deleted file mode 100644 index 145d1a593..000000000 --- a/old_d_version/terrain/bindings.d +++ /dev/null @@ -1,27 +0,0 @@ -module terrain.bindings; - -alias void *SceneNode; -alias void *Bounds; -alias void *MeshObj; - -// These are all defined in cpp_terrain.cpp: -extern(C): - -SceneNode terr_createChildNode(float relX, float relY, SceneNode); -void terr_destroyNode(SceneNode); -Bounds terr_makeBounds(float minHeight, float maxHeight, float width, SceneNode); -void terr_killBounds(Bounds); -float terr_getSqCamDist(Bounds); -MeshObj terr_makeMesh(SceneNode,void*,int,float); -void terr_killMesh(MeshObj); - -void terr_genData(); -void terr_setupRendering(); - -void terr_makeLandMaterial(char*,float); -ubyte *terr_makeAlphaLayer(char*,int); -void terr_closeAlpha(char*,char*,float); -void terr_cleanupAlpha(char*,void*,int); - -void terr_resize(void*,void*,int,int); -void terr_saveImage(void*,int,char*); diff --git a/old_d_version/terrain/cachewriter.d b/old_d_version/terrain/cachewriter.d deleted file mode 100644 index 61a52addb..000000000 --- a/old_d_version/terrain/cachewriter.d +++ /dev/null @@ -1,337 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2009 Nicolay Korslund - WWW: http://openmw.sourceforge.net/ - - This file (cachewriter.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - -*/ - -module terrain.cachewriter; - -import terrain.archive; - -import terrain.outbuffer; -import std.stdio, std.stream, std.string; -import terrain.myfile; -import std.math2; -import monster.util.string; -import monster.vm.dbg; - -// Helper structs -struct AlphaHolder -{ - AlphaInfo info; - - // Actual pixel buffer - ubyte[] buffer; -} - -struct MeshHolder -{ - MeshInfo info; - - // Actual buffers - byte[] vertexBuffer; - - // Alpha maps (if any) - AlphaHolder alphas[]; -} - -// A struct that gathers all the relevant quad data in one place. -struct QuadHolder -{ - QuadInfo info; - - MeshHolder meshes[]; -} - -struct CacheWriter -{ - // Opens the main archive file for output - void openFile(char[] fname) - { - mainFile = new File(fname, FileMode.OutNew); - iname = fname ~ ".index"; - - buf = new OutBuffer; - } - - void setParams(int mxLev, int alphSize) - { - maxLevel = mxLev; - alphaSize = alphSize; - - vertBuf.length = maxLevel; - } - - // Closes the main archive file and writes the index. - void finish() - { - mainFile.close(); - - // Write the index file - scope MyFile ofile = new MyFile(iname, FileMode.OutNew); - - // Header first - ArchiveHeader head; - head.magic = CACHE_MAGIC; - head.quads = quadList.length; - head.rootLevel = maxLevel; - head.alphaSize = alphaSize; - head.stringNum = stringList.length; - head.stringSize = totalStringLength; - ofile.dump(head); - - // Write the quads - ofile.dumpArray(quadList); - - // String table next. We need to sort it in order of the indices - // first. - char[][] strVector; - strVector.length = head.stringNum; - - foreach(char[] key, int value; stringList) - strVector[value] = key; - - // Next, write the strings to file while we fill in the offset - // list - int[] offsets = new int[head.stringNum]; - - size_t curOffs = 0; - for(int i=0; i level); - vertBuf[level] = buf; - } - - // Add a common index buffer - void setIndexBuffer(ushort[] buf) - { - indexBuf = buf; - } - - // Write a finished quad to the archive file. All the offsets and - // numbers in the *Info structs are filled in automatically based on - // the additional data in the Holder structs. - void writeQuad(ref QuadHolder qh) - { - scope auto _trc = new MTrace("writeQuad"); - - // Write the MeshInfo's first - int meshNum = qh.meshes.length; - - MeshInfo meshes[] = buf.write!(MeshInfo)(meshNum); - - float minh = float.infinity; - float maxh = -float.infinity; - - // Then write the mesh data in approximately the order it's read - for(int i=0; igetFarClipDistance(); - // Recreate the mesh if the view distance has increased - if ( vd > mMeshDistance ) - { - destroyMesh(); - createMesh(); - } - - Ogre::Vector3 p = mCamera->getDerivedPosition(); - p.x -= ((int)p.x % CELL_WIDTH); - p.z -= ((int)p.z % CELL_WIDTH); - - float h = (p.y + 2048)*2.0/CELL_WIDTH; - h *= h; - - mNode->setPosition(p.x, -p.z, -32 -h); - } - -private: - void createMesh() - { - float vd = mCamera->getFarClipDistance(); - - mMeshDistance = vd; - - vd = vd/CELL_WIDTH * 32; - - mMat = Ogre::MaterialManager::getSingleton(). - create("BaseLandMat", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - - Ogre::TextureUnitState* us = mMat->getTechnique(0)->getPass(0)->createTextureUnitState("_land_default.dds"); - us->setTextureScale(1.0f/vd,1.0f/vd); - - mMat->getTechnique(0)->getPass(0)->setDepthBias(-1); - - mObject = mSceneMgr->createManualObject("BaseLand"); - mObject->begin("BaseLandMat", Ogre::RenderOperation::OT_TRIANGLE_LIST); - - vd = mMeshDistance; - - const int HEIGHT = -2048 - 10; - - mObject->position(-vd,vd,HEIGHT); - mObject->textureCoord(0, 1); - - mObject->position(-vd,-vd,HEIGHT); - mObject->textureCoord(0, 0); - - mObject->position(vd,-vd,HEIGHT); - mObject->textureCoord(1, 0); - - mObject->position(vd,vd,HEIGHT); - mObject->textureCoord(1, 1); - - mObject->quad(0,1,2,3); - - mObject->end(); - - mNode = g_rootTerrainNode->createChildSceneNode(); - mNode->attachObject(mObject); - } - - void destroyMesh() - { - mNode->detachAllObjects(); - mSceneMgr->destroyManualObject(mObject); - mNode->getParentSceneNode()->removeAndDestroyChild(mNode->getName()); - - mMat->getCreator()->remove(mMat->getHandle()); - mMat = Ogre::MaterialPtr(); - } - - ///the created mesh - Ogre::ManualObject* mObject; - - ///The material for the mesh - Ogre::MaterialPtr mMat; - - ///scene node for the mesh - Ogre::SceneNode* mNode; - - ///In essence, the farViewDistance of the camera last frame - Ogre::Real mMeshDistance; -}; diff --git a/old_d_version/terrain/cpp_mesh.cpp b/old_d_version/terrain/cpp_mesh.cpp deleted file mode 100644 index f5f6a26f5..000000000 --- a/old_d_version/terrain/cpp_mesh.cpp +++ /dev/null @@ -1,286 +0,0 @@ -// The Ogre renderable used to hold and display the terrain meshes. -class TerrainMesh : public Ogre::Renderable, public Ogre::MovableObject -{ -public: - - TerrainMesh(Ogre::SceneNode *parent, const MeshInfo &info, - int level, float scale) - : Ogre::Renderable(), - Ogre::MovableObject() - { - TRACE("TerrainMesh()"); - - mLevel = level; - - // This is a bit messy, with everything in one function. We could - // split it up later. - - // Use MW coordinates all the way - assert(info.worldWidth > 0); - assert(info.minHeight <= info.maxHeight); - mBounds.setExtents(0,0,info.minHeight, - info.worldWidth, info.worldWidth, - info.maxHeight); - mCenter = mBounds.getCenter(); - mBoundingRadius = mBounds.getHalfSize().length(); - - // TODO: VertexData has a clone() function. This probably means we - // can set this up once and then clone it, to get a completely - // unnoticable increase in performance :) - mVertices = new VertexData(); - mVertices->vertexStart = 0; - mVertices->vertexCount = info.vertRows*info.vertCols; - - VertexDeclaration* vertexDecl = mVertices->vertexDeclaration; - size_t currOffset = 0; - - vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); - currOffset += VertexElement::getTypeSize(VET_FLOAT3); - - vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); - currOffset += VertexElement::getTypeSize(VET_FLOAT3); - - vertexDecl->addElement(0, currOffset, VET_FLOAT2, - VES_TEXTURE_COORDINATES, 0); - currOffset += VertexElement::getTypeSize(VET_FLOAT2); - - assert(vertexDecl->getVertexSize(0) == currOffset); - - HardwareVertexBufferSharedPtr mMainBuffer; - mMainBuffer = HardwareBufferManager::getSingleton().createVertexBuffer - ( - vertexDecl->getVertexSize(0), // size of one whole vertex - mVertices->vertexCount, // number of vertices - HardwareBuffer::HBU_STATIC_WRITE_ONLY, // usage - false); // no shadow buffer - - // Bind the data - mVertices->vertexBufferBinding->setBinding(0, mMainBuffer); - - // Fill the buffer - float* verts = static_cast - (mMainBuffer->lock(HardwareBuffer::HBL_DISCARD)); - info.fillVertexBuffer(verts,8*mVertices->vertexCount); - mMainBuffer->unlock(); - - // Create the index data holder - mIndices = new IndexData(); - mIndices->indexCount = 64*64*6; // TODO: Shouldn't be hard-coded - mIndices->indexBuffer = - HardwareBufferManager::getSingleton().createIndexBuffer - ( HardwareIndexBuffer::IT_16BIT, - mIndices->indexCount, - HardwareBuffer::HBU_STATIC_WRITE_ONLY, - false); - - // Fill the buffer with warm fuzzy archive data - unsigned short* indices = static_cast - (mIndices->indexBuffer->lock - (0, mIndices->indexBuffer->getSizeInBytes(), - HardwareBuffer::HBL_DISCARD)); - info.fillIndexBuffer(indices,mIndices->indexCount); - mIndices->indexBuffer->unlock(); - - // Finally, create the material - const std::string texName = info.getTexName(); - - // Set up the scene node. - mNode = parent->createChildSceneNode(); - mNode->attachObject(this); - - // Finally, create or retrieve the material - if(MaterialManager::getSingleton().resourceExists(texName)) - { - mMaterial = MaterialManager::getSingleton().getByName - (texName); - return; - } - - // No existing material. Create a new one. - mMaterial = MaterialManager::getSingleton().create - (texName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - - Pass* pass = mMaterial->getTechnique(0)->getPass(0); - pass->setLightingEnabled(false); - - if(level > 1) - { - // This material just has a normal texture - pass->createTextureUnitState(texName) - //->setTextureAddressingMode(TextureUnitState::TAM_CLAMP) - ; - } - else - { - assert(level == 1); - - // Get the background texture. TODO: We should get this from - // somewhere, no file names should be hard coded. The texture - // might exist as a .tga in earlier versions of the game, and - // we might also want to specify a different background - // texture on some meshes. - //const char *bgTex = info.getBackgroundTex(); - - const char *bgTex = "_land_default.dds"; - pass->createTextureUnitState(bgTex) - ->setTextureScale(scale,scale); - - // Loop through all the textures in this mesh - for(int tnum=0; tnumgetBuffer(); - pixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); - const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock(); - Ogre::uint8* pDest = static_cast(pixelBox.data); - - // Copy alpha data from file - alpha.fillAlphaBuffer(pDest,g_alphaSize*g_alphaSize); - - // Close the buffer - pixelBuffer->unlock(); - } - - pass = mMaterial->getTechnique(0)->createPass(); - pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); - pass->setLightingEnabled(false); - pass->setDepthFunction(Ogre::CMPF_EQUAL); - - Ogre::TextureUnitState* tus = pass->createTextureUnitState(alphaName); - //tus->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - - tus->setAlphaOperation(Ogre::LBX_BLEND_TEXTURE_ALPHA, - Ogre::LBS_TEXTURE, - Ogre::LBS_TEXTURE); - tus->setColourOperationEx(Ogre::LBX_BLEND_DIFFUSE_ALPHA, - Ogre::LBS_TEXTURE, - Ogre::LBS_TEXTURE); - tus->setIsAlpha(true); - - // Add the actual texture on top of the alpha map. - tus = pass->createTextureUnitState(tname); - tus->setColourOperationEx(Ogre::LBX_BLEND_DIFFUSE_ALPHA, - Ogre::LBS_TEXTURE, - Ogre::LBS_CURRENT); - - tus->setTextureScale(scale, scale); - } - } - } - - ~TerrainMesh() - { - assert(mNode); - mNode->detachAllObjects(); - mNode->getCreator()->destroySceneNode(mNode); - - // TODO: This still crashes on level1 meshes. Find out why! - if(mLevel!=1)delete mVertices; - delete mIndices; - } - - //----------------------------------------------------------------------- - // These are all Ogre functions that we have to override - //----------------------------------------------------------------------- - - // Internal Ogre function. We should call visitor->visit on all - // Renderables that are part of this object. In our case, this is - // only ourselves. - void visitRenderables(Renderable::Visitor* visitor, - bool debugRenderables = false) { - visitor->visit(this, 0, false); - } - - void getRenderOperation( Ogre::RenderOperation& op ) { - op.useIndexes = true; - op.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; - op.vertexData = mVertices; - op.indexData = mIndices; - } - - void getWorldTransforms( Ogre::Matrix4* xform ) const { - *xform = mNode->_getFullTransform(); - } - - const Ogre::Quaternion& getWorldOrientation(void) const { - return mNode->_getDerivedOrientation(); - } - - const Ogre::Vector3& getWorldPosition(void) const { - return mNode->_getDerivedPosition(); - } - - Ogre::Real getSquaredViewDepth(const Ogre::Camera *cam) const { - Ogre::Vector3 diff = mCenter - cam->getDerivedPosition(); - // Use squared length to avoid square root - return diff.squaredLength(); - } - - const Ogre::LightList& getLights(void) const { - if (mLightListDirty) { - getParentSceneNode()->getCreator()->_populateLightList - (mCenter, mBoundingRadius, mLightList); - mLightListDirty = false; - } - return mLightList; - } - virtual const Ogre::String& getMovableType( void ) const { - static Ogre::String t = "MW_TERRAIN"; - return t; - } - void _updateRenderQueue( Ogre::RenderQueue* queue ) { - mLightListDirty = true; - queue->addRenderable(this, mRenderQueueID); - } - const Ogre::AxisAlignedBox& getBoundingBox( void ) const - { - return mBounds; - } - - Ogre::Real getBoundingRadius(void) const { - return mBoundingRadius; - } - virtual const MaterialPtr& getMaterial(void) const - { return mMaterial; } - - //----------------------------------------------------------------------- - //----------------------------------------------------------------------- - -private: - - int mLevel; - - Ogre::SceneNode* mNode; - - Ogre::MaterialPtr mMaterial; - - Ogre::VertexData* mVertices; - Ogre::IndexData* mIndices; - - mutable bool mLightListDirty; - - Ogre::Real mBoundingRadius; - Ogre::AxisAlignedBox mBounds; - Ogre::Vector3 mCenter; -}; diff --git a/old_d_version/terrain/cpp_terrain.cpp b/old_d_version/terrain/cpp_terrain.cpp deleted file mode 100644 index ad2711036..000000000 --- a/old_d_version/terrain/cpp_terrain.cpp +++ /dev/null @@ -1,413 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2009 Jacob Essex, Nicolay Korslund - WWW: http://openmw.sourceforge.net/ - - This file (cpp_terrain.cpp) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - -*/ - -const int CELL_WIDTH = 8192; - -SceneNode *g_rootTerrainNode; -int g_alphaSize; - -struct MeshInfo; -struct AlphaInfo; - -// D functions -extern "C" -{ - void d_terr_superman(); - void d_terr_terrainUpdate(); - - char *d_terr_getTexName(int32_t); - - void d_terr_fillVertexBuffer(const MeshInfo*,float*,uint64_t); - void d_terr_fillIndexBuffer(const MeshInfo*,uint16_t*,uint64_t); - AlphaInfo *d_terr_getAlphaInfo(const MeshInfo*,int32_t); - - void d_terr_fillAlphaBuffer(const AlphaInfo*,uint8_t*,uint64_t); - - int32_t d_terr_getAlphaSize(); -} - -// Info about a submesh. This is a clone of the struct defined in -// archive.d. TODO: Make sure the D and C++ structs are of the same -// size and alignment. -struct MeshInfo -{ - // Bounding box info - float minHeight, maxHeight; - float worldWidth; - - // Vertex and index numbers - int32_t vertRows, vertCols; - - // Height offset to apply to all vertices - float heightOffset; - - // Size and offset of the vertex buffer - int64_t vertBufSize, vertBufOffset; - - // Texture name. Index to the string table. - int32_t texName; - - // Number and offset of AlphaInfo blocks - int32_t alphaNum; - uint64_t alphaOffset; - - inline void fillVertexBuffer(float *buffer, uint64_t size) const - { - d_terr_fillVertexBuffer(this, buffer, size); - } - - inline void fillIndexBuffer(uint16_t *buffer, uint64_t size) const - { - d_terr_fillIndexBuffer(this, buffer, size); - } - - inline char* getTexName() const - { - return d_terr_getTexName(texName); - } - - inline AlphaInfo *getAlphaInfo(int tnum) const - { - return d_terr_getAlphaInfo(this, tnum); - } -}; - -// Info about an alpha map belonging to a mesh -struct AlphaInfo -{ - // Position of the actual image data - uint64_t bufSize, bufOffset; - - // The texture name for this layer. The actual string is stored in - // the archive's string buffer. - int32_t texName; - int32_t alphaName; - - inline char* getTexName() const - { - return d_terr_getTexName(texName); - } - - inline char* getAlphaName() const - { - return d_terr_getTexName(alphaName); - } - - inline void fillAlphaBuffer(uint8_t *buffer, uint64_t size) const - { - return d_terr_fillAlphaBuffer(this, buffer, size); - } -}; - -#include "cpp_baseland.cpp" -#include "cpp_mesh.cpp" - -BaseLand *g_baseLand; - -class TerrainFrameListener : public FrameListener -{ -protected: - bool frameEnded(const FrameEvent& evt) - { - TRACE("Terrain frame"); - d_terr_terrainUpdate(); - if(g_baseLand) - g_baseLand->update(); - return true; - } -}; - -// Renders a material into a texture -Ogre::TexturePtr getRenderedTexture(Ogre::MaterialPtr mp, - const std::string& name, - int texSize, Ogre::PixelFormat tt) -{ - Ogre::CompositorPtr cp = Ogre::CompositorManager::getSingleton(). - create("Rtt_Comp", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - - Ogre::CompositionTargetPass* ctp = cp->createTechnique()->getOutputTargetPass(); - Ogre::CompositionPass* cpass = ctp->createPass(); - cpass->setType(Ogre::CompositionPass::PT_RENDERQUAD); - cpass->setMaterial(mp); - - // Create the destination texture - Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton(). - createManual(name + "_T", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, - texSize, - texSize, - 0, - tt, - Ogre::TU_RENDERTARGET - ); - - Ogre::RenderTexture* renderTexture = texture->getBuffer()->getRenderTarget(); - Ogre::Viewport* vp = renderTexture->addViewport(mCamera); - - Ogre::CompositorManager::getSingleton().addCompositor(vp, "Rtt_Comp"); - Ogre::CompositorManager::getSingleton().setCompositorEnabled(vp,"Rtt_Comp", true); - - renderTexture->update(); - - // Call the OGRE renderer. - Ogre::Root::getSingleton().renderOneFrame(); - - Ogre::CompositorManager::getSingleton().removeCompositor(vp, "Rtt_Comp"); - Ogre::CompositorManager::getSingleton().remove(cp->getHandle()); - - renderTexture->removeAllViewports(); - - return texture; -} - -// These are used between some functions below. Kinda messy. Since -// these are GLOBAL instances, they are terminated at program -// exit. However, OGRE itself is terminated before that, so we have to -// make sure we have no 'active' shared pointers after OGRE is -// finished (otherwise we get a segfault at exit.) -std::list createdResources; -Ogre::HardwarePixelBuffer *pixelBuffer; -MaterialPtr mat; - -// Functions called from D -extern "C" -{ - SceneNode* terr_createChildNode(float x, float y, - SceneNode *parent) - { - Ogre::Vector3 pos(x,y,0); - if(parent == NULL) - parent = g_rootTerrainNode; - - assert(parent); - return parent->createChildSceneNode(pos); - } - - void terr_destroyNode(SceneNode *node) - { - node->removeAndDestroyAllChildren(); - mSceneMgr->destroySceneNode(node); - } - - // TODO: We could make allocation a little more refined than new and - // delete. But that's true for everything here. A freelist based - // approach is best in most of these cases, as we have continuous - // allocation/deallocation of fixed-size structs. - Ogre::AxisAlignedBox *terr_makeBounds(float minHeight, float maxHeight, - float width, SceneNode* node) - { - TRACE("terr_makeBounds"); - AxisAlignedBox *mBounds = new AxisAlignedBox; - - assert(maxHeight >= minHeight); - - mBounds->setExtents(0,0,minHeight, - width,width,maxHeight); - - // Transform the box to world coordinates, so it can be compared - // with the camera later. - mBounds->transformAffine(node->_getFullTransform()); - - return mBounds; - } - - void terr_killBounds(AxisAlignedBox *bounds) - { - TRACE("terr_killBounds"); - delete bounds; - } - - float terr_getSqCamDist(AxisAlignedBox *mBounds) - { - TRACE("terr_getSqCamDist"); - Ogre::Vector3 cpos = mCamera->getDerivedPosition(); - Ogre::Vector3 diff(0, 0, 0); - diff.makeFloor(cpos - mBounds->getMinimum() ); - diff.makeCeil(cpos - mBounds->getMaximum() ); - return diff.squaredLength(); - } - - TerrainMesh *terr_makeMesh(SceneNode *parent, - MeshInfo *info, - int level, float scale) - { - return new TerrainMesh(parent, *info, level, scale); - } - - void terr_killMesh(TerrainMesh *mesh) - { - TRACE("terr_killMesh"); - delete mesh; - } - - // Set up the rendering system - void terr_setupRendering() - { - TRACE("terr_setupRendering()"); - // Make sure the C++ sizes match the D sizes, since the structs - // are shared between the two. - assert(sizeof(MeshInfo) == 14*4); - assert(sizeof(AlphaInfo) == 6*4); - - // Add the terrain directory as a resource location. TODO: Get the - // name from D. - ResourceGroupManager::getSingleton(). - addResourceLocation("cache/terrain/", "FileSystem", "General"); - - // Enter superman mode - mCamera->setFarClipDistance(40*CELL_WIDTH); - //ogre_setFog(0.7, 0.7, 0.7, 200, 32*CELL_WIDTH); - d_terr_superman(); - - // Create a root scene node first. The 'root' node is rotated to - // match the MW coordinate system - g_rootTerrainNode = mwRoot->createChildSceneNode("TERRAIN_ROOT"); - - // Add the base land. This is the ground beneath the actual - // terrain mesh that makes the terrain look infinite. - //g_baseLand = new BaseLand(); - - g_alphaSize = d_terr_getAlphaSize(); - - // Add the frame listener - mRoot->addFrameListener(new TerrainFrameListener); - } - - // The next four functions are called in the function genLevel2Map() - // only. This is very top-down-programming-ish and a bit messy, but - // that's what I get for mixing C++ and D like this. - void terr_makeLandMaterial(const char* name, float scale) - { - // Get a new material - mat = Ogre::MaterialManager::getSingleton(). - create(name, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - - // Put the default texture in the bottom 'layer', so that we don't - // end up seeing through the landscape. - Ogre::Pass* np = mat->getTechnique(0)->getPass(0); - np->setLightingEnabled(false); - np->createTextureUnitState("_land_default.dds") - ->setTextureScale(scale,scale); - } - - uint8_t *terr_makeAlphaLayer(const char* name, int32_t width) - { - // Create alpha map for this texture. - Ogre::TexturePtr texPtr = Ogre::TextureManager::getSingleton(). - createManual(name, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, - width, width, - 1,0, // depth, mipmaps - Ogre::PF_A8, // One-channel alpha - Ogre::TU_STATIC_WRITE_ONLY); - - createdResources.push_back(texPtr); - - pixelBuffer = texPtr->getBuffer().get(); - pixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); - const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock(); - - return static_cast(pixelBox.data); - } - - void terr_closeAlpha(const char *alphaName, - const char *texName, float scale) - { - // Close the alpha pixel buffer opened in the previous function - pixelBuffer->unlock(); - - // Create a pass containing the alpha map - Pass *np = mat->getTechnique(0)->createPass(); - np->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); - np->setLightingEnabled(false); - np->setDepthFunction(Ogre::CMPF_EQUAL); - Ogre::TextureUnitState* tus = np->createTextureUnitState(alphaName); - tus->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - - // Set various blending options - tus->setAlphaOperation(Ogre::LBX_BLEND_TEXTURE_ALPHA, - Ogre::LBS_TEXTURE, - Ogre::LBS_TEXTURE); - tus->setColourOperationEx(Ogre::LBX_BLEND_DIFFUSE_ALPHA, - Ogre::LBS_TEXTURE, - Ogre::LBS_TEXTURE); - tus->setIsAlpha(true); - - // Add the terrain texture to the pass and scale it. - tus = np->createTextureUnitState(texName); - tus->setColourOperationEx(Ogre::LBX_BLEND_DIFFUSE_ALPHA, - Ogre::LBS_TEXTURE, - Ogre::LBS_CURRENT); - tus->setTextureScale(scale, scale); - } - - // Clean up after the above functions, render the material to - // texture and save the data in outdata and in the file outname. - void terr_cleanupAlpha(const char *outname, - void *outData, int32_t toSize) - { - TexturePtr tex1 = getRenderedTexture(mat,outname, - toSize,Ogre::PF_R8G8B8); - - // Blit the texture into the given memory buffer - PixelBox pb = PixelBox(toSize, toSize, 1, PF_R8G8B8); - pb.data = outData; - tex1->getBuffer()->blitToMemory(pb); - - // Clean up - TextureManager::getSingleton().remove(tex1->getHandle()); - const std::list::const_iterator iend = createdResources.end(); - for ( std::list::const_iterator itr = createdResources.begin(); - itr != iend; - ++itr) - (*itr)->getCreator()->remove((*itr)->getHandle()); - createdResources.clear(); - - MaterialManager::getSingleton().remove(mat->getHandle()); - mat.setNull(); - } - - void terr_resize(void* srcPtr, void* dstPtr, int32_t fromW, int32_t toW) - { - // Create pixelboxes - PixelBox src = PixelBox(fromW, fromW, 1, PF_R8G8B8); - PixelBox dst = PixelBox(toW, toW, 1, PF_R8G8B8); - - src.data = srcPtr; - dst.data = dstPtr; - - // Resize the image. The nearest neighbour filter makes sure - // there is no blurring. - Image::scale(src, dst, Ogre::Image::FILTER_NEAREST); - } - - void terr_saveImage(void *data, int32_t width, const char* name) - { - Image img; - img.loadDynamicImage((uchar*)data, width, width, PF_R8G8B8); - img.save(name); - } -} diff --git a/old_d_version/terrain/esmland.d b/old_d_version/terrain/esmland.d deleted file mode 100644 index 1ea169ade..000000000 --- a/old_d_version/terrain/esmland.d +++ /dev/null @@ -1,158 +0,0 @@ -module terrain.esmland; - -import esm.loadltex; -import esm.loadcell; -import util.regions; -import esm.filereader; - -import std.stdio; - -const int LAND_NUM_VERTS = 65*65; - -MWLand mwland; - -// Interface to the ESM landscape data -struct MWLand -{ - RegionManager reg; - - // These structs/types represent the way data is actually stored in - // the ESM files. - - // Heightmap - align(1) - struct VHGT - { - float heightOffset; - byte heightData[LAND_NUM_VERTS]; - short unknown1; - char unknown2; - } - - // Normals - typedef byte[LAND_NUM_VERTS*3] VNML; - - // Land textures. This is organized in 4x4 buffers of 4x4 squares - // each. This is how the original engine splits up the cell meshes, - // and it's probably a good idea for us to do the same. - typedef short[4][4][4][4] VTEX; - - static assert(VHGT.sizeof == 4232); - static assert(VNML.sizeof == 12675); - static assert(VTEX.sizeof == 512); - - // Landscape data for one cell - struct LandData - { - VHGT vhgt; - VNML normals; - } - - // Texture data for one cell - struct LTEXData - { - // Global list of land textures from the source ES file - LandTextureList.TextureList source; - - // Texture indices for this cell - VTEX vtex; - - // Get the texture x2,y2 from the sub map x1,x2 - char[] getTexture(int x1, int y1, int x2, int y2) - { - // Get the texture index relative to the current esm/esp file - short texID = vtex[y1][x1][y2][x2] - 1; - - if(texID == -1) - return null; - - // Return the 'new' texture name. This name was automatically - // been converted to .dds at load time if the .tga file was not - // found. - assert(source !is null); - assert(texID >= 0 && texID < source.length); - return source[texID].getNewName(); - } - - // Get a texture from the 16x16 grid in one cell - char[] getTexture(int x, int y) - { - return getTexture(x/4,y/4,x%4,y%4); - } - } - - // Get the maximum absolute coordinate value in any direction - int getMaxCoord() - { return cells.maxXY; } - - // Does the given cell exist and does it have land data? - bool hasData(int x, int y) - { - // Does the cell exist? - if(!cells.hasExt(x,y)) - return false; - - // And does it have terrain data? - auto ex = cells.getExt(x,y); - return ex.hasLand(); - } - - LandData *getLandData(int x, int y) - { - loadCell(x, y); - return ¤tLand; - } - - LTEXData *getLTEXData(int x, int y) - { - loadCell(x, y); - return ¤tLtex; - } - - private: - - int currentX = -1234; - int currentY = 4321; - - LandData currentLand; - LTEXData currentLtex; - - // Make sure the given cell is loaded - void loadCell(int x, int y) - { - // If the right cell is already loaded, don't do anything - if(x == currentX && y == currentY) - return; - - assert(hasData(x,y)); - - currentX = x; - currentY = y; - - // Get the file context for the terrain data. This can be used to - // skip to the right part of the ESM file. - auto cont = cells.getExt(x,y).land.context; - - // Get the land texture list from the file - currentLtex.source = landTextures.files[cont.filename]; - - // We should use an existing region later, or at least delete this - // once we're done with the gen process. - if(reg is null) - reg = new RegionManager(); - - // Open the ESM at this cell - esFile.restoreContext(cont, reg); - - // Store the cell-specific data - esFile.readHNExact(currentLand.normals.ptr, - currentLand.normals.length, "VNML"); - esFile.readHNExact(¤tLand.vhgt, VHGT.sizeof, "VHGT"); - - // These aren't used yet - if(esFile.isNextSub("WNAM")) esFile.skipHSubSize(81); - if(esFile.isNextSub("VCLR")) esFile.skipHSubSize(12675); - - esFile.readHNExact(¤tLtex.vtex, VTEX.sizeof, "VTEX"); - } -} diff --git a/old_d_version/terrain/generator.d b/old_d_version/terrain/generator.d deleted file mode 100644 index f1645c9ab..000000000 --- a/old_d_version/terrain/generator.d +++ /dev/null @@ -1,1114 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008-2009 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (generator.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - -*/ - -// This module is responsible for generating the cache files. -module terrain.generator; - -import std.stdio; -import std.string; -import std.math2; -import std.c.string; - -import terrain.cachewriter; -import terrain.archive; -import terrain.esmland; -import terrain.terrain; -import terrain.bindings; - -import util.cachefile; - -import monster.util.aa; -import monster.util.string; -import monster.vm.dbg; - -int mCount; - -// Texture sizes for the various levels. For the most detailed level -// (level 1), this give the size of the alpha splatting textures rather -// than a final texture. -int[] texSizes; - -CacheWriter cache; - -void generate(char[] filename) -{ - makePath(cacheDir); - - cache.openFile(filename); - - // Find the maxiumum distance from (0,0) in any direction - int max = mwland.getMaxCoord(); - - // Round up to nearest power of 2 - int depth=1; - while(max) - { - max >>= 1; - depth++; - assert(depth <= 8); - } - max = 1 << depth-1; - - // We already know the answers - assert(max == 32); - assert(depth == 6); - - // Set the texture sizes. TODO: These should be config options, - // perhaps - or maybe a result of some higher-level detail setting. - texSizes.length = depth+1; - texSizes[6] = 1024; - texSizes[5] = 512; - texSizes[4] = 256; - texSizes[3] = 256; - texSizes[2] = 512; - texSizes[1] = 64; - - // Set some general parameters for the runtime - cache.setParams(depth+1, texSizes[1]); - - // Create some common data first - writefln("Generating common data"); - genDefaults(); - genIndexData(); - - writefln("Generating quad data"); - GenLevelResult gen; - - // Start at one level above the top, but don't generate data for it - genLevel(depth+1, -max, -max, gen, false); - - writefln("Writing index file"); - cache.finish(); - writefln("Pregeneration done. Results written to ", filename); -} - -struct GenLevelResult -{ - QuadHolder quad; - - bool hasMesh; - bool isAlpha; - - int width; - - ubyte[] data; - - void allocImage(int _width) - { - assert(isEmpty()); - - width = _width; - data.length = width*width*3; - quad.meshes.length = 1; - - assert(!hasAlpha()); - } - - void allocAlphas(int _width, int texNum) - { - assert(isEmpty() || hasMesh); - - width = _width; - data.length = width*width*texNum; - isAlpha = true; - - // Set up the alpha images. TODO: We have to split these over - // several meshes, but for now pretend that we're using only - // one. - assert(quad.meshes.length == 1); - quad.meshes[0].alphas.length = texNum; - assert(alphaNum() == texNum); - - int s = width*width; - for(int i=0;i 2); - genLevel2Map(null, defaults[2]); - - for(int i=3; i=0&&v>=0); - assert(u<=1&&v<=1); - - vertList[index++] = u; - vertList[index++] = v; - } - assert(index == vertList.length); - // Store the buffer - cache.addVertexBuffer(lev,vertList); - } - - // index stuff already ported -} - -void genLevel(int level, int X, int Y, ref GenLevelResult result, - bool makeData = true) -{ - scope auto _trc = new MTrace(format("genLevel(%s,%s,%s)",level,X,Y)); - result.quad.info.cellX = X; - result.quad.info.cellY = Y; - result.quad.info.level = level; - result.quad.info.worldWidth = 8192 << (level-1); - - assert(result.isEmpty); - - // Level 1 (most detailed) is handled differently from the - // other leves. - if(level == 1) - { - assert(makeData); - - if(!mwland.hasData(X,Y)) - // Oops, there's no data for this cell. Skip it. - return; - - // The mesh is generated in pieces rather than as one part. - genLevel1Meshes(result); - - // We also generate alpha maps instead of the actual textures. - genCellAlpha(result); - - if(!result.isEmpty()) - { - // Store the information we just created - assert(result.hasAlpha()); - cache.writeQuad(result.quad); - } - - return; - } - assert(level > 1); - - // Number of cells along one side in each sub-quad (not in this - // quad) - int cells = 1 << (level-2); - - // Call the sub-levels and store the result - GenLevelResult sub[4]; - genLevel(level-1, X, Y, sub[0]); // NW - genLevel(level-1, X+cells, Y, sub[1]); // NE - genLevel(level-1, X, Y+cells, sub[2]); // SW - genLevel(level-1, X+cells, Y+cells, sub[3]); // SE - - // Make sure we deallocate everything when the function exists - scope(exit) - { - foreach(ref s; sub) - s.kill(); - } - - // Mark the sub-quads that have data - bool anyUsed = false; - for(int i=0;i<4;i++) - { - bool used = !sub[i].isEmpty(); - result.quad.info.hasChild[i] = used; - anyUsed = anyUsed || used; - } - - if(!anyUsed) - { - // If our children are empty, then we are also empty. - assert(result.isEmpty()); - return; - } - - if(makeData) - { - if(level == 2) - // For level==2, generate a new texture from the alpha maps. - genLevel2Map(sub, result); - else - // Level 3+, merge the images from the previous levels - mergeMaps(sub, result); - - // Create the landscape mesh by merging the result from the - // children. - mergeMesh(sub, result); - } - - // Store the result in the cache file - cache.writeQuad(result.quad); -} - -// Generate mesh data for one cell -void genLevel1Meshes(ref GenLevelResult res) -{ - // Constants - int intervals = 64; - int vertNum = intervals+1; - int vertSep = 128; - - // Allocate the mesh buffer - res.allocMesh(vertNum); - - int cellX = res.quad.info.cellX; - int cellY = res.quad.info.cellY; - assert(res.quad.info.level==1); - - MeshHolder *mh = &res.quad.meshes[0]; - MeshInfo *mi = &mh.info; - - // Set some basic data - mi.worldWidth = vertSep*intervals; - assert(mi.worldWidth == 8192); - - auto land = mwland.getLandData(cellX, cellY); - - byte[] heightData = land.vhgt.heightData; - byte[] normals = land.normals; - mi.heightOffset = land.vhgt.heightOffset; - - float max=-1000000.0; - float min=1000000.0; - - byte[] verts = mh.vertexBuffer; - int index = 0; - - // Loop over all the vertices in the mesh - float rowheight = mi.heightOffset; - float height; - for(int y=0; y<65; y++) - for(int x=0; x<65; x++) - { - // Offset of this vertex within the source buffer - int offs=y*65+x; - - // The vertex data from the ESM - byte data = heightData[offs]; - - // Write the height value as a short (2 bytes) - *(cast(short*)&verts[index]) = data; - index+=2; - - // Calculate the height here, even though we don't store - // it. We use it to find the min and max values. - if(x == 0) - { - // Set the height to the row height - height = rowheight; - - // First value in each row adjusts the row height - rowheight += data; - } - // Adjust the accumulated height with the new data. - height += data; - - // Calculate the min and max - max = height > max ? height : max; - min = height < min ? height : min; - - // Store the normals - for(int k=0; k<3; k++) - verts[index++] = normals[offs*3+k]; - } - - // Make sure we wrote exactly the right amount of data - assert(index == verts.length); - - // Store the min/max values - mi.minHeight = min * 8; - mi.maxHeight = max * 8; -} - -// Generate the alpha splatting bitmap for one cell. -void genCellAlpha(ref GenLevelResult res) -{ - scope auto _trc = new MTrace("genCellAlpha"); - - int cellX = res.quad.info.cellX; - int cellY = res.quad.info.cellY; - assert(res.quad.info.level == 1); - - // Set the texture name - it's used internally as the material name - // at runtime. - assert(res.quad.meshes.length == 1); - res.setTexName("AMAT_"~toString(cellX)~"_"~toString(cellY)); - - // List of texture indices for this cell. A cell has 16x16 texture - // squares. - int ltex[16][16]; - - auto ltexData = mwland.getLTEXData(cellX, cellY); - - // A map from the global texture index to the local index for this - // cell. - int[int] textureMap; - - int texNum = 0; // Number of local indices - - // Loop through all the textures in the cell and get the indices - bool isDef = true; - for(int ty = 0; ty < 16; ty++) - for(int tx = 0; tx < 16; tx++) - { - // Get the texture in a given cell - char[] textureName = ltexData.getTexture(tx,ty); - - // If the default texture is used, skip it. The background - // texture covers it (for now - we might change that later.) - if(textureName == "") - { - ltex[ty][tx] = -1; - continue; - } - - isDef = false; - - // Store the global index - int index = cache.addTexture(textureName); - ltex[ty][tx] = index; - - // Add the index to the map - if(!(index in textureMap)) - textureMap[index] = texNum++; - } - - assert(texNum == textureMap.length); - - // If we only found default textures, exit now. - if(isDef) - return; - - int imageRes = texSizes[1]; - int dataSize = imageRes*imageRes; - - // Number of alpha pixels per texture square - int pps = imageRes/16; - - // Make sure there are at least as many alpha pixels as there are - // textures - assert(imageRes >= 16); - assert(imageRes%16 == 0); - assert(pps >= 1); - assert(texNum >= 1); - - // Allocate the alpha images - res.allocAlphas(imageRes, texNum); - assert(res.hasAlpha() && !res.isEmpty()); - - // Write the indices to the result list - foreach(int global, int local; textureMap) - res.setAlphaTex(local, global); - - ubyte *uptr = res.data.ptr; - - // Loop over all textures again. This time, do alpha splatting. - for(int ty = 0; ty < 16; ty++) - for(int tx = 0; tx < 16; tx++) - { - // Get the global texture index for this square, if any. - int index = ltex[ty][tx]; - if(index == -1) - continue; - - // Get the local index - index = textureMap[index]; - - // Get the offset of this square - long offs = index*dataSize + pps*(ty*imageRes + tx); - - // FIXME: Make real splatting later. This is just - // placeholder code. - - // Set alphas to full for this square - for(int y=0; y level); - assert(level > 2); - int fromSize = texSizes[level-1]; - int toSize = texSizes[level]; - - // Create a new image buffer large enough to hold the four - // sub textures - res.allocImage(fromSize*2); - - // Add the four sub-textures - for(int mi=0;mi<4;mi++) - { - ubyte[] src; - - // Use default texture if no source is present - if(maps.length == 0 || maps[mi].isEmpty()) - src = defaults[level-1].data; - else - src = maps[mi].data; - - assert(src.length == 3*fromSize*fromSize); - - // Find the sub-part of the destination buffer to write to - int x = (mi%2) * fromSize; - int y = (mi/2) * fromSize; - - // Copy the image into the new buffer - copyBox(src, res.data, fromSize, fromSize*2, x, y, 3); - } - - // Resize image if necessary - if(toSize != 2*fromSize) - res.resize(toSize); - - // Texture file name - char[] outname = res.getPNGName(maps.length == 0); - - // Save the image - res.save(outname); -} - -// Copy from one buffer into a sub-region of another buffer -void copyBox(ubyte[] src, ubyte[] dst, - int srcWidth, int dstWidth, - int dstX, int dstY, int pixSize) -{ - int fskip = srcWidth * pixSize; - int tskip = dstWidth * pixSize; - int rows = srcWidth; - int rowSize = srcWidth*pixSize; - - assert(src.length == pixSize*srcWidth*srcWidth); - assert(dst.length == pixSize*dstWidth*dstWidth); - assert(srcWidth <= dstWidth); - assert(dstX <= dstWidth-srcWidth && dstY <= dstWidth-srcWidth); - - // Source and destination pointers - ubyte *from = src.ptr; - ubyte *to = dst.ptr + dstY*tskip + dstX*pixSize; - - for(;rows>0;rows--) - { - memcpy(to, from, rowSize); - to += tskip; - from += fskip; - } -} - -// Create the mesh for this level, by merging the meshes from the -// previous levels. -void mergeMesh(GenLevelResult[] sub, ref GenLevelResult res) -{ - // How much to shift various numbers to the left at this level - // (ie. multiply by 2^shift). The height at each vertex is - // multiplied by 8 in each cell to get the final value. However, - // when we're merging two cells (in each direction), we have to - // scale down all the height values by 2 in order to fit the result - // in one byte. This means multiplying the factor by 2 for each - // level above the cell level. - int shift = res.quad.info.level - 1; - assert(shift >= 1); - assert(sub.length == 4); - - // Allocate the result buffer - res.allocMesh(65); - - MeshHolder *mh = &res.quad.meshes[0]; - MeshInfo *mi = &mh.info; - - // Basic info - mi.worldWidth = 8192 << shift; - - // Copy the mesh height from the top left mesh - mi.heightOffset = sub[0].getHeight(); - - // Output buffer - byte verts[] = mh.vertexBuffer; - - // Bytes per vertex - const int VSIZE = 5; - - // Used to calculate the max and min heights - float minh = 300000.0; - float maxh = -300000.0; - - foreach(si, s; sub) - { - int SX = si % 2; - int SY = si / 2; - - // Find the offset in the destination buffer - int dest = SX*32 + SY*65*32; - dest *= VSIZE; - - void putValue(int val) - { - assert(val >= short.min && val <= short.max); - *(cast(short*)&verts[dest]) = val; - dest += 2; - } - - if(s.hasMesh) - { - auto m = &s.quad.meshes[0]; - auto i = &m.info; - - minh = min(minh, i.minHeight); - maxh = max(maxh, i.maxHeight); - - byte[] source = m.vertexBuffer; - int src = 0; - - int getValue() - { - int s = *(cast(short*)&source[src]); - src += 2; - return s; - } - - // Loop through all the vertices in the mesh - for(int y=0;y<33;y++) - { - // Skip the first row in the mesh if there was a mesh - // above us. We assume that the previously written row - // already has the correct information. - if(y==0 && SY != 0) - { - src += 65*VSIZE; - dest += 65*VSIZE; - continue; - } - - // Handle the first vertex of the row outside the - // loop. - int height = getValue(); - - // If this isn't the very first row, sum up two row - // heights and skip the first row. - if(y!=0) - { - // Skip the rest of the row. - src += 64*VSIZE + 3; - - // Add the second height - height += getValue(); - } - - putValue(height); - - // Copy the normal - verts[dest++] = source[src++]; - verts[dest++] = source[src++]; - verts[dest++] = source[src++]; - - // Loop through the remaining 64 vertices in this row, - // processing two at a time. - for(int x=0;x<32;x++) - { - height = getValue(); - - // Sum up the next two heights - src += 3; // Skip normal - height += getValue(); - - // Set the height - putValue(height); - - // Copy the normal - verts[dest++] = source[src++]; - verts[dest++] = source[src++]; - verts[dest++] = source[src++]; - } - // Skip to the next row - dest += 32*VSIZE; - } - assert(src == source.length); - } - else - { - minh = min(minh, -2048); - maxh = max(maxh, -2048); - - // Set all the vertices to zero. - for(int y=0;y<33;y++) - { - if(y==0 && SY != 0) - { - dest += 65*VSIZE; - continue; - } - - for(int x=0;x<33;x++) - { - if(x==0 && SX != 0) - { - dest += VSIZE; - continue; - } - - // Zero height and vertical normal - verts[dest++] = 0; - verts[dest++] = 0; - verts[dest++] = 0; - verts[dest++] = 0; - verts[dest++] = 0x7f; - } - // Skip to the next row - dest += 32*VSIZE; - } - } - } - - mi.minHeight = minh; - mi.maxHeight = maxh; - assert(minh <= maxh); -} - -// ------- OLD CODE - use these snippets later ------- - -// About segments: -/* NOTES for the gen-phase: Was: -// This is pretty messy. Btw: 128*16 == 2048 == -// CELL_WIDTH/4 -// 65 points across one cell means 64 intervals, and 17 points - -// means 16=64/4 intervals. So IOW the number of verts when -// dividing by D is (65-1)/D + 1 = 64/D+1, which means that D -// should divide 64, that is, be a power of two < 64. - -addNewObject(Ogre::Vector3(x*16*128, 0, y*16*128), //pos -17, //size -false, //skirts -0.25f, float(x)/4.0f, float(y)/4.0f);//quad seg location -*/ - -/* This was also declared in the original code, you'll need it - when creating the cache data - - size_t vw = mWidth; // mWidth is 17 or 65 - if ( mUseSkirts ) vw += 2; // skirts are used for level 2 and up - vertCount=vw*vw; -*/ - -/** - * @brief fills the vertex buffer with data - * @todo I don't think tex co-ords are right - void calculateVertexValues() - { - int start = 0; - int end = mWidth; - - if ( mUseSkirts ) - { - --start; - ++end; - } - - for ( int y = start; y < end; y++ ) - for ( int x = start; x < end; x++ ) - { - if ( y < 0 || y > (mWidth-1) || x < 0 || x > (mWidth-1) ) - { - // These are the skirt vertices. 'Skirts' are simply a - // wall at the edges of the mesh that goes straight down, - // cutting off the posibility that you might see 'gaps' - // between the meshes. Or at least I think that's the - // intention. - - assert(mUseSkirts); - - // 1st coordinate - if ( x < 0 ) - *verts++ = 0; - else if ( x > (mWidth-1) ) - *verts++ = (mWidth-1)*getVertexSeperation(); - else - *verts++ = x*getVertexSeperation(); - - // 2nd coordinate - *verts++ = -4096; //2048 below base sea floor height - - // 3rd coordinate - if ( y < 0 ) - *verts++ = 0; - else if ( y > (mWidth-1) ) - *verts++ = (mWidth-1)*getVertexSeperation(); - else - *verts++ = y*getVertexSeperation(); - - // No normals - for ( Ogre::uint i = 0; i < 3; i++ ) - *verts++ = 0; - - // It shouldn't matter if these go over 1 - float u = (float)(x) / (mWidth-1); - float v = (float)(y) / (mWidth-1); - *verts++ = u; - *verts++ = v; - } - else // Covered already - - void calculateIndexValues() - { - size_t vw = mWidth-1; - if ( mUseSkirts ) vw += 2; - - const size_t indexCount = (vw)*(vw)*6; - - //need to manage allocation if not null - assert(mIndices==0); - - // buffer was created here - - bool flag = false; - Ogre::uint indNum = 0; - for ( Ogre::uint y = 0; y < (vw); y+=1 ) { - for ( Ogre::uint x = 0; x < (vw); x+=1 ) { - - const int line1 = y * (vw+1) + x; - const int line2 = (y + 1) * (vw+1) + x; - - if ( flag ) { - *indices++ = line1; - *indices++ = line2; - *indices++ = line1 + 1; - - *indices++ = line1 + 1; - *indices++ = line2; - *indices++ = line2 + 1; - } else { - *indices++ = line1; - *indices++ = line2; - *indices++ = line2 + 1; - - *indices++ = line1; - *indices++ = line2 + 1; - *indices++ = line1 + 1; - } - flag = !flag; //flip tris for next time - - indNum+=6; - } - flag = !flag; //flip tries for next row - } - assert(indNum==indexCount); - //return mIndices; - } -*/ diff --git a/old_d_version/terrain/myfile.d b/old_d_version/terrain/myfile.d deleted file mode 100644 index 15239ac2e..000000000 --- a/old_d_version/terrain/myfile.d +++ /dev/null @@ -1,71 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2009 Nicolay Korslund - WWW: http://openmw.sourceforge.net/ - - This file (archive.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - -*/ - -module terrain.myfile; - -import std.stream; -import std.stdio; - -// Add a couple of helper functions to the file stream -class MyFile : File -{ - this(string filename, FileMode mode = FileMode.In) - { - super(filename, mode); - } - - void fill(T)(ref T t) - { - readExact(&t, T.sizeof); - } - - void dump(T)(ref T t) - { - writeExact(&t, T.sizeof); - } - - void fillArray(T)(T[] t) - { - readExact(t.ptr, t.length*T.sizeof); - } - - void dumpArray(T)(T[] t) - { - writeExact(t.ptr, t.length*T.sizeof); - } - - void readArray(T)(ref T[] arr) - { - int size; - read(size); - assert(size < 1024*1024 && size > 0); - arr = new T[size]; - fillArray!(T)(arr); - } - - void writeArray(T)(T[] t) - { - int size = t.length; - write(size); - dumpArray!(T)(t); - } -} diff --git a/old_d_version/terrain/outbuffer.d b/old_d_version/terrain/outbuffer.d deleted file mode 100644 index c496a4787..000000000 --- a/old_d_version/terrain/outbuffer.d +++ /dev/null @@ -1,94 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008-2009 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ - - This file (outbuffer.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - */ - -/* - This files provides a simple buffer class used for writing the cache - files. It lets you 'write' data to a growing memory buffer and - allows you to change the written data after the fact (since it's - retained in memory.) When you're done, you can write the entire - buffer to a stream in one operation. - */ - -module terrain.outbuffer; - -import util.regions; -import std.stream; - -class OutBuffer -{ - private: - RegionManager reg; - long used; - void[][] buffers; - - public: - this() - { - reg = new RegionManager("Outbuf", 200*1024); - } - - void reset() - { - if(buffers.length) - delete buffers; - - reg.freeAll(); - used = 0; - buffers = null; - } - - // Write everyting to a stream as one buffer - void writeTo(Stream str) - { - foreach(void[] v; buffers) - str.writeExact(v.ptr, v.length); - - reset(); - } - - // Get a pointer to a new block at least 'bytes' large, but don't - // add it to the list. - void[] reserve(size_t bytes) - { return reg.allocate(bytes); } - - // Get a new block which is 'bytes' size large. - void[] add(size_t bytes) - { - void[] p = reserve(bytes); - add(p); - return p; - } - - // Add an existing block to the write list - void add(void[] p) - { - buffers ~= p; - used += p.length; - } - - T[] write(T)(size_t num) - { - return cast(T[])add(num * T.sizeof); - } - - size_t size() { return used; } -} diff --git a/old_d_version/terrain/quad.d b/old_d_version/terrain/quad.d deleted file mode 100644 index c68afc1ca..000000000 --- a/old_d_version/terrain/quad.d +++ /dev/null @@ -1,286 +0,0 @@ -module terrain.quad; - -import terrain.archive; -import terrain.bindings; -import std.stdio; -import monster.vm.dbg; - -const int CELL_WIDTH = 8192; -const float SPLIT_FACTOR = 0.5; -const float UNSPLIT_FACTOR = 2.0; - -class Quad -{ - this(int cellX=0, int cellY=0, Quad parent = null) - { - scope auto _trc = new MTrace("Quad.this"); - - mCellX = cellX; - mCellY = cellY; - - // Do we have a parent? - if(parent !is null) - { - mLevel = parent.mLevel-1; - - // Coordinates relative to our parent - int relX = cellX - parent.mCellX; - int relY = cellY - parent.mCellY; - - // The coordinates give the top left corner of the quad, or our - // relative coordinates within that should always be positive. - assert(relX >= 0); - assert(relY >= 0); - - // Create a child scene node. The scene node position is given in - // world units, ie. CELL_WIDTH units per cell. - mNode = terr_createChildNode(relX*CELL_WIDTH, - relY*CELL_WIDTH, - parent.mNode); - - // Get the archive data for this quad. - mInfo = g_archive.getQuad(mCellX,mCellY,mLevel); - - // Set up the bounding box. Use MW coordinates all the - // way. - mBounds = terr_makeBounds(mInfo.minHeight, - mInfo.maxHeight, - mInfo.worldWidth, - mNode); - - float radius = mInfo.boundingRadius; - - mSplitDistance = radius * SPLIT_FACTOR; - mUnsplitDistance = radius * UNSPLIT_FACTOR; - - // Square the distances - mSplitDistance *= mSplitDistance; - mUnsplitDistance *= mUnsplitDistance; - - if(mLevel == 1) - { - // Create the terrain and leave it there. - buildTerrain(); - isStatic = true; - } - } - else - { - // No parent, this is the top-most quad. Get all the info from - // the archive. - mInfo = g_archive.rootQuad; - assert(mInfo); - - mLevel = mInfo.level; - cellX = mCellX = mInfo.cellX; - cellY = mCellY = mInfo.cellY; - - mNode = terr_createChildNode(cellX*CELL_WIDTH, - cellY*CELL_WIDTH, - null); - - // Split up - split(); - - // The root can never be unsplit - isStatic = true; - } - - assert(mLevel >= 1); - assert(mNode !is null); - - // Update the terrain. This will create the mesh or children if - // necessary. - update(); - } - - ~this() - { - scope auto _trc = new MTrace("Quad.~this"); - - // TODO: We might rewrite the code so that the quads are never - // actually destroyed, just 'inactivated' by hiding their scene - // node. We only call update on our children if we don't have a - // mesh ourselves. - if(hasMesh) - destroyTerrain(); - else if(hasChildren) - for (size_t i = 0; i < 4; i++) - delete mChildren[i]; - - terr_destroyNode(mNode); - if(mBounds !is null) - terr_killBounds(mBounds); - } - - // Remove the landscape for this quad, and create children. - void split() - { - scope auto _trc = new MTrace("split"); - // Never split a static quad or a quad that already has children. - assert(!isStatic); - assert(!hasChildren); - assert(mLevel > 1); - - if(hasMesh) - destroyTerrain(); - - // Find the cell width of our children - int cWidth = 1 << (mLevel-2); - - // Create children - for ( size_t i = 0; i < 4; ++i ) - { - if(!mInfo.hasChild[i]) - continue; - - // The cell coordinates for this child quad - int x = (i%2)*cWidth + mCellX; - int y = (i/2)*cWidth + mCellY; - - mChildren[i] = new Quad(x,y,this); - } - hasChildren = true; - } - - // Removes children and rebuilds terrain - void unsplit() - { - scope auto _trc = new MTrace("unsplit"); - // Never unsplit the root quad - assert(mLevel < g_archive.rootQuad.level); - // Never unsplit a static or quad that isn't split. - assert(!isStatic); - assert(hasChildren); - assert(!hasMesh); - - for( size_t i = 0; i < 4; i++ ) - { - delete mChildren[i]; - mChildren[i] = null; - } - - buildTerrain(); - - hasChildren = false; - } - - // Determines whether to split or unsplit the quad, and immediately - // does it. - void update() - { - scope auto _trc = new MTrace("Quad.update()"); - - // Static quads don't change - if(!isStatic) - { - assert(mUnsplitDistance > mSplitDistance); - - // Get (squared) camera distance. TODO: shouldn't this just - // be a simple vector difference from the mesh center? - assert(mBounds !is null); - float camDist = terr_getSqCamDist(mBounds); - - // No children? - if(!hasChildren) - { - // If we're close, split now. - if(camDist < mSplitDistance) - split(); - else - { - // We're not close, and don't have any children. Should we - // built terrain? - if(!hasMesh) - buildTerrain(); - return; - } - } - - // If we get here, we either had children when we entered, - // or we just performed a split. - assert(!hasMesh); - assert(hasChildren); - - // If the camera is too far away, kill the children. - if(camDist > mUnsplitDistance) - { - unsplit(); - return; - } - } - else if(!hasChildren) - return; - - // We have children and we're happy about it. Update them too. - for(int i; i < 4; ++i) - { - Quad q = mChildren[i]; - if(q !is null) q.update(); - } - } - - // Build the terrain for this quad - void buildTerrain() - { - scope auto _trc = new MTrace("buildTerrain"); - - assert(!hasMesh); - assert(!isStatic); - - // Map the terrain data into memory. - assert(mInfo); - g_archive.mapQuad(mInfo); - - // Create one mesh for each segment in the quad. TerrainMesh takes - // care of the loading. - meshList.length = mInfo.meshNum; - foreach(i, ref m; meshList) - { - MeshInfo *mi = g_archive.getMeshInfo(i); - m = terr_makeMesh(mNode, mi, mInfo.level, TEX_SCALE); - } - - hasMesh = true; - } - - void destroyTerrain() - { - scope auto _trc = new MTrace("destroyTerrain"); - - assert(hasMesh); - - foreach(m; meshList) - terr_killMesh(m); - - meshList[] = null; - hasMesh = false; - } - - private: - - // List of meshes, if any. The meshes are C++ objects. - MeshObj meshList[]; - - // Scene node. All child quads are added to this. - SceneNode mNode; - - // Bounding box, transformed to world coordinates. Used to calculate - // camera distance. - Bounds mBounds; - - float mSplitDistance,mUnsplitDistance; - - Quad mChildren[4]; - - // Contains the 'level' of this node. Level 1 is the closest and - // most detailed level - int mLevel; - int mCellX, mCellY; - - QuadInfo *mInfo; - - bool hasMesh; - bool hasChildren; - bool isStatic; // Static quads are never split or unsplit -} diff --git a/old_d_version/terrain/terrain.d b/old_d_version/terrain/terrain.d deleted file mode 100644 index 4bf03c87b..000000000 --- a/old_d_version/terrain/terrain.d +++ /dev/null @@ -1,103 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008-2009 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.snaptoad.com/ - - This file (terrain.d) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -module terrain.terrain; - -import terrain.generator; -import terrain.archive; -import terrain.bindings; -import terrain.quad; -import std.file, std.stdio; - -char[] cacheDir = "cache/terrain/"; - -// Enable this to render single terrain meshes instead of the entire -// data set -//debug=singleMesh; - -void initTerrain(bool doGen) -{ - char[] fname = cacheDir ~ "landscape.cache"; - - if(!exists(fname)) - { - writefln("Cache file '%s' not found. Creating:", - fname); - doGen = true; - } - - if(doGen) - generate(fname); - - // Load the archive file - g_archive.openFile(fname); - - terr_setupRendering(); - - debug(singleMesh) - { - int X = 22; - int Y = 0; - bool next = false; - - void doQuad(int x, int y, int lev, int diffx, int diffy) - { - if(!g_archive.hasQuad(x,y,lev)) - return; - - diffx *= 8192; - diffy *= 8192; - - auto node = terr_createChildNode(20000+diffx,-60000+diffy,null); - auto info = g_archive.getQuad(x,y,lev); - g_archive.mapQuad(info); - auto mi = g_archive.getMeshInfo(0); - terr_makeMesh(node, mi, info.level, TEX_SCALE); - } - - doQuad(X,Y,1, 0,0); - doQuad(X+1,Y,1, 1,0); - doQuad(X,Y+1,1, 0,1); - doQuad(X+1,Y+1,1, 1,1); - - doQuad(X + (next?2:0),Y,2, 2,0); - - doQuad(20,Y,3, 0,2); - } - else - { - // Create the root quad - rootQuad = new Quad; - } -} - -extern(C) void d_terr_terrainUpdate() -{ - debug(singleMesh) return; - - // Update the root quad each frame. - assert(rootQuad !is null); - rootQuad.update(); -} - -Quad rootQuad; From ea241d85efdd5c5110e3e944b19501b5e7b9acbc Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Sat, 28 Jan 2012 01:36:17 +0100 Subject: [PATCH 28/47] Fixed some issues with the CMake files --- apps/openmw/CMakeLists.txt | 41 ++++++++++++++++++-------------------- cmake/OpenMWMacros.cmake | 4 ++-- components/CMakeLists.txt | 8 ++++++-- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index bbee7498a..e9e548c0e 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -1,18 +1,16 @@ -project(OpenMW) # config file - -configure_file ("${OpenMW_SOURCE_DIR}/config.hpp.cmake" "${OpenMW_SOURCE_DIR}/config.hpp") +configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/config.hpp.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/config.hpp") # local files - set(GAME main.cpp engine.cpp - ) +) set(GAME_HEADER engine.hpp - config.hpp) + config.hpp +) source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender @@ -61,13 +59,11 @@ add_openmw_dir (mwmechanics # Main executable add_executable(openmw ${OPENMW_LIBS} ${OPENMW_LIBS_HEADER} - ${CONPONENT_FILES} + ${COMPONENT_FILES} ${OPENMW_FILES} ${GAME} ${GAME_HEADER} ${APPLE_BUNDLE_RESOURCES} - ) - -target_link_libraries (openmw components) +) # Sound stuff - here so CMake doesn't stupidly recompile EVERYTHING # when we change the backend. @@ -75,26 +71,27 @@ include_directories(${SOUND_INPUT_INCLUDES} ${BULLET_INCLUDE_DIRS}) add_definitions(${SOUND_DEFINE}) target_link_libraries(openmw - ${OGRE_LIBRARIES} - ${OIS_LIBRARIES} - ${Boost_LIBRARIES} - ${OPENAL_LIBRARY} - ${SOUND_INPUT_LIBRARY} - ${BULLET_LIBRARIES} - caelum - MyGUIEngine - MyGUIOgrePlatform + ${OGRE_LIBRARIES} + ${OIS_LIBRARIES} + ${Boost_LIBRARIES} + ${OPENAL_LIBRARY} + ${SOUND_INPUT_LIBRARY} + ${BULLET_LIBRARIES} + caelum + components + MyGUIEngine + MyGUIOgrePlatform ) -if (APPLE) +if(APPLE) find_library(CARBON_FRAMEWORK Carbon) target_link_libraries(openmw ${CARBON_FRAMEWORK}) install(TARGETS openmw BUNDLE DESTINATION . RUNTIME DESTINATION ../MacOS COMPONENT Runtime) -endif (APPLE) +endif(APPLE) if(DPKG_PROGRAM) INSTALL(TARGETS openmw RUNTIME DESTINATION games COMPONENT openmw) -endif() +endif(DPKG_PROGRAM) diff --git a/cmake/OpenMWMacros.cmake b/cmake/OpenMWMacros.cmake index c40936691..e79f9e615 100644 --- a/cmake/OpenMWMacros.cmake +++ b/cmake/OpenMWMacros.cmake @@ -2,7 +2,7 @@ macro (add_openmw_dir dir) set (files) foreach (u ${ARGN}) -file (GLOB ALL RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${dir}/${u}.*") +file (GLOB ALL ${CMAKE_CURRENT_SOURCE_DIR} "${dir}/${u}.*") foreach (f ${ALL}) list (APPEND files "${f}") list (APPEND OPENMW_FILES "${f}") @@ -14,7 +14,7 @@ endmacro (add_openmw_dir) macro (add_component_dir dir) set (files) foreach (u ${ARGN}) -file (GLOB ALL RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${dir}/${u}.*") +file (GLOB ALL ${CMAKE_CURRENT_SOURCE_DIR} "${dir}/${u}.*") foreach (f ${ALL}) list (APPEND files "${f}") list (APPEND COMPONENT_FILES "${f}") diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 75b8aff8c..7fcac6eb8 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -63,6 +63,10 @@ add_component_dir (interpreter include_directories(${BULLET_INCLUDE_DIRS}) -add_library (components STATIC ${COMPONENT_FILES}) +add_library(components STATIC ${COMPONENT_FILES}) + +target_link_libraries(components ${Boost_LIBRARIES} ${OGRE_LIBRARIES}) + +# Make the variable accessible for other subdirectories +set(COMPONENT_FILES ${COMPONENT_FILES} PARENT_SCOPE) -target_link_libraries (components ${Boost_LIBRARIES} ${OGRE_LIBRARIES}) From 61dd1922b067940d2508027fe03cdc39af221a48 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 28 Jan 2012 14:16:25 +0100 Subject: [PATCH 29/47] more specific cmake source file GLOBing --- cmake/OpenMWMacros.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/OpenMWMacros.cmake b/cmake/OpenMWMacros.cmake index e79f9e615..024338d3a 100644 --- a/cmake/OpenMWMacros.cmake +++ b/cmake/OpenMWMacros.cmake @@ -2,7 +2,7 @@ macro (add_openmw_dir dir) set (files) foreach (u ${ARGN}) -file (GLOB ALL ${CMAKE_CURRENT_SOURCE_DIR} "${dir}/${u}.*") +file (GLOB ALL ${CMAKE_CURRENT_SOURCE_DIR} "${dir}/${u}.[ch]pp") foreach (f ${ALL}) list (APPEND files "${f}") list (APPEND OPENMW_FILES "${f}") @@ -14,7 +14,7 @@ endmacro (add_openmw_dir) macro (add_component_dir dir) set (files) foreach (u ${ARGN}) -file (GLOB ALL ${CMAKE_CURRENT_SOURCE_DIR} "${dir}/${u}.*") +file (GLOB ALL ${CMAKE_CURRENT_SOURCE_DIR} "${dir}/${u}.[ch]pp") foreach (f ${ALL}) list (APPEND files "${f}") list (APPEND COMPONENT_FILES "${f}") From a301fc355e13fd906152b9d2db2145e220b7316a Mon Sep 17 00:00:00 2001 From: Nikolay Kasyanov Date: Sun, 29 Jan 2012 23:28:05 +0400 Subject: [PATCH 30/47] Feature #162 - Need to create app bundle using CMake, not by hand In progress. Still need to handle dynamically loaded libs (Ogre & Qt plugins) --- CMakeLists.txt | 129 +++++++++++++++++++++++++++---------- apps/openmw/CMakeLists.txt | 4 -- 2 files changed, 96 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 723d10b34..156035ccb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,38 @@ project(OpenMW) -IF (APPLE) - set(APP_BUNDLE_DIR "${OpenMW_BINARY_DIR}/OpenMW.app") +if (APPLE) + set(APP_BUNDLE_NAME "${CMAKE_PROJECT_NAME}.app") + + set(APP_BUNDLE_DIR "${OpenMW_BINARY_DIR}/${APP_BUNDLE_NAME}") # using 10.6 sdk set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.6.sdk") -ENDIF (APPLE) + + # This override needed to handle cases where some dependencies already fixed up, + # so BundleUtilities cannot find them + + #function(gp_resolve_item_override context item exepath dirs resolved_item resolved) + # message(STATUS "gp_resolve_item_override for ${item} with ${exepath} and ${dirs}") + # if(item MATCHES "@executable_path" AND resolved) + # if (item MATCHES "Frameworks") # if it is a framework + # # get last segment of path + # get_filename_component(fname "${item}" NAME_WE) + # # now cycle through dirs + # find_library(ri NAMES ${fname} PATHS ${exepath} ${dirs}) + # if (ri) + # message(STATUS "found ${ri} for ${item}") + # set(${resolved_item_var} ri) + # endif() + # endif() + # endif() + #endfunction(gp_resolve_item_override) + + #gp_resolve_item_override("" "@executable_path/../Frameworks/Ogre.framework" + # /Users/corristo/Projects/OpenMW/build/OpenMW.app/Contents/MacOS + # "" + # "" + # "") +endif (APPLE) # Macros @@ -268,36 +295,6 @@ if (CMAKE_COMPILER_IS_GNUCC) add_definitions (-Wall) endif (CMAKE_COMPILER_IS_GNUCC) -# Apple bundling -# TODO REWRITE! -if (APPLE) - set(MISC_FILES - ${APP_BUNDLE_DIR}/Contents/MacOS/openmw.cfg - ${APP_BUNDLE_DIR}/Contents/MacOS/plugins.cfg) - - set(OGRE_PLUGINS - ${APP_BUNDLE_DIR}/Contents/Plugins/*) - -install(FILES ${MISC_FILES} DESTINATION ../MacOS) -install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Plugins" DESTINATION ..) -install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Resources/resources" DESTINATION ../Resources) -set(CPACK_GENERATOR "Bundle") -set(CPACK_BUNDLE_PLIST "${CMAKE_SOURCE_DIR}/files/mac/Info.plist") -set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/files/mac/openmw.icns") -set(CPACK_BUNDLE_NAME "OpenMW") -set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) -set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) -set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO}) -set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) - -include(CPack) - -set(CMAKE_EXE_LINKER_FLAGS "-arch i386") -set(CMAKE_CXX_FLAGS "-arch i386") - -endif (APPLE) - - if(DPKG_PROGRAM) SET(CMAKE_INSTALL_PREFIX "/usr") @@ -405,3 +402,69 @@ if (WIN32) #set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") #set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS") endif() + +# Apple bundling +# TODO REWRITE! +if (APPLE) + set(MISC_FILES + ${APP_BUNDLE_DIR}/Contents/MacOS/openmw.cfg + ${APP_BUNDLE_DIR}/Contents/MacOS/plugins.cfg) + + set(OGRE_PLUGINS + ${APP_BUNDLE_DIR}/Contents/Plugins/*) + +#install(FILES ${MISC_FILES} DESTINATION ../MacOS) +#install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Plugins" DESTINATION ..) +#install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Resources/resources" DESTINATION ../Resources) +install(DIRECTORY "${APP_BUNDLE_DIR}" DESTINATION . COMPONENT Runtime) +set(CPACK_GENERATOR "DragNDrop") +# set(CPACK_BUNDLE_PLIST "${CMAKE_SOURCE_DIR}/files/mac/Info.plist") +# set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/files/mac/openmw.icns") +# set(CPACK_BUNDLE_NAME "OpenMW") +set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) +set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO}) +set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) + +set(APPS "\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_NAME}") +set(DIRS "") + +INSTALL(CODE " + set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES}) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set(CMAKE_SYSTEM_FRAMEWORK_PATH ${CMAKE_SYSTEM_FRAMEWORK_PATH}) + + set(OPENMW_RESOLVED_ITEMS \"\") + + function(gp_resolve_item_override context item exepath dirs resolved_item_var resolved_var) + if(item MATCHES \"@executable_path\" AND NOT \${\${resolved_var}}) + if (item MATCHES \"Frameworks\") # if it is a framework + # get last segment of path + get_filename_component(fname \"\${item}\" NAME_WE) + find_library(ri NAMES \${fname} PATHS \${exepath} \${dirs} /Library/Frameworks) + if (ri) + message(STATUS \"found \${ri} for \${item}\") + string(REGEX REPLACE \"^.*/Frameworks/.*\\\\.framework\" \"\" item_part \${item}) + set(ri \"\${ri}\${item_part}\") + set(\${resolved_item_var} \${ri} PARENT_SCOPE) + set(\${resolved_var} 1 PARENT_SCOPE) + set(OPENMW_RESOLVED_ITEMS \${_OPENMW_RESOLVED_ITEMS} \${ri}) + endif() + else() + # code path for standard (non-framework) libs (ogre & qt pugins) + endif() + endif() + endfunction(gp_resolve_item_override) + + cmake_policy(SET CMP0009 OLD) + set(BU_CHMOD_BUNDLE_ITEMS ON) + include(BundleUtilities) + fixup_bundle(\"${APPS}\" \"\" \"${DIRS}\") + " COMPONENT Runtime) + +include(CPack) + +set(CMAKE_EXE_LINKER_FLAGS "-arch i386") +set(CMAKE_CXX_FLAGS "-arch i386") + +endif (APPLE) \ No newline at end of file diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index e9e548c0e..d8fe3deb5 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -86,10 +86,6 @@ target_link_libraries(openmw if(APPLE) find_library(CARBON_FRAMEWORK Carbon) target_link_libraries(openmw ${CARBON_FRAMEWORK}) - install(TARGETS openmw - BUNDLE DESTINATION . - RUNTIME DESTINATION ../MacOS - COMPONENT Runtime) endif(APPLE) if(DPKG_PROGRAM) From 705b2955a0c522036fba85cea90df982900d16cb Mon Sep 17 00:00:00 2001 From: Nikolay Kasyanov Date: Mon, 30 Jan 2012 00:28:02 +0400 Subject: [PATCH 31/47] Feature #162 - Need to create app bundle using CMake, not by hand. In progress, working towards plugins support. --- CMakeLists.txt | 57 ++++++++++++++++---------------------------- files/mac/Info.plist | 2 +- 2 files changed, 21 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 156035ccb..740ec83bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,31 +7,6 @@ if (APPLE) # using 10.6 sdk set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.6.sdk") - - # This override needed to handle cases where some dependencies already fixed up, - # so BundleUtilities cannot find them - - #function(gp_resolve_item_override context item exepath dirs resolved_item resolved) - # message(STATUS "gp_resolve_item_override for ${item} with ${exepath} and ${dirs}") - # if(item MATCHES "@executable_path" AND resolved) - # if (item MATCHES "Frameworks") # if it is a framework - # # get last segment of path - # get_filename_component(fname "${item}" NAME_WE) - # # now cycle through dirs - # find_library(ri NAMES ${fname} PATHS ${exepath} ${dirs}) - # if (ri) - # message(STATUS "found ${ri} for ${item}") - # set(${resolved_item_var} ri) - # endif() - # endif() - # endif() - #endfunction(gp_resolve_item_override) - - #gp_resolve_item_override("" "@executable_path/../Frameworks/Ogre.framework" - # /Users/corristo/Projects/OpenMW/build/OpenMW.app/Contents/MacOS - # "" - # "" - # "") endif (APPLE) # Macros @@ -227,6 +202,13 @@ include_directories("." link_directories(${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR}) +if(APPLE) + # List used Ogre plugins + SET(USED_OGRE_PLUGINS "RenderSystem_GL" + "Plugin_OctreeSceneManager" + "Plugin_ParticleFX") +endif(APPLE) + add_subdirectory( extern/caelum ) add_subdirectory( extern/mygui_3.0.1 ) @@ -270,22 +252,17 @@ if (APPLE) "${OpenMW_BINARY_DIR}/plugins.cfg") configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist - "${APP_BUNDLE_DIR}/Contents/Info.plist" COPYONLY) + "${APP_BUNDLE_DIR}/Contents/Info.plist") configure_file(${OpenMW_SOURCE_DIR}/files/mac/openmw.icns "${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY) - # prepare plugins - configure_file(${OGRE_PLUGIN_DIR}/RenderSystem_GL.dylib - "${APP_BUNDLE_DIR}/Contents/Plugins/RenderSystem_GL.dylib" COPYONLY) - - configure_file(${OGRE_PLUGIN_DIR}/Plugin_OctreeSceneManager.dylib - "${APP_BUNDLE_DIR}/Contents/Plugins/Plugin_OctreeSceneManager.dylib" COPYONLY) - - configure_file(${OGRE_PLUGIN_DIR}/Plugin_ParticleFX.dylib - "${APP_BUNDLE_DIR}/Contents/Plugins/Plugin_ParticleFX.dylib" COPYONLY) - + foreach(plugin ${USED_OGRE_PLUGINS}) + configure_file("${OGRE_PLUGIN_DIR}/${plugin}.dylib" + "${APP_BUNDLE_DIR}/Contents/Plugins/${plugin}.dylib" + COPYONLY) + endforeach() endif (APPLE) @@ -427,6 +404,12 @@ set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO}) set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) set(APPS "\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_NAME}") +set(PLUGINS "") + +foreach(plugin ${USED_OGRE_PLUGINS}) + set(PLUGINS ${PLUGINS} "\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_NAME}/Contents/Plugins/${plugin}.dylib") +endforeach() + set(DIRS "") INSTALL(CODE " @@ -459,7 +442,7 @@ INSTALL(CODE " cmake_policy(SET CMP0009 OLD) set(BU_CHMOD_BUNDLE_ITEMS ON) include(BundleUtilities) - fixup_bundle(\"${APPS}\" \"\" \"${DIRS}\") + fixup_bundle(\"${APPS}\" \"${PLUGINS}\" \"${DIRS}\") " COMPONENT Runtime) include(CPack) diff --git a/files/mac/Info.plist b/files/mac/Info.plist index 1872425e7..bc7efd075 100644 --- a/files/mac/Info.plist +++ b/files/mac/Info.plist @@ -19,7 +19,7 @@ CFBundleSignature ???? CFBundleVersion - 0.10 + ${OPENMW_VERSION} CSResourcesFileMapped LSRequiresCarbon From 4fe31fbd61d112fd01838027c1e64c88c01ec69f Mon Sep 17 00:00:00 2001 From: "Alexander \"Ace\" Olofsson" Date: Sun, 29 Jan 2012 23:08:02 +0100 Subject: [PATCH 32/47] Simple windows packaging with CPack (NSIS) --- CMakeLists.txt | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 723d10b34..b22181148 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -351,6 +351,34 @@ if(DPKG_PROGRAM) include(CPack) endif(DPKG_PROGRAM) +if(WIN32) + FILE(GLOB files "${OpenMW_BINARY_DIR}/Release/*.*") + INSTALL(FILES ${files} DESTINATION ".") + INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg") + INSTALL(FILES "${OpenMW_BINARY_DIR}/launcher.cfg" "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION ".") + INSTALL(FILES "${OpenMW_BINARY_DIR}/vcredist_x86.exe" DESTINATION "redist") + INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".") + + SET(CPACK_GENERATOR "NSIS") + SET(CPACK_PACKAGE_NAME "OpenMW") + SET(CPACK_PACKAGE_VENDOR "OpenMW.org") + SET(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) + SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) + SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO}) + SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) + SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW;esmtool;Esmtool;omwlauncher;OpenMW Launcher") + SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/readme.txt") + SET(CPACK_RESOURCE_FILE_LICENSE "${OpenMW_SOURCE_DIR}/GPL3.txt") + SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") + SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\redist\\\\vcredist_x86.exe\\\" /q'" ) + SET(CPACK_NSIS_DISPLAY_NAME "OpenMW") + SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org") + SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org") + SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe") + + include(CPack) +endif(WIN32) + # Components add_subdirectory (components) From 72c4f752127ced4508e791d367fee8af8ccbe58d Mon Sep 17 00:00:00 2001 From: "Alexander \"Ace\" Olofsson" Date: Sun, 29 Jan 2012 23:12:40 +0100 Subject: [PATCH 33/47] Only install redist if it exists --- CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b22181148..40752c7f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -356,7 +356,6 @@ if(WIN32) INSTALL(FILES ${files} DESTINATION ".") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg") INSTALL(FILES "${OpenMW_BINARY_DIR}/launcher.cfg" "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION ".") - INSTALL(FILES "${OpenMW_BINARY_DIR}/vcredist_x86.exe" DESTINATION "redist") INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".") SET(CPACK_GENERATOR "NSIS") @@ -370,12 +369,16 @@ if(WIN32) SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/readme.txt") SET(CPACK_RESOURCE_FILE_LICENSE "${OpenMW_SOURCE_DIR}/GPL3.txt") SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") - SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\redist\\\\vcredist_x86.exe\\\" /q'" ) SET(CPACK_NSIS_DISPLAY_NAME "OpenMW") SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org") SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org") SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe") + if(EXISTS "${OpenMW_BINARY_DIR}/vcredist_x86.exe") + INSTALL(FILES "${OpenMW_BINARY_DIR}/vcredist_x86.exe" DESTINATION "redist") + SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\redist\\\\vcredist_x86.exe\\\" /q'" ) + endif(EXISTS "${OpenMW_BINARY_DIR}/vcredist_x86.exe") + include(CPack) endif(WIN32) From 472d88e2c558f5dbcf96cf99f1b8b026b8506efb Mon Sep 17 00:00:00 2001 From: Nikolay Kasyanov Date: Wed, 1 Feb 2012 20:48:13 +0400 Subject: [PATCH 34/47] Feature #162 - Need to create app bundle using CMake, not by hand WIP --- CMakeLists.txt | 120 +++++++++++++++++++---------------- apps/launcher/CMakeLists.txt | 18 ++++++ 2 files changed, 82 insertions(+), 56 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 740ec83bd..50ed5e1c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -381,69 +381,77 @@ if (WIN32) endif() # Apple bundling -# TODO REWRITE! if (APPLE) set(MISC_FILES ${APP_BUNDLE_DIR}/Contents/MacOS/openmw.cfg ${APP_BUNDLE_DIR}/Contents/MacOS/plugins.cfg) - set(OGRE_PLUGINS - ${APP_BUNDLE_DIR}/Contents/Plugins/*) - -#install(FILES ${MISC_FILES} DESTINATION ../MacOS) -#install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Plugins" DESTINATION ..) -#install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Resources/resources" DESTINATION ../Resources) -install(DIRECTORY "${APP_BUNDLE_DIR}" DESTINATION . COMPONENT Runtime) -set(CPACK_GENERATOR "DragNDrop") -# set(CPACK_BUNDLE_PLIST "${CMAKE_SOURCE_DIR}/files/mac/Info.plist") -# set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/files/mac/openmw.icns") -# set(CPACK_BUNDLE_NAME "OpenMW") -set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) -set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) -set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO}) -set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) - -set(APPS "\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_NAME}") -set(PLUGINS "") - -foreach(plugin ${USED_OGRE_PLUGINS}) - set(PLUGINS ${PLUGINS} "\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_NAME}/Contents/Plugins/${plugin}.dylib") -endforeach() - -set(DIRS "") - -INSTALL(CODE " - set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES}) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - set(CMAKE_SYSTEM_FRAMEWORK_PATH ${CMAKE_SYSTEM_FRAMEWORK_PATH}) - - set(OPENMW_RESOLVED_ITEMS \"\") - - function(gp_resolve_item_override context item exepath dirs resolved_item_var resolved_var) - if(item MATCHES \"@executable_path\" AND NOT \${\${resolved_var}}) - if (item MATCHES \"Frameworks\") # if it is a framework - # get last segment of path - get_filename_component(fname \"\${item}\" NAME_WE) - find_library(ri NAMES \${fname} PATHS \${exepath} \${dirs} /Library/Frameworks) - if (ri) - message(STATUS \"found \${ri} for \${item}\") - string(REGEX REPLACE \"^.*/Frameworks/.*\\\\.framework\" \"\" item_part \${item}) - set(ri \"\${ri}\${item_part}\") - set(\${resolved_item_var} \${ri} PARENT_SCOPE) - set(\${resolved_var} 1 PARENT_SCOPE) - set(OPENMW_RESOLVED_ITEMS \${_OPENMW_RESOLVED_ITEMS} \${ri}) + #install(FILES ${MISC_FILES} DESTINATION ../MacOS) + #install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Plugins" DESTINATION ..) + #install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Resources/resources" DESTINATION ../Resources) + install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION . COMPONENT Runtime) + set(CPACK_GENERATOR "DragNDrop") + # set(CPACK_BUNDLE_PLIST "${CMAKE_SOURCE_DIR}/files/mac/Info.plist") + # set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/files/mac/openmw.icns") + # set(CPACK_BUNDLE_NAME "OpenMW") + set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) + set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) + set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO}) + set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) + + set(APPS "\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_NAME}") + set(PLUGINS "") + + # Scan Plugins dir for *.dylibs + file(GLOB ALL_PLUGINS "${APP_BUNDLE_DIR}/Contents/Plugins/*.dylib") + + foreach(PLUGIN ${ALL_PLUGINS}) + get_filename_component(PLUGIN_FILENAME ${PLUGIN} NAME) + set(PLUGINS ${PLUGINS} "\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_NAME}/Contents/Plugins/${PLUGIN_FILENAME}") + endforeach() + + #For now, search unresolved dependencies only in default system paths, so if you put unresolveable (i.e. with @executable_path in id name) lib or framework somewhere else, it would fail + set(DIRS "") + + # Overriding item resolving during installation, it needed if + # some library already has be "fixed up", i.e. its id name contains @executable_path, + # but library is not embedded in bundle. For example, it's Ogre.framework from Ogre SDK. + # Current implementation of GetPrerequsities/BundleUtilities doesn't handle that case. + # + # Current limitations: + # 1. Handles only frameworks, not simple libs + INSTALL(CODE " + set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES}) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set(CMAKE_SYSTEM_FRAMEWORK_PATH ${CMAKE_SYSTEM_FRAMEWORK_PATH}) + + set(OPENMW_RESOLVED_ITEMS \"\") + + function(gp_resolve_item_override context item exepath dirs resolved_item_var resolved_var) + if(item MATCHES \"@executable_path\" AND NOT \${\${resolved_var}}) + if (item MATCHES \"Frameworks\") # if it is a framework + # get last segment of path + get_filename_component(fname \"\${item}\" NAME_WE) + find_library(ri NAMES \${fname} PATHS \${exepath} \${dirs} /Library/Frameworks) + if (ri) + message(STATUS \"found \${ri} for \${item}\") + string(REGEX REPLACE \"^.*/Frameworks/.*\\\\.framework\" \"\" item_part \${item}) + set(ri \"\${ri}\${item_part}\") + set(\${resolved_item_var} \${ri} PARENT_SCOPE) + set(\${resolved_var} 1 PARENT_SCOPE) + set(OPENMW_RESOLVED_ITEMS \${_OPENMW_RESOLVED_ITEMS} \${ri}) + endif() + else() + # code path for standard (non-framework) libs (ogre & qt pugins) endif() - else() - # code path for standard (non-framework) libs (ogre & qt pugins) endif() - endif() - endfunction(gp_resolve_item_override) - - cmake_policy(SET CMP0009 OLD) - set(BU_CHMOD_BUNDLE_ITEMS ON) - include(BundleUtilities) - fixup_bundle(\"${APPS}\" \"${PLUGINS}\" \"${DIRS}\") - " COMPONENT Runtime) + endfunction(gp_resolve_item_override) + + cmake_policy(SET CMP0009 OLD) + set(BU_CHMOD_BUNDLE_ITEMS ON) + include(BundleUtilities) + fixup_bundle(\"${APPS}\" \"${PLUGINS}\" \"${DIRS}\") + " COMPONENT Runtime) include(CPack) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 2fc3189fc..235bec6ab 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -49,6 +49,17 @@ QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) include(${QT_USE_FILE}) +# list here plugins that can't be detected statically, but loaded in runtime +# it needed for packaging automatisation +#set(USED_QT_PLUGINS imageformats/libqgif +# imageformats/libqico +# imageformats/libqjpeg +# imageformats/libqmng +# imageformats/libqsvg +# imageformats/libqtga +# imageformats/libqtiff) +# It seems that launcher works without this plugins, but it loads them into memory if they exists + # Main executable add_executable(omwlauncher ${LAUNCHER} @@ -73,6 +84,13 @@ if (APPLE) "${APP_BUNDLE_DIR}/../launcher.qss") configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss "${APP_BUNDLE_DIR}/../launcher.cfg") + + # copy used QT plugins into ${APP_BUNDLE_DIR}/Contents/Plugins + #foreach(PLUGIN ${USED_QT_PLUGINS}) + # get_filename_component(PLUGIN_FILENAME ${PLUGIN} NAME) + # configure_file("${QT_PLUGINS_DIR}/${PLUGIN}.dylib" "${APP_BUNDLE_DIR}/Contents/Plugins/${PLUGIN_FILENAME}.dylib" COPYONLY) + #endforeach() + else() configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.qss") From ee021548050d15219096dba07854f3f932c76603 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 4 Feb 2012 10:48:15 +0100 Subject: [PATCH 35/47] lights without a mesh were not rendered --- apps/openmw/mwclass/light.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 3890899b0..0009c575b 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -23,19 +23,19 @@ namespace MWClass assert (ref->base != NULL); const std::string &model = ref->base->model; - + + MWRender::Objects& objects = renderingInterface.getObjects(); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + if (!model.empty()) - { - MWRender::Objects& objects = renderingInterface.getObjects(); - objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); objects.insertMesh(ptr, "meshes\\" + model); - const int color = ref->base->data.color; - const float r = ((color >> 0) & 0xFF) / 255.0f; - const float g = ((color >> 8) & 0xFF) / 255.0f; - const float b = ((color >> 16) & 0xFF) / 255.0f; - const float radius = float (ref->base->data.radius); - objects.insertLight (ptr, r, g, b, radius); - } + + const int color = ref->base->data.color; + const float r = ((color >> 0) & 0xFF) / 255.0f; + const float g = ((color >> 8) & 0xFF) / 255.0f; + const float b = ((color >> 16) & 0xFF) / 255.0f; + const float radius = float (ref->base->data.radius); + objects.insertLight (ptr, r, g, b, radius); } void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const @@ -43,13 +43,12 @@ namespace MWClass ESMS::LiveCellRef *ref = ptr.get(); - - const std::string &model = ref->base->model; assert (ref->base != NULL); + const std::string &model = ref->base->model; + if(!model.empty()){ physics.insertObjectPhysics(ptr, "meshes\\" + model); } - } void Light::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const From c471aa950f89bf674a49d7ea2f5a385643954eb5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 6 Feb 2012 09:42:24 +0100 Subject: [PATCH 36/47] re-enabled batching for statics; fixed a misplaced assert --- apps/openmw/mwclass/static.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index 946da311d..24d36dc1e 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -15,11 +15,11 @@ namespace MWClass assert (ref->base != NULL); const std::string &model = ref->base->model; - + if (!model.empty()) { MWRender::Objects& objects = renderingInterface.getObjects(); - objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); + objects.insertBegin(ptr, ptr.getRefData().isEnabled(), true); objects.insertMesh(ptr, "meshes\\" + model); } } @@ -29,13 +29,12 @@ namespace MWClass ESMS::LiveCellRef *ref = ptr.get(); - - const std::string &model = ref->base->model; assert (ref->base != NULL); + const std::string &model = ref->base->model; + if(!model.empty()){ physics.insertObjectPhysics(ptr, "meshes\\" + model); } - } std::string Static::getName (const MWWorld::Ptr& ptr) const From e1600d9a2a57b235c8b6b2851cd62fa96928e57d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 6 Feb 2012 10:29:18 +0100 Subject: [PATCH 37/47] fixed movable object cleanup for ordinary objects --- apps/openmw/mwrender/objects.cpp | 19 ++++++++++++++++++- apps/openmw/mwrender/objects.hpp | 9 +++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 1e3b4dda0..d04751ff3 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -23,6 +23,17 @@ bool Objects::lightOutQuadInLin = false; int Objects::uniqueID = 0; +void Objects::clearSceneNode (Ogre::SceneNode *node) +{ + /// \todo This should probably be moved into OpenEngine at some point. + for (int i=node->numAttachedObjects()-1; i>=0; --i) + { + Ogre::MovableObject *object = node->getAttachedObject (i); + node->detachObject (object); + mRend.getScene()->destroyMovableObject (object); + } +} + void Objects::setMwRoot(Ogre::SceneNode* root){ mMwRoot = root; } @@ -59,6 +70,7 @@ void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){ // Rotates first around z, then y, then x insert->setOrientation(xr*yr*zr); + if (!enabled) insert->setVisible (false); ptr.getRefData().setBaseNode(insert); @@ -145,6 +157,7 @@ bool Objects::deleteObject (const MWWorld::Ptr& ptr) mCellSceneNodes.begin()); iter!=mCellSceneNodes.end(); ++iter) if (iter->second==parent) { + clearSceneNode (base); base->removeAndDestroyAllChildren(); mRend.getScene()->destroySceneNode (base); ptr.getRefData().setBaseNode (0); @@ -161,13 +174,16 @@ void Objects::removeCell(MWWorld::Ptr::CellStore* store){ if(mCellSceneNodes.find(store) != mCellSceneNodes.end()) { Ogre::SceneNode* base = mCellSceneNodes[store]; + + for (int i=0; inumChildren(); ++i) + clearSceneNode (static_cast (base->getChild (i))); + base->removeAndDestroyAllChildren(); mCellSceneNodes.erase(store); mRend.getScene()->destroySceneNode(base); base = 0; } - if(mSG.find(store) != mSG.end()) { Ogre::StaticGeometry* sg = mSG[store]; @@ -176,6 +192,7 @@ void Objects::removeCell(MWWorld::Ptr::CellStore* store){ sg = 0; } } + void Objects::buildStaticGeometry(ESMS::CellStore& cell){ if(mSG.find(&cell) != mSG.end()) { diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp index 6cd465fdd..737f9acec 100644 --- a/apps/openmw/mwrender/objects.hpp +++ b/apps/openmw/mwrender/objects.hpp @@ -1,11 +1,12 @@ #ifndef _GAME_RENDER_OBJECTS_H #define _GAME_RENDER_OBJECTS_H -#include "components/esm_store/cell_store.hpp" +#include + +#include #include "../mwworld/refdata.hpp" #include "../mwworld/ptr.hpp" -#include namespace MWRender{ @@ -30,6 +31,10 @@ class Objects{ static float lightQuadraticRadiusMult; static bool lightOutQuadInLin; + + void clearSceneNode (Ogre::SceneNode *node); + ///< Remove all movable objects from \a node. + public: Objects(OEngine::Render::OgreRenderer& _rend): mRend(_rend){} ~Objects(){} From 784c6fe0ffc0e645c97485c1b4cce6aa2f4ff6b2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 6 Feb 2012 10:41:13 +0100 Subject: [PATCH 38/47] some cleanup --- apps/openmw/mwrender/objects.cpp | 121 ++++++++++++++++--------------- apps/openmw/mwrender/objects.hpp | 8 +- 2 files changed, 67 insertions(+), 62 deletions(-) diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index d04751ff3..4e2a3caab 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -1,11 +1,11 @@ #include "objects.hpp" + #include + #include -using namespace Ogre; using namespace MWRender; - bool Objects::lightConst = false; float Objects::lightConstValue = 0.0f; @@ -30,14 +30,17 @@ void Objects::clearSceneNode (Ogre::SceneNode *node) { Ogre::MovableObject *object = node->getAttachedObject (i); node->detachObject (object); - mRend.getScene()->destroyMovableObject (object); + mRenderer.getScene()->destroyMovableObject (object); } } -void Objects::setMwRoot(Ogre::SceneNode* root){ +void Objects::setMwRoot(Ogre::SceneNode* root) +{ mMwRoot = root; } -void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){ + +void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_) +{ Ogre::SceneNode* root = mMwRoot; Ogre::SceneNode* cellnode; if(mCellSceneNodes.find(ptr.getCell()) == mCellSceneNodes.end()) @@ -60,91 +63,91 @@ void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){ f = ptr.getCellRef().pos.rot; // Rotate around X axis - Quaternion xr(Radian(-f[0]), Vector3::UNIT_X); + Ogre::Quaternion xr(Ogre::Radian(-f[0]), Ogre::Vector3::UNIT_X); // Rotate around Y axis - Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y); + Ogre::Quaternion yr(Ogre::Radian(-f[1]), Ogre::Vector3::UNIT_Y); // Rotate around Z axis - Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z); + Ogre::Quaternion zr(Ogre::Radian(-f[2]), Ogre::Vector3::UNIT_Z); - // Rotates first around z, then y, then x + // Rotates first around z, then y, then x insert->setOrientation(xr*yr*zr); if (!enabled) insert->setVisible (false); ptr.getRefData().setBaseNode(insert); - isStatic = static_; - - + mIsStatic = static_; } -void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh){ + +void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) +{ Ogre::SceneNode* insert = ptr.getRefData().getBaseNode(); assert(insert); NifOgre::NIFLoader::load(mesh); - Entity *ent = mRend.getScene()->createEntity(mesh); + Ogre::Entity *ent = mRenderer.getScene()->createEntity(mesh); - if(!isStatic) + if(!mIsStatic) { insert->attachObject(ent); } else { Ogre::StaticGeometry* sg = 0; - if(mSG.find(ptr.getCell()) == mSG.end()) + if(mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end()) { uniqueID = uniqueID +1; - sg = mRend.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); + sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); //Create the scenenode and put it in the map - mSG[ptr.getCell()] = sg; + mStaticGeometry[ptr.getCell()] = sg; } else { - sg = mSG[ptr.getCell()]; + sg = mStaticGeometry[ptr.getCell()]; } sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale()); sg->setRegionDimensions(Ogre::Vector3(100000,10000,100000)); - - mRend.getScene()->destroyEntity(ent); + mRenderer.getScene()->destroyEntity(ent); } - - } -void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius){ - Ogre::SceneNode* insert = mRend.getScene()->getSceneNode(ptr.getRefData().getHandle()); + +void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius) +{ + Ogre::SceneNode* insert = mRenderer.getScene()->getSceneNode(ptr.getRefData().getHandle()); assert(insert); - Ogre::Light *light = mRend.getScene()->createLight(); + Ogre::Light *light = mRenderer.getScene()->createLight(); light->setDiffuseColour (r, g, b); float cval=0.0f, lval=0.0f, qval=0.0f; if(lightConst) cval = lightConstValue; - if(!lightOutQuadInLin) - { - if(lightLinear) - radius *= lightLinearRadiusMult; - if(lightQuadratic) - radius *= lightQuadraticRadiusMult; - - if(lightLinear) - lval = lightLinearValue / pow(radius, lightLinearMethod); - if(lightQuadratic) - qval = lightQuadraticValue / pow(radius, lightQuadraticMethod); - } - else - { - // FIXME: - // Do quadratic or linear, depending if we're in an exterior or interior - // cell, respectively. Ignore lightLinear and lightQuadratic. - } - - light->setAttenuation(10*radius, cval, lval, qval); - - insert->attachObject(light); + + if(!lightOutQuadInLin) + { + if(lightLinear) + radius *= lightLinearRadiusMult; + if(lightQuadratic) + radius *= lightQuadraticRadiusMult; + + if(lightLinear) + lval = lightLinearValue / pow(radius, lightLinearMethod); + if(lightQuadratic) + qval = lightQuadraticValue / pow(radius, lightQuadraticMethod); + } + else + { + // FIXME: + // Do quadratic or linear, depending if we're in an exterior or interior + // cell, respectively. Ignore lightLinear and lightQuadratic. + } + + light->setAttenuation(10*radius, cval, lval, qval); + + insert->attachObject(light); } bool Objects::deleteObject (const MWWorld::Ptr& ptr) @@ -159,7 +162,7 @@ bool Objects::deleteObject (const MWWorld::Ptr& ptr) { clearSceneNode (base); base->removeAndDestroyAllChildren(); - mRend.getScene()->destroySceneNode (base); + mRenderer.getScene()->destroySceneNode (base); ptr.getRefData().setBaseNode (0); return true; } @@ -170,7 +173,8 @@ bool Objects::deleteObject (const MWWorld::Ptr& ptr) return true; } -void Objects::removeCell(MWWorld::Ptr::CellStore* store){ +void Objects::removeCell(MWWorld::Ptr::CellStore* store) +{ if(mCellSceneNodes.find(store) != mCellSceneNodes.end()) { Ogre::SceneNode* base = mCellSceneNodes[store]; @@ -180,23 +184,24 @@ void Objects::removeCell(MWWorld::Ptr::CellStore* store){ base->removeAndDestroyAllChildren(); mCellSceneNodes.erase(store); - mRend.getScene()->destroySceneNode(base); + mRenderer.getScene()->destroySceneNode(base); base = 0; } - if(mSG.find(store) != mSG.end()) + if(mStaticGeometry.find(store) != mStaticGeometry.end()) { - Ogre::StaticGeometry* sg = mSG[store]; - mSG.erase(store); - mRend.getScene()->destroyStaticGeometry (sg); + Ogre::StaticGeometry* sg = mStaticGeometry[store]; + mStaticGeometry.erase(store); + mRenderer.getScene()->destroyStaticGeometry (sg); sg = 0; } } -void Objects::buildStaticGeometry(ESMS::CellStore& cell){ - if(mSG.find(&cell) != mSG.end()) +void Objects::buildStaticGeometry(ESMS::CellStore& cell) +{ + if(mStaticGeometry.find(&cell) != mStaticGeometry.end()) { - Ogre::StaticGeometry* sg = mSG[&cell]; + Ogre::StaticGeometry* sg = mStaticGeometry[&cell]; sg->build(); } } diff --git a/apps/openmw/mwrender/objects.hpp b/apps/openmw/mwrender/objects.hpp index 737f9acec..d58455b9f 100644 --- a/apps/openmw/mwrender/objects.hpp +++ b/apps/openmw/mwrender/objects.hpp @@ -11,11 +11,11 @@ namespace MWRender{ class Objects{ - OEngine::Render::OgreRenderer &mRend; + OEngine::Render::OgreRenderer &mRenderer; std::map mCellSceneNodes; - std::map mSG; + std::map mStaticGeometry; Ogre::SceneNode* mMwRoot; - bool isStatic; + bool mIsStatic; static int uniqueID; static bool lightConst; static float lightConstValue; @@ -36,7 +36,7 @@ class Objects{ ///< Remove all movable objects from \a node. public: - Objects(OEngine::Render::OgreRenderer& _rend): mRend(_rend){} + Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer){} ~Objects(){} void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_); void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh); From 0b0254d30e053c370d31c1eef5cc27a75819ae18 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 6 Feb 2012 10:48:14 +0100 Subject: [PATCH 39/47] spelling fix --- apps/openmw/mwscript/controlextensions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index 893af259f..5289be24a 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -48,7 +48,7 @@ namespace MWScript bool enabled = context.getWorld().toggleCollisionMode(); - context.report (enabled ? "Collsion -> On" : "Collision -> Off"); + context.report (enabled ? "Collision -> On" : "Collision -> Off"); } }; From c4e028effe9f02fe5efb3c47647a3b7bc6aede95 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 6 Feb 2012 10:48:58 +0100 Subject: [PATCH 40/47] fixing a faulty include --- apps/openmw/mwscript/controlextensions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index 5289be24a..384e13e45 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -1,5 +1,5 @@ -#include "statsextensions.hpp" +#include "controlextensions.hpp" #include From 597e670eef30025c1e49303dc5ed0afaf87a5304 Mon Sep 17 00:00:00 2001 From: gugus Date: Wed, 8 Feb 2012 00:32:22 +0100 Subject: [PATCH 41/47] corrected the light problem --- apps/openmw/mwrender/renderingmanager.cpp | 13 +++++++++---- apps/openmw/mwrender/renderingmanager.hpp | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index c5cf8be5d..bc33951e7 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -54,10 +54,12 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const cameraPitchNode->attachObject(mRendering.getCamera()); mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); + mSun = 0; } RenderingManager::~RenderingManager () { + //TODO: destroy mSun? delete mPlayer; delete mSkyManager; } @@ -204,12 +206,15 @@ void RenderingManager::configureAmbient(ESMS::CellStore &mCell // Create a "sun" that shines light downwards. It doesn't look // completely right, but leave it for now. - Ogre::Light *light = mRendering.getScene()->createLight(); + if(!mSun) + { + mSun = mRendering.getScene()->createLight(); + } Ogre::ColourValue colour; colour.setAsABGR (mCell.cell->ambi.sunlight); - light->setDiffuseColour (colour); - light->setType(Ogre::Light::LT_DIRECTIONAL); - light->setDirection(0,-1,0); + mSun->setDiffuseColour (colour); + mSun->setType(Ogre::Light::LT_DIRECTIONAL); + mSun->setDirection(0,-1,0); } // Switch through lighting modes. diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 084f89cb0..ca5d95a3f 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -118,6 +118,7 @@ class RenderingManager: private RenderingInterface { int mAmbientMode; Ogre::ColourValue mAmbientColor; + Ogre::Light* mSun; /// Root node for all objects added to the scene. This is rotated so /// that the OGRE coordinate system matches that used internally in From 4fcb72105424a81a3ffb33f80be9d667b05d1576 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 10 Feb 2012 14:59:22 +0100 Subject: [PATCH 42/47] openengine update (physics crash workaround --- libs/openengine | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/openengine b/libs/openengine index 6c7e5d00e..4a188f282 160000 --- a/libs/openengine +++ b/libs/openengine @@ -1 +1 @@ -Subproject commit 6c7e5d00e4f5bf954afe15f10e56f03520abfee4 +Subproject commit 4a188f2820c037ca4ad8ef35492d3857ea8d7df8 From 17b1546dc1694b5419287c7b7d8c5e86a39e83e3 Mon Sep 17 00:00:00 2001 From: Pieter van der Kloet Date: Fri, 10 Feb 2012 19:17:49 +0100 Subject: [PATCH 43/47] Changed the way screenshots are created (Bug #191) --- apps/openmw/engine.cpp | 22 ++++++++++++++++++++++ apps/openmw/engine.hpp | 3 +++ apps/openmw/mwinput/inputmanager.cpp | 15 +-------------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index ee3a6181a..3579977b0 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -462,6 +462,28 @@ void OMW::Engine::activate() } } +void OMW::Engine::screenshot() +{ + // Count screenshots. + int shotCount = 0; + + const std::string screenshotPath = mCfgMgr.getLocalConfigPath().string(); + + // Find the first unused filename with a do-while + std::ostringstream stream; + do + { + // Reset the stream + stream.str(""); + stream.clear(); + + stream << screenshotPath << "screenshot" << std::setw(3) << std::setfill('0') << shotCount++ << ".png"; + + } while (boost::filesystem::exists(stream.str())); + + mOgre->screenshot(stream.str()); +} + void OMW::Engine::setCompileAll (bool all) { mCompileAll = all; diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 02d108f0a..88eea728e 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -152,6 +152,9 @@ namespace OMW /// Activate the focussed object. void activate(); + /// Write screenshot to file. + void screenshot(); + /// Compile all scripts (excludign dialogue scripts) at startup? void setCompileAll (bool all); diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index e0c819a71..a5d590b85 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -83,27 +83,14 @@ namespace MWInput MWGui::WindowManager &windows; OMW::Engine& mEngine; - // Count screenshots. - int shotCount; - /* InputImpl Methods */ - // Write screenshot to file. void screenshot() { - - // Find the first unused filename with a do-while - char buf[50]; - do - { - snprintf(buf, 50, "screenshot%03d.png", shotCount++); - } while (boost::filesystem::exists(buf)); - - ogre.screenshot(buf); + mEngine.screenshot(); } - /* toggleInventory() is called when the user presses the button to toggle the inventory screen. */ void toggleInventory() { From bc71fb47e018d2c23ce77483d9da646c43bcb7d0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 10 Feb 2012 21:24:33 +0100 Subject: [PATCH 44/47] minor fix --- apps/openmw/mwinput/inputmanager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index a5d590b85..88534ddda 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -170,8 +170,7 @@ namespace MWInput poller(input), player(_player), windows(_windows), - mEngine (engine), - shotCount(0) + mEngine (engine) { using namespace OEngine::Input; using namespace OEngine::Render; From a0ac6e51502368792ee8ddfa3b650dd7366b3760 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 12 Feb 2012 12:35:29 +0100 Subject: [PATCH 45/47] cells were sometimes not fully loaded --- apps/openmw/mwworld/cells.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/cells.cpp b/apps/openmw/mwworld/cells.cpp index 143ce557b..079c888aa 100644 --- a/apps/openmw/mwworld/cells.cpp +++ b/apps/openmw/mwworld/cells.cpp @@ -63,9 +63,10 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y) result = mExteriors.insert (std::make_pair ( std::make_pair (x, y), Ptr::CellStore (cell))).first; + } + if (result->second.mState!=Ptr::CellStore::State_Loaded) result->second.load (mStore, mReader); - } return &result->second; } @@ -79,9 +80,10 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name) const ESM::Cell *cell = mStore.cells.findInt (name); result = mInteriors.insert (std::make_pair (name, Ptr::CellStore (cell))).first; + } + if (result->second.mState!=Ptr::CellStore::State_Loaded) result->second.load (mStore, mReader); - } return &result->second; } From 8829d46bda4f09e365cd97b842abdfe4ef571286 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sun, 12 Feb 2012 15:45:08 +0100 Subject: [PATCH 46/47] Clean up compilation warnings. Clan up compilation warnings like "variable ... set but not used" introduced in some older and recent commits. Signed-off-by: Lukasz Gromanowski --- apps/esmtool/esmtool_cmd.c | 18 +++++++++--------- apps/openmw/mwgui/journalwindow.cpp | 4 ++-- apps/openmw/mwrender/animation.cpp | 2 +- apps/openmw/mwrender/npcanimation.cpp | 2 +- components/nif/data.hpp | 4 ++-- components/nifogre/ogre_nif_loader.cpp | 4 ++-- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/esmtool/esmtool_cmd.c b/apps/esmtool/esmtool_cmd.c index d6556d9e7..3fce77de2 100644 --- a/apps/esmtool/esmtool_cmd.c +++ b/apps/esmtool/esmtool_cmd.c @@ -926,13 +926,13 @@ int update_arg(void *field, char **orig_field, const char *long_opt, char short_opt, const char *additional_error) { - char *stop_char = 0; - const char *val = value; - int found; + //char *stop_char = 0; + //const char *val = value; + //int found; FIX_UNUSED (field); - stop_char = 0; - found = 0; + //stop_char = 0; + //found = 0; if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) { @@ -955,8 +955,8 @@ int update_arg(void *field, char **orig_field, (*prev_given)++; if (field_given) (*field_given)++; - if (possible_values) - val = possible_values[found]; + //if (possible_values) + //val = possible_values[found]; switch(arg_type) { default: @@ -996,7 +996,7 @@ cmdline_parser_internal ( int override; int initialize; - int check_required; + //int check_required; int check_ambiguity; char *optarg; @@ -1008,7 +1008,7 @@ cmdline_parser_internal ( override = params->override; initialize = params->initialize; - check_required = params->check_required; + //check_required = params->check_required; check_ambiguity = params->check_ambiguity; if (initialize) diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 457a07582..3f3c89f39 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -32,8 +32,8 @@ book formatText(std::string text,book mBook,int maxLine, int lineSize) mBook.pages.pop_back(); } - std::string::iterator wordBegin = text.begin(); - std::string::iterator wordEnd; + //std::string::iterator wordBegin = text.begin(); + //std::string::iterator wordEnd; std::string cText = text; diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 5a9731d2d..056550e74 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -499,7 +499,7 @@ namespace MWRender{ std::vector quats = iter->getQuat(); std::vector ttime = iter->gettTime(); - std::vector::iterator ttimeiter = ttime.begin(); + //std::vector::iterator ttimeiter = ttime.begin(); std::vector rtime = iter->getrTime(); int rindexJ = 0; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 863f7577b..fe48aa321 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -267,7 +267,7 @@ void NpcAnimation::runAnimation(float timepassed){ } handleAnimationTransforms(); - Ogre::Vector3 current = insert->_getWorldAABB().getCenter(); + //Ogre::Vector3 current = insert->_getWorldAABB().getCenter(); std::vector*>::iterator shapepartsiter = shapeparts.begin(); std::vector::iterator entitypartsiter = entityparts.begin(); diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 9e28e1534..df9079758 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -473,7 +473,7 @@ void read(NIFFile *nif) int vertCount = nif->getInt(); nif->getByte(); int magic = nif->getInt(); - int type = nif->getInt(); + /*int type =*/ nif->getInt(); for(int i = 0; i < vertCount; i++){ float x = nif->getFloat(); @@ -485,7 +485,7 @@ void read(NIFFile *nif) for(int i=1; igetInt(); - type = nif->getInt(); + /*type =*/ nif->getInt(); std::vector current; std::vector currentTime; for(int i = 0; i < magic; i++){ diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index c62f59ea3..2662f0c97 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1150,7 +1150,7 @@ void NIFLoader::loadResource(Resource *resource) char suffix = name.at(name.length() - 2); bool addAnim = true; bool hasAnim = false; - bool baddin = false; + //bool baddin = false; bNiTri = true; if(suffix == '*') @@ -1168,7 +1168,7 @@ void NIFLoader::loadResource(Resource *resource) } else if(suffix == '>') { - baddin = true; + //baddin = true; bNiTri = true; std::string sub = name.substr(name.length() - 6, 4); From 5a42c6c6f59242f447a30c3ef9c4721db21f54cd Mon Sep 17 00:00:00 2001 From: Nikolay Kasyanov Date: Mon, 13 Feb 2012 10:31:43 +0400 Subject: [PATCH 47/47] Feature #162 - Need to create app bundle using CMake, not by hand WIP. Removed libpng dependency from launcher --- CMakeLists.txt | 15 +++++++++------ apps/launcher/CMakeLists.txt | 6 +++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 50ed5e1c1..ef31dae07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -382,14 +382,17 @@ endif() # Apple bundling if (APPLE) - set(MISC_FILES - ${APP_BUNDLE_DIR}/Contents/MacOS/openmw.cfg - ${APP_BUNDLE_DIR}/Contents/MacOS/plugins.cfg) + set(INSTALL_SUBDIR OpenMW) #install(FILES ${MISC_FILES} DESTINATION ../MacOS) #install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Plugins" DESTINATION ..) #install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Resources/resources" DESTINATION ../Resources) - install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION . COMPONENT Runtime) + install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) + install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) + install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) + + install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) + install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) set(CPACK_GENERATOR "DragNDrop") # set(CPACK_BUNDLE_PLIST "${CMAKE_SOURCE_DIR}/files/mac/Info.plist") # set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/files/mac/openmw.icns") @@ -399,7 +402,7 @@ if (APPLE) set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO}) set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE}) - set(APPS "\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_NAME}") + set(APPS "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}") set(PLUGINS "") # Scan Plugins dir for *.dylibs @@ -407,7 +410,7 @@ if (APPLE) foreach(PLUGIN ${ALL_PLUGINS}) get_filename_component(PLUGIN_FILENAME ${PLUGIN} NAME) - set(PLUGINS ${PLUGINS} "\${CMAKE_INSTALL_PREFIX}/${APP_BUNDLE_NAME}/Contents/Plugins/${PLUGIN_FILENAME}") + set(PLUGINS ${PLUGINS} "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}/Contents/Plugins/${PLUGIN_FILENAME}") endforeach() #For now, search unresolved dependencies only in default system paths, so if you put unresolveable (i.e. with @executable_path in id name) lib or framework somewhere else, it would fail diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 235bec6ab..e46a06205 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -41,8 +41,8 @@ source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC find_package(Qt4 REQUIRED) set(QT_USE_QTGUI 1) -find_package(PNG REQUIRED) -include_directories(${PNG_INCLUDE_DIR}) +#find_package(PNG REQUIRED) +#include_directories(${PNG_INCLUDE_DIR}) QT4_ADD_RESOURCES(RCC_SRCS resources.qrc) QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) @@ -71,7 +71,7 @@ target_link_libraries(omwlauncher ${Boost_LIBRARIES} ${OGRE_LIBRARIES} ${QT_LIBRARIES} - ${PNG_LIBRARY} +# ${PNG_LIBRARY} components )