diff --git a/COMPILE-linux.txt b/COMPILE-linux.txt index 0dba3bf66..56dad8fa1 100644 --- a/COMPILE-linux.txt +++ b/COMPILE-linux.txt @@ -37,11 +37,11 @@ Dependencies: Dependencies needed to build OpenMW: -OGRE 1.4.5 (3d engine) +OGRE 1.6.2 (3d engine) OIS-1.0.0 (input system) -MyGUI (GUI system for OGRE) -Bullet 2.72 (collision and physics library) -Monster 0.11 (scripting engine, included) +MyGUI 2.2.2 (GUI system for OGRE) +Bullet 2.74 (collision and physics library) +Monster 0.12 (scripting engine, included) OpenAL (3d sound system) libavcodec, libavformat (For MP3 playback) @@ -116,7 +116,7 @@ the libbulletdynamics.a etc if necessary.) Example: cd openmw/bullet -ln -s ~/software/bullet-2.72/src/BulletCollision/libbulletcollision.a . +ln -s ~/software/bullet-2.74/src/BulletCollision/libbulletcollision.a . Next, create a link to the "src" directory in openmw/include/bullet/ . @@ -124,7 +124,7 @@ Example: cd openmw mkdir -p include cd include -ln -s ~/software/bullet-2.72/src bullet +ln -s ~/software/bullet-2.74/src bullet Setting up MyGUI diff --git a/Makefile b/Makefile index 5c9e6d988..a680c0f59 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,8 @@ # Designed for GNU Make # Compiler settings -CXXFLAGS?= -g +CXXFLAGS?= -g -Iutil/ DMD=gdmd -version=Posix -#DMD=dmd -version=Posix # Some extra flags for niftool and bsatool NIFFLAGS=-debug=warnstd -debug=check -debug=statecheck -debug=strict -debug=verbose diff --git a/bsatool.d b/bsatool.d index 3769d3f0a..6f25b2fc3 100644 --- a/bsatool.d +++ b/bsatool.d @@ -87,7 +87,7 @@ int main(char[][] args) int help(char[] msg) { writefln("%s", msg); - writefln("Format: bsatool archive.bsa [-x filename] [-l] [-n]"); + writefln("Format: bsatool archive.bsa [-x filename] [-l] [-n] [-xa]"); writefln(" -x filename extract file"); writefln(" -xa extract everything"); writefln(" -l list all files"); diff --git a/bullet/cpp_bullet.cpp b/bullet/cpp_bullet.cpp index e347049b4..8192f7066 100644 --- a/bullet/cpp_bullet.cpp +++ b/bullet/cpp_bullet.cpp @@ -25,6 +25,8 @@ #include +#include "dbg.h" + using namespace std; class CustomOverlappingPairCallback; @@ -406,7 +408,7 @@ extern "C" void bullet_insertStatic(btConcaveShape *shape, // Are we scaled? if(scale != 1.0) { - cout << "Scaling shape " << shape << " by " << scale << endl; + //cout << "Scaling shape " << shape << " by " << scale << endl; // Not quite sure how to handle local scaling yet. Our initial // attempt was to create a wrapper that showed a scale mesh to @@ -454,6 +456,7 @@ extern "C" void bullet_insertStatic(btConcaveShape *shape, // 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); diff --git a/core/config.d b/core/config.d index 989beda85..7dd27b5fd 100644 --- a/core/config.d +++ b/core/config.d @@ -281,10 +281,7 @@ struct ConfigManager { char[] s = ini.getString("Game Files", format("GameFile[%d]",i), null); if(s != null && srch.has(s)) - { - writefln("Adding game file %s", s); - gameFiles ~= esmDir ~ s; - } + gameFiles ~= esmDir ~ s; } delete srch; diff --git a/input/events.d b/input/events.d index 856026aa8..15702f4c4 100644 --- a/input/events.d +++ b/input/events.d @@ -36,6 +36,7 @@ import scene.player; import bullet.bindings; import monster.monster; +import monster.vm.dbg; import ogre.bindings; @@ -242,6 +243,9 @@ extern(C) int d_frameStarted(float time, int guiMode) { if(doExit) return 0; + dbg.trace("d_frameStarted"); + scope(exit) dbg.untrace(); + // Run the Monster scheduler vm.frame(time); diff --git a/monster/options.d b/monster/options.d index 5f18932d5..f6d1485ab 100644 --- a/monster/options.d +++ b/monster/options.d @@ -37,8 +37,8 @@ module monster.options; the language, let us know! */ -const: static: +const: /********************************************************* @@ -97,7 +97,8 @@ int maxFStack = 100; // can run at once. Enabling this will prevent infinite loops. bool enableExecLimit = true; -// Maximum number of instructions to allow in once call to execute() (if +// Maximum number of instructions to allow in each call to execute() +// (if enableExecLimit is true) long execLimit = 10000000; @@ -109,17 +110,18 @@ long execLimit = 10000000; *********************************************************/ -// Enable tracing of external functions on the function stack. If -// true, you may use vm.trace() and vm.untrace() to add your own -// functions to the internal Monster function stack for debug purposes -// (the functions will show up in debug output.) If false, these -// functions will be empty and most likely optimized away completely -// by the D compiler (in release builds). -bool enableTrace = true; - - +// If true, set the log output to standard out. If false, logging is +// disabled by default and must be activated (through monster.vm.dbg) +// at runtime. +bool defaultLogToStdout = false; +// If true, all function stack operations (pushes and pops) are logged +// with dbg.log(), and all logged messages are indented according to +// the current fstack level. +bool logFStack = true; +// If true, log when threads are put into the background/forground. +bool logThreads = true; /********************************************************* diff --git a/monster/options.openmw b/monster/options.openmw index 5f18932d5..6098c4a4f 100644 --- a/monster/options.openmw +++ b/monster/options.openmw @@ -37,8 +37,8 @@ module monster.options; the language, let us know! */ -const: static: +const: /********************************************************* @@ -97,7 +97,8 @@ int maxFStack = 100; // can run at once. Enabling this will prevent infinite loops. bool enableExecLimit = true; -// Maximum number of instructions to allow in once call to execute() (if +// Maximum number of instructions to allow in each call to execute() +// (if enableExecLimit is true) long execLimit = 10000000; @@ -109,17 +110,14 @@ long execLimit = 10000000; *********************************************************/ -// Enable tracing of external functions on the function stack. If -// true, you may use vm.trace() and vm.untrace() to add your own -// functions to the internal Monster function stack for debug purposes -// (the functions will show up in debug output.) If false, these -// functions will be empty and most likely optimized away completely -// by the D compiler (in release builds). -bool enableTrace = true; - - - +// If true, set the log output to standard out. If false, logging is +// disabled by default and must be activated (through monster.vm.dbg) +// at runtime. +bool defaultLogToStdout = false; +// If true, all function stack operations (pushes and pops) are logged +// with dbg.log(). +bool logFStack = true; /********************************************************* diff --git a/monster/update.sh b/monster/update.sh index 0fb5a7d32..536863b55 100755 --- a/monster/update.sh +++ b/monster/update.sh @@ -10,4 +10,6 @@ done svn st -diff options.openmw options.d +diff options.openmw options.d || $EDITOR options.d +mv options.openmw options.openmw_last +cp options.d options.openmw diff --git a/monster/vm/dbg.d b/monster/vm/dbg.d new file mode 100644 index 000000000..6868a1718 --- /dev/null +++ b/monster/vm/dbg.d @@ -0,0 +1,155 @@ +/* + Monster - an advanced game scripting language + Copyright (C) 2007-2009 Nicolay Korslund + Email: + WWW: http://monster.snaptoad.com/ + + This file (dbg.d) is part of the Monster script language package. + + Monster 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 monster.vm.dbg; + +import monster.vm.thread; +import std.stream; +import std.string; +import std.cstream; +import monster.vm.fstack; +import monster.options; + +/* + This file is used for runtime debugging, stack tracing, etc. + */ + +/* + Create a trace for your function that automatically pops itself of + the fstack when it goes out of scope. Usage: + + auto scope _t = new MTrace("funcName"); + + This is one of the few places where C++ is actually easier to use... + + An alternative way to do the same thing: + + dbg.trace("funcName"); + scope(exit) dbg.untrace(); +*/ + +scope class MTrace +{ + this(char[] str) { dbg.trace(str); } + ~this() { dbg.untrace(); } +} + +Dbg dbg; + +struct Dbg +{ + Stream dbgOut = null; + + // Add indentation for each function stack level (only works if + // logFStack is true in options.d) + char[] logLevelString = "| "; + + // Called at startup + void init() + { + static if(defaultLogToStdout) + dbgOut = dout; + } + + void log(char[] msg) + { + if(dbgOut !is null) + { + int logLevel = getFStackLevel(); + int extLevel = getExtLevel(); + int trdIndex = getThreadIndex(); + + char[] str = format("(trd=%s,ext=%s,lev=%s)", + trdIndex, + extLevel, + logLevel); + str = format("%-24s", str); + dbgOut.writeString(str); + + // If we're logging function stack activity, put in some fancy + // indentation as well. + static if(logFStack) + { + for(int i;i= 0); - /* - if(cur.isFunc) writefln("popping function ", cur.func.name); - else if(cur.isState) writefln("popping state ", cur.state.name); - writefln(toString, "\n"); - */ + static if(logFStack) + { + dbg.log(" -- " ~ cur.toString()); + } // Remove the topmost node from the list, and set cur. assert(cur == list.getHead()); @@ -338,6 +347,11 @@ struct FunctionStack restoreFrame(); assert(list.length != 0 || cur is null); + + static if(logFStack) + { + dbg.log(""); + } } // Get a stack trace (pretty basic at the moment) diff --git a/monster/vm/init.d b/monster/vm/init.d index 8ef57ea07..e3e960908 100644 --- a/monster/vm/init.d +++ b/monster/vm/init.d @@ -32,6 +32,7 @@ import monster.vm.thread; import monster.vm.stack; import monster.vm.arrays; import monster.vm.vm; +import monster.vm.dbg; import monster.modules.all; import monster.options; @@ -121,6 +122,9 @@ void doMonsterInit() // Next, initialize the Monster library + // Initialize the debugger structure + dbg.init(); + // Initialize compiler constructs initTokenizer(); initProperties(); diff --git a/monster/vm/mclass.d b/monster/vm/mclass.d index 9d93f5d8f..93374be58 100644 --- a/monster/vm/mclass.d +++ b/monster/vm/mclass.d @@ -455,7 +455,8 @@ final class MonsterClass // Needed to make sure execute() exits when the constructor is // done. - vm.pushExt("callConst"); + if(cthread !is null) + cthread.fstack.pushExt("callConst"); // Call constructors foreach(c; tree) @@ -473,7 +474,8 @@ final class MonsterClass c.scptConst.fn.call(obj); } - vm.popExt(); + if(cthread !is null) + cthread.fstack.pop(); } // Get the whole allocated buffer belonging to this object diff --git a/monster/vm/thread.d b/monster/vm/thread.d index 6d72a0fb7..e0235ae02 100644 --- a/monster/vm/thread.d +++ b/monster/vm/thread.d @@ -42,6 +42,7 @@ import monster.vm.mclass; import monster.vm.mobject; import monster.vm.codestream; import monster.vm.stack; +import monster.vm.dbg; import monster.vm.idlefunction; import monster.vm.arrays; import monster.vm.iterators; @@ -139,6 +140,11 @@ struct Thread return cn; } + int getIndex() + { + return NodeList.getIndex(this)+1; + } + // Schedule the function to run the next frame. Can only be used on // paused threads. void restart() @@ -366,6 +372,10 @@ struct Thread // Clear out our stack values stack.reset(); + static if(logThreads) + dbg.log(format("------ deactivate thread=%s (stack=%s) ------", + getIndex, sstack.length)); + assert(!isRunning); } @@ -383,6 +393,10 @@ struct Thread stack.getPos() == 0, "only empty transient threads kan restore into a non-empty stack"); + static if(logThreads) + dbg.log(format("------ activate thread=%s (stack=%s) ------", + getIndex, sstack.length)); + if(sstack.length) { assert(stack.getPos() == 0, @@ -390,6 +404,8 @@ struct Thread assert(!isTransient, "cannot restore a transent thread with stack"); + + // Push the values back, and free the buffer stack.pushInts(sstack); Buffers.free(sstack); diff --git a/monster/vm/vm.d b/monster/vm/vm.d index c06fd53f1..92b453af0 100644 --- a/monster/vm/vm.d +++ b/monster/vm/vm.d @@ -28,7 +28,6 @@ import monster.vm.thread; import monster.vm.mclass; import monster.vm.mobject; import monster.vm.init; -import monster.vm.fstack; import monster.compiler.tokenizer; import monster.compiler.linespec; @@ -135,63 +134,6 @@ struct VM return load(ms, name); } - static if(enableTrace) - { - // Push the given string onto the function stack as an external - // function. - void tracef(...) - { - char[] s; - - void putc(dchar c) - { - std.utf.encode(s, c); - } - - std.format.doFormat(&putc, _arguments, _argptr); - trace(s); - } - - void trace(char[] name) { pushExt(name); } - void untrace() { popExt(); } - } - else - { - void tracef(...) {} - void trace(char[]) {} - void untrace() {} - } - - void pushExt(char[] name) - { - getFStack().pushExt(name); - } - - // Pop the last function pushed by pushExt() - void popExt() - { - auto fs = getFStack(); - assert(fs.cur !is null && fs.cur.isExternal, - "vm.untrace() used on a non-external function stack entry"); - fs.pop(); - } - - // Get the active function stack, or the externals stack if no - // thread is active. - FunctionStack *getFStack() - { - if(cthread !is null) - { - assert(!cthread.fstack.isEmpty); - return &cthread.fstack; - } - return &externals; - } - - // Return the current function stack printout - char[] getTrace() - { return getFStack().toString(); } - void addPath(char[] path) { init(); diff --git a/mscripts/gmst.mn b/mscripts/gmst.mn index 5a5f0defe..027262641 100644 --- a/mscripts/gmst.mn +++ b/mscripts/gmst.mn @@ -2086,19 +2086,3 @@ char[] sMagicCreature02ID; char[] sMagicCreature03ID; char[] sMagicCreature04ID; char[] sMagicCreature05ID; - -test() -{ - // Print out some random variables. If you want these not to get - // lost in a sea of output from OGRE, run openmw with the -n switch - // to disable rendering. - print(); - print("Some random GMST variables:"); - print("sThief:", sThief); - print("iAlchemyMod:", iAlchemyMod); - print("sBribe_100_Gold:", sBribe_100_Gold); - print("fMaxWalkSpeed:", fMaxWalkSpeed); - print("fWereWolfMagicka:", fWereWolfMagicka); - print("sEffectSummonFabricant:", sEffectSummonFabricant); - print(); -} diff --git a/mscripts/setup.d b/mscripts/setup.d index 13bcfb883..5ac07bb82 100644 --- a/mscripts/setup.d +++ b/mscripts/setup.d @@ -47,9 +47,6 @@ void initMonsterScripts() // Set up the GUI Monster module setupGUIScripts(); - - // Run the test script - vm.run("test.mn"); } // Run the GUI scripts. These should be run only after the @@ -62,3 +59,11 @@ void runGUIScripts() // Run the fps ticker vm.run("fpsticker.mn"); } + +// This should probably not be here: +import monster.vm.dbg; +import std.string; + +extern(C): +void dbg_trace(char*str) { dbg.trace(toString(str)); } +void dbg_untrace() { dbg.untrace(); } diff --git a/mscripts/test.mn b/mscripts/test.mn deleted file mode 100644 index 4b740fc43..000000000 --- a/mscripts/test.mn +++ /dev/null @@ -1,10 +0,0 @@ -// A short example script - -sleep(6); - -while(true) -{ - print("Howdy from the world of Monster scripts!"); - print("This script is located in mscripts/test.mn. Check it out!"); - sleep(60); -} diff --git a/nif/property.d b/nif/property.d index adbf1d4eb..9e605b619 100644 --- a/nif/property.d +++ b/nif/property.d @@ -26,6 +26,7 @@ import nif.record; abstract class Property : Named { + // The meaning of these depends on the actual property type. ushort flags; override: @@ -105,7 +106,7 @@ class NiTexturingProperty : Property } /* - * This just in: The textures in this list is as follows: + * The textures in this list is as follows: * * 0 - Base texture * 1 - Dark texture @@ -236,6 +237,46 @@ class NiShadeProperty : Property class NiAlphaProperty : Property { + /* + In NiAlphaProperty, the flags have the following meaning. + + Bit 0 : alpha blending enable + Bits 1-4 : source blend mode + Bits 5-8 : destination blend mode + Bit 9 : alpha test enable + Bit 10-12 : alpha test mode + Bit 13 : no sorter flag ( disables triangle sorting ) + + blend modes (glBlendFunc): + 0000 GL_ONE + 0001 GL_ZERO + 0010 GL_SRC_COLOR + 0011 GL_ONE_MINUS_SRC_COLOR + 0100 GL_DST_COLOR + 0101 GL_ONE_MINUS_DST_COLOR + 0110 GL_SRC_ALPHA + 0111 GL_ONE_MINUS_SRC_ALPHA + 1000 GL_DST_ALPHA + 1001 GL_ONE_MINUS_DST_ALPHA + 1010 GL_SRC_ALPHA_SATURATE + + test modes (glAlphaFunc): + 000 GL_ALWAYS + 001 GL_LESS + 010 GL_EQUAL + 011 GL_LEQUAL + 100 GL_GREATER + 101 GL_NOTEQUAL + 110 GL_GEQUAL + 111 GL_NEVER + + Taken from: + http://niftools.sourceforge.net/doc/nif/NiAlphaProperty.html + */ + + // Tested against when certain flags are set (see above.) + ubyte threshold; + override: void read() { diff --git a/ogre/bindings.d b/ogre/bindings.d index 49121b2c0..fab1fb25a 100644 --- a/ogre/bindings.d +++ b/ogre/bindings.d @@ -50,8 +50,8 @@ extern(C): // Do engine configuration. Returns 0 if we should continue, 1 if // not. int ogre_configure(int showConfig, // Do we show the config dialogue? - char *plugincfg // Name of 'plugin.cfg' file - ); + char *plugincfg,// Name of 'plugin.cfg' file + int debutOut); // Enable or disable debug output // Sets up the window void ogre_initWindow(); @@ -116,14 +116,16 @@ NodePtr ogre_attachLight(char* name, NodePtr parent, float radius); // Create the specified material -void ogre_createMaterial(char *name, // Name to give resource - float *ambient, // Ambient RBG value +void ogre_createMaterial(char *name, // Name to give resource + float *ambient, // Ambient RBG value float *diffuse, float *specular, - float *emissive,// Self illumination + float *emissive, // Self illumination float glossiness,// Same as shininess? - float alpha, // Use this in all alpha values? - char *texture); // Texture name + float alpha, // Reflection alpha? + char *texture, // Texture name + int alphaFlags, // Alpha settings (see + ubyte alphaTest);// NiAlphaProperty in nif/) // Creates a mesh and gives it a bounding box. Also creates an entity // and attached it to the given SceneNode 'owner'. @@ -165,7 +167,7 @@ void ogre_moveCameraRel(float x, float y, float z); // GUI functions. Under development. typedef void* WidgetPtr; -void gui_setupGUI(); +void gui_setupGUI(int debugOut); void gui_toggleGui(); void gui_setCellName(char *str); diff --git a/ogre/cpp_interface.cpp b/ogre/cpp_interface.cpp index f173eb724..04ba18d68 100644 --- a/ogre/cpp_interface.cpp +++ b/ogre/cpp_interface.cpp @@ -43,10 +43,21 @@ extern "C" void ogre_cleanup() extern "C" int32_t ogre_configure( int32_t showConfig, // Do we show the config dialogue? - char *plugincfg // Name of 'plugin.cfg' file - ) + char *plugincfg, // Name of 'plugin.cfg' file + int32_t debugOut) // Enable or disable logging { - mRoot = new Root(plugincfg); + // Set up logging first + new LogManager; + Log *log = LogManager::getSingleton().createLog("default"); + + if(debugOut) + // Full log detail + log->setLogDetail(LL_BOREME); + else + // Disable logging + log->setDebugOutputEnabled(false); + + mRoot = new Root(plugincfg, "ogre.cfg", ""); // Add the BSA archive manager before reading the config file. ArchiveManager::getSingleton().addArchiveFactory( &mBSAFactory ); @@ -95,7 +106,7 @@ extern "C" int32_t ogre_configure( // Initialize window. This will create and show the actual window. extern "C" void ogre_initWindow() { - std::cout << "ogre_initWindow()\n"; + TRACE("ogre_initWindow"); // Initialize OGRE. mWindow = mRoot->initialise(true, "OpenMW", ""); @@ -155,8 +166,6 @@ extern "C" void ogre_initWindow() // Register the input listener mKeyboard -> setEventCallback( &mInput ); mMouse -> setEventCallback( &mInput ); - - std::cout << "ogre_initWindow finished\n"; } // Make a scene @@ -619,7 +628,10 @@ extern "C" void ogre_createMaterial(char *name, // Name to give float alpha, // Use this in all // alpha values? - char* texture) // Texture + char* texture, // Texture + + int32_t alphaFlags, + uint8_t alphaTest) // Alpha settings { MaterialPtr material = MaterialManager::getSingleton().create( name, @@ -630,7 +642,30 @@ extern "C" void ogre_createMaterial(char *name, // Name to give // directory), it will automatically be loaded when needed. If // not, we should already have inserted a manual loader for the texture. if(texture) - material->getTechnique(0)->getPass(0)->createTextureUnitState(texture); + { + Pass *pass = material->getTechnique(0)->getPass(0); + TextureUnitState *txt = pass->createTextureUnitState(texture); + + // Add transparencly. + + if(alphaFlags != -1) + { + // The 237 alpha flags are by far the most common. Check + // NiAlphaProperty in nif/properties.d if you need to + // decode other values. 237 basically means normal + // transparencly. + if(alphaFlags == 237) + { + // Enable transparency + pass->setSceneBlending(SBT_TRANSPARENT_ALPHA); + + //pass->setDepthCheckEnabled(false); + pass->setDepthWriteEnabled(false); + } + else + std::cout << "UNHANDLED ALPHA FOR " << texture << ": " << alphaFlags << "\n"; + } + } // Set bells and whistles material->setAmbient(ambient[0], ambient[1], ambient[2]); @@ -638,12 +673,6 @@ extern "C" void ogre_createMaterial(char *name, // Name to give material->setSpecular(specular[0], specular[1], specular[2], alpha); material->setSelfIllumination(emissive[0], emissive[1], emissive[2]); material->setShininess(glossiness); - - // Enable transparancy? This is just guesswork. Perhaps we - // should use NiAlphaProperty or something instead. This looks - // like crap so it's not enabled right now. - - //material->setSceneBlending(SBT_TRANSPARENT_ALPHA); } extern "C" SceneNode *ogre_getDetachedNode() diff --git a/ogre/cpp_mygui.cpp b/ogre/cpp_mygui.cpp index a0b1e9c8f..55ec17bd6 100644 --- a/ogre/cpp_mygui.cpp +++ b/ogre/cpp_mygui.cpp @@ -30,7 +30,11 @@ extern "C" void gui_setNeedMouseFocus(MyGUI::WidgetPtr p, int32_t b) { p->setNeedMouseFocus(b); } extern "C" void gui_setTextColor(MyGUI::WidgetPtr p, float r,float g,float b) -{ p->setTextColour(Ogre::ColourValue(b,g,r)); } +{ + MyGUI::StaticText *st = dynamic_cast(p); + if(st != NULL) + st->setTextColour(Ogre::ColourValue(b,g,r)); +} extern "C" void gui_setCoord(MyGUI::WidgetPtr p, int32_t x,int32_t y,int32_t w,int32_t h) @@ -177,7 +181,7 @@ public: { MyGUI::WidgetPtr pt; getWidget(pt, name); - pt->setTextColour(Ogre::ColourValue(b,g,r)); + gui_setTextColor(pt,r,g,b); } void setImage(const char* name, const char* imgName) @@ -278,7 +282,6 @@ public: setCoord(500,0,320,300); mMainWidget->setCaption(cellName); setText("WorldButton", "World"); - setColor("WorldButton", 0.75, 0.6, 0.35); setImage("Compass", "compass.dds"); } }; @@ -399,11 +402,15 @@ void turnGuiOff(MyGUI::WidgetPtr sender) gui_toggleGui(); } -extern "C" void gui_setupGUI() +extern "C" void gui_setupGUI(int32_t debugOut) { ResourceGroupManager::getSingleton(). addResourceLocation("media_mygui", "FileSystem", "General"); + // Enable/disable logging to stdout + MyGUI::LogManager::initialise(); + MyGUI::LogManager::setSTDOutputEnabled(debugOut); + mGUI = new MyGUI::Gui(); mGUI->initialise(mWindow); diff --git a/ogre/cpp_ogre.cpp b/ogre/cpp_ogre.cpp index 40d911312..54abe1942 100644 --- a/ogre/cpp_ogre.cpp +++ b/ogre/cpp_ogre.cpp @@ -35,6 +35,8 @@ #include +#include "dbg.h" + using namespace Ogre; RenderWindow* mWindow; diff --git a/ogre/meshloader.d b/ogre/meshloader.d index 740cf2392..9ab521398 100644 --- a/ogre/meshloader.d +++ b/ogre/meshloader.d @@ -66,8 +66,6 @@ struct MeshLoader { baseName = name; - writefln("Loading mesh '%s'", name); - // Check if the first record is a node Node n = cast(Node) nifMesh.records[0]; @@ -194,7 +192,7 @@ struct MeshLoader //writefln("Found path controller"); assert(cont.target is data); } - else writefln("Other controller (%s)", cont); + //else writefln("Other controller (%s)", cont); cont = cont.next; } @@ -210,6 +208,10 @@ struct MeshLoader 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 @@ -260,6 +262,16 @@ struct MeshLoader } } + // NiAlphaProperty + { + NiAlphaProperty a = cast(NiAlphaProperty) p; + if(a !is null) + { + alphaFlags = a.flags; + alphaTest = a.threshold; + } + } + // NiMaterialProperty block { NiMaterialProperty tmp = cast(NiMaterialProperty) p; @@ -270,11 +282,8 @@ struct MeshLoader material = newName; continue; } - //writefln("Unknown property found: ", p); } } - //if(!texture.length) writefln("No texture found"); - // Get a pointer to the texture name char* texturePtr; if(texture.length) texturePtr = toStringz(texture); @@ -282,9 +291,12 @@ struct MeshLoader // Create the material if(material.length) - 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); + // 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. @@ -294,8 +306,8 @@ struct MeshLoader zero[] = 0.0; one[] = 1.0; - ogre_createMaterial(newName.ptr, one.ptr, one.ptr, zero.ptr, zero.ptr, 0.0, 1.0, - texturePtr); + ogre_createMaterial(newName.ptr, one.ptr, one.ptr, zero.ptr, zero.ptr, + 0.0, 1.0, texturePtr, alphaFlags, alphaTest); } nomaterial: diff --git a/ogre/ogre.d b/ogre/ogre.d index 4df7383d8..d07d5e342 100644 --- a/ogre/ogre.d +++ b/ogre/ogre.d @@ -94,7 +94,7 @@ static ~this() } // Loads ogre configurations, creats the root, etc. -void setupOgre() +void setupOgre(bool debugOut) { char[] plugincfg; @@ -108,7 +108,7 @@ void setupOgre() // Later we will send more config info from core.config along with // this function - if(ogre_configure(config.finalOgreConfig, toStringz(plugincfg))) + if(ogre_configure(config.finalOgreConfig, toStringz(plugincfg), debugOut)) OgreException("Configuration abort"); ogre_initWindow(); @@ -119,7 +119,7 @@ void setupOgre() ogre_makeScene(); // Load the GUI system - gui_setupGUI(); + gui_setupGUI(debugOut); // Run the GUI scripts runGUIScripts(); @@ -148,8 +148,8 @@ void startRendering() ogre_startRendering(); } -// Cleans up after OGRE. Resets things like screen resolution and -// mouse control. +// Cleans up after OGRE. Resets things like screen resolution, mouse +// control and keyboard repeat rate. void cleanupOgre() { if(ogreSetup) diff --git a/openmw.d b/openmw.d index a34976092..c8eadfc54 100644 --- a/openmw.d +++ b/openmw.d @@ -43,6 +43,7 @@ import core.config; import monster.util.string; import monster.vm.mclass; +import monster.vm.dbg; import mscripts.setup; import sound.audio; @@ -69,6 +70,7 @@ void main(char[][] args) bool resetKeys = false; bool showOgreFlag = false; bool noSound = false; + bool debugOut = false; // Some examples to try: // @@ -99,6 +101,14 @@ void main(char[][] args) else if(a == "-rk") resetKeys = true; else if(a == "-oc") showOgreFlag = true; else if(a == "-ns") noSound = true; + else if(a == "-debug") + { + // Enable Monster debug output + dbg.dbgOut = dout; + + // Tell OGRE to do the same later on + debugOut = true; + } else cells ~= a; if(cells.length + eCells.length/2 > 1 ) @@ -116,6 +126,7 @@ void main(char[][] args) 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(" -h Show this help"); writefln(""); writefln("Specifying more than one cell implies -n"); @@ -205,7 +216,7 @@ Try specifying another cell name on the command line, or edit openmw.ini."); // Get a cell data holder and load an interior cell cd = cellList.get(); - writefln("Will load %s,%s", x, y); + if(debugOut) writefln("Will load %s,%s", x, y); try cd.loadExtCell(x,y); catch(Exception e) { @@ -219,11 +230,12 @@ Try specifying another cell name on the command line, or edit openmw.ini."); NodePtr putObject(MeshIndex m, Placement *pos, float scale, bool collide=false) { - if(m == null) + if(m is null) writefln("WARNING: CANNOT PUT NULL OBJECT"); - else if(m.isEmpty) - writefln("WARNING: CANNOT INSERT EMPTY MESH '%s'", m.getName); - else return placeObject(m, pos, scale, collide); + else if(!m.isEmpty) + return placeObject(m, pos, scale, collide); + + //writefln("WARNING: CANNOT INSERT EMPTY MESH '%s'", m.getName); return null; } @@ -234,7 +246,7 @@ Try specifying another cell name on the command line, or edit openmw.ini."); if(render) { // Warm up OGRE - setupOgre(); + setupOgre(debugOut); scope(exit) cleanupOgre(); // Set up Bullet @@ -278,7 +290,6 @@ Try specifying another cell name on the command line, or edit openmw.ini."); Sound *s = ls.m.sound; if(s) { - writefln("Dynamic light %s has sound %s", ls.m.id, s.id); ls.loopSound = soundScene.insert(s, true); if(ls.loopSound) { @@ -300,7 +311,6 @@ Try specifying another cell name on the command line, or edit openmw.ini."); Sound *s = ls.m.sound; if(s) { - writefln("Static light %s has sound %s", ls.m.id, s.id); ls.loopSound = soundScene.insert(s, true); if(ls.loopSound) { @@ -369,7 +379,7 @@ Try specifying another cell name on the command line, or edit openmw.ini."); // Run it until the user tells us to quit startRendering(); } - else debug(verbose) writefln("Skipping rendering"); + else if(debugOut) writefln("Skipping rendering"); if(!noSound) { @@ -377,7 +387,7 @@ Try specifying another cell name on the command line, or edit openmw.ini."); shutdownSound(); } - debug(verbose) + if(debugOut) { writefln(); writefln("%d statics", cd.statics.length); @@ -421,7 +431,10 @@ Try specifying another cell name on the command line, or edit openmw.ini."); cellList.release(cd); // Write some statistics - poolSize(); - writefln(esmRegion); - writefln("Total objects: ", MonsterClass.getTotalObjects); + if(debugOut) + { + poolSize(); + writefln(esmRegion); + writefln("Total objects: ", MonsterClass.getTotalObjects); + } } diff --git a/scene/gamesettings.d b/scene/gamesettings.d index 755271df1..a07133fe3 100644 --- a/scene/gamesettings.d +++ b/scene/gamesettings.d @@ -44,7 +44,4 @@ void loadGameSettings() // UTF32 at load time, so string8 will not be needed here. else if(b.type == VarType.String) gmstObj.setString8(name, b.str); } - - // Call the test function - gmstObj.call("test"); } diff --git a/util/dbg.h b/util/dbg.h new file mode 100644 index 000000000..4498cd32f --- /dev/null +++ b/util/dbg.h @@ -0,0 +1,16 @@ +#include + +extern "C" void dbg_trace(const char *); +extern "C" void dbg_untrace(); + +class MTrace +{ + public: + MTrace(const char* str) + { dbg_trace(str); } + + ~MTrace() + { dbg_untrace(); } +}; + +#define TRACE(x) MTrace _trc(x);