diff --git a/Makefile b/Makefile index a680c0f59..ff334be1e 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ bullet_cpp_files=$(bullet_cpp:%=bullet/cpp_%.cpp) # All object files needed by openmw and esmtool src := $(wildcard bsa/*.d) $(wildcard bullet/*.d) $(wildcard core/*.d) \ $(wildcard esm/*.d) $(wildcard input/*.d) $(wildcard nif/*.d) $(wildcard ogre/*.d) \ -$(wildcard scene/*.d) $(wildcard sound/*.d) $(wildcard util/*.d) +$(wildcard scene/*.d) $(wildcard sound/*.d) $(wildcard util/*.d) $(wildcard gui/*.d) src := $(src) $(wildcard mscripts/*.d) src := $(src) monster/monster.d \ $(wildcard monster/vm/*.d) \ diff --git a/bullet/bindings.d b/bullet/bindings.d index af0c59151..9dbd76197 100644 --- a/bullet/bindings.d +++ b/bullet/bindings.d @@ -35,8 +35,11 @@ extern(C): // Initialize the dynamic world. Returns non-zero if an error occurs. int bullet_init(); -// Switch to the next physics mode +// 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); diff --git a/bullet/cpp_bullet.cpp b/bullet/cpp_bullet.cpp index 8192f7066..d61aa6baa 100644 --- a/bullet/cpp_bullet.cpp +++ b/bullet/cpp_bullet.cpp @@ -206,29 +206,45 @@ extern "C" int32_t bullet_init() 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() { - g_physMode++; - if(g_physMode > PHYS_GHOST) - g_physMode = PHYS_WALK; - switch(g_physMode) { case PHYS_WALK: - cout << "Entering walking mode\n"; + bullet_fly(); break; case PHYS_FLY: - cout << "Entering flying mode\n"; + bullet_ghost(); break; case PHYS_GHOST: - cout << "Entering ghost mode\n"; + bullet_walk(); break; } } // Warp the player to a specific location. We do not bother setting -// rotation, since it's completely irrelevant for collision detection. +// 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; diff --git a/esm/loadnpc.d b/esm/loadnpc.d index 3965543fb..c18251d0a 100644 --- a/esm/loadnpc.d +++ b/esm/loadnpc.d @@ -164,7 +164,7 @@ struct NPC skipRecord(); - makeProto("Person"); + makeProto(); // Clean this up a little later, eg. no point in storing the // structs outside the function any longer. Same goes for most of diff --git a/gui/bindings.d b/gui/bindings.d new file mode 100644 index 000000000..7825e575f --- /dev/null +++ b/gui/bindings.d @@ -0,0 +1,53 @@ +/* + 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 gui.bindings; + +extern(C): + +// GUI functions. Under development. The corresponding C++ functions +// are in ogre/cpp_mygui.cpp + +typedef void* WidgetPtr; +void gui_setupGUI(int debugOut); +void gui_toggleGui(); +void gui_setCellName(char *str); + +// Get the widget type, as a string +char *gui_widgetType(WidgetPtr); + +// Get the height or width of a widget. If the argument is null, +// return the size of the screen. +int gui_getHeight(WidgetPtr); +int gui_getWidth(WidgetPtr); + +// Set various properties of a given widget +void gui_setCaption(WidgetPtr, char*); +void gui_setNeedMouseFocus(WidgetPtr, int); +void gui_setTextColor(WidgetPtr, float,float,float); +void gui_setCoord(WidgetPtr, int,int,int,int); + +// Various ways to get or create widgets +WidgetPtr gui_loadLayout(char *file, char *prefix, WidgetPtr parent); +WidgetPtr gui_getChild(WidgetPtr, char*); +WidgetPtr gui_createText(char *skin, int x, int y, int w, int h, char *layer); diff --git a/ogre/gui.d b/gui/gui.d similarity index 94% rename from ogre/gui.d rename to gui/gui.d index 08a62998f..451f49751 100644 --- a/ogre/gui.d +++ b/gui/gui.d @@ -21,11 +21,11 @@ */ -module ogre.gui; +module gui.gui; import monster.monster; import monster.vm.mclass; -import ogre.bindings; +import gui.bindings; import std.string; // Widget class and gui module @@ -57,7 +57,7 @@ class MWidget isLayout = true; prefix = format("%s", cast(void*)this); - widget = gui_loadLayout(layout.ptr, prefix.ptr, parent); + widget = gui_loadLayout(layout.toStringz(), prefix.toStringz(), parent); if(widget is null) fail("Layout " ~ layout ~ " is empty"); @@ -91,7 +91,7 @@ class MWidget name = prefix ~ name; // Get the child widget - auto pt = gui_getChild(widget, name.ptr); + auto pt = gui_getChild(widget, name.toStringz()); if(pt is null) fail("Widget has no child named " ~ name); @@ -163,7 +163,7 @@ void setCaption() foreach(AIndex ind; args) res ~= format("%s", arrays.getRef(ind).carr); - gui_setCaption(getOwner(), res.ptr); + gui_setCaption(getOwner(), toStringz(res)); } void setNeedMouseFocus() { gui_setNeedMouseFocus(getOwner(), stack.popBool); } @@ -211,9 +211,9 @@ void text() int y = stack.popInt(); int x = stack.popInt(); char[] skin = stack.popString8(); - WidgetPtr ptr = gui_createText(skin.ptr, + WidgetPtr ptr = gui_createText(skin.toStringz(), x,y,w,h, - layer.ptr); + layer.toStringz()); assert(widgetType(ptr) == "StaticText"); MWidget mw = new MWidget(ptr); stack.pushObject(mw.mo); diff --git a/input/events.d b/input/events.d index 15702f4c4..f1e234f22 100644 --- a/input/events.d +++ b/input/events.d @@ -213,7 +213,7 @@ void initializeInput() { // Move the player into place. TODO: This isn't really input-related // at all, and should be moved. - with(playerData.position) + with(*playerData.position) { ogre_moveCamera(position[0], position[1], position[2]); ogre_setCameraRotation(rotation[0], rotation[1], rotation[2]); @@ -305,6 +305,11 @@ extern(C) int d_frameStarted(float time, int guiMode) 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; + // Tell the sound scene that the player has moved sndCumTime += time; if(sndCumTime > sndRefresh) diff --git a/monster/compiler/expression.d b/monster/compiler/expression.d index 0de5fb072..1a36f3154 100644 --- a/monster/compiler/expression.d +++ b/monster/compiler/expression.d @@ -1180,12 +1180,26 @@ class ExprStatement : Statement // Require a terminating semicolon or line break bool term = true; + // True if 'left' was set in the constructor + bool leftSet = false; + + this(Expression lft=null) + { + left = lft; + if(left !is null) + leftSet = true; + } + void parse(ref TokenArray toks) { - if(toks.length == 0) - fail("Expected statement, found end of stream."); - loc = toks[0].loc; - left = Expression.identify(toks); + if(left is null) + { + if(toks.length == 0) + fail("Expected statement, found end of stream."); + left = Expression.identify(toks); + } + + loc = left.loc; Token tok; @@ -1219,7 +1233,8 @@ class ExprStatement : Statement void resolve(Scope sc) { - left.resolve(sc); + if(!leftSet) + left.resolve(sc); loc = left.loc; type = left.type; diff --git a/monster/compiler/functions.d b/monster/compiler/functions.d index c22e6bf74..944fca215 100644 --- a/monster/compiler/functions.d +++ b/monster/compiler/functions.d @@ -989,26 +989,66 @@ class FunctionCallExpr : Expression fail("Parameter list expected ')'", toks); } - - this(Expression func, ref TokenArray toks) + // Special version of getParams that allow 'console-mode' grammar. + static void getParamsConsole(ref TokenArray toks, + out ExprArray parms, + out NamedParam[] named) + { + parms = null; + named = null; + + // The param list is terminated by a semicolon or a newline + while(!isSep(toks)) + { + if(toks.length == 0) + fail("Unexpected end of stream"); + + // Named paramter? + if(toks.length >= 3 && toks[1].type == TT.Equals) + { + NamedParam np; + + reqNext(toks, TT.Identifier, np.name); + reqNext(toks, TT.Equals); + np.value = Expression.identify(toks); + + named ~= np; + } + else + { + // Normal parameter + if(named.length) + fail("Cannot use non-named parameters after a named one", + toks[0].loc); + + parms ~= Expression.identify(toks); + } + + // Allow optional commas between parameters + isNext(toks, TT.Comma); + } + } + + this(Expression func, ref TokenArray toks, bool console=false) { assert(func !is null); fname = func; loc = fname.loc; - // Parse the parameter list - getParams(toks, params, named); + // Parse the parameter list. The 'console' parameter determines + // whether we're using normal grammar rules: + // func(param1,param2) + // or console rules + // func param1 param2 + if(console) + getParamsConsole(toks, params, named); + else + getParams(toks, params, named); } /* Might be used for D-like implicit function calling, eg. someFunc; or (obj.prop) this(Expression func) {} - - We might also allow a special free-form function call syntax, eg. - func 1 2 3 - - where parens and commas are optional, and the list is terminated by - isSep (newline or ;). This is useful mostly for console mode. */ void parse(ref TokenArray toks) { assert(0); } @@ -1176,7 +1216,7 @@ class FunctionCallExpr : Expression } // Evaluate the parameters - void evalParams() + private void evalParams() { // Again, let's handle the vararg case separately if(isVararg) @@ -1253,9 +1293,10 @@ class FunctionCallExpr : Expression { if(isCast) { + // This is a type cast, not a function call. + // Just evaluate the expression. CastExpression takes care // of everything automatically. - assert(params.length == 1); assert(params[0] !is null); params[0].eval(); diff --git a/monster/compiler/operators.d b/monster/compiler/operators.d index 96db25762..45096e121 100644 --- a/monster/compiler/operators.d +++ b/monster/compiler/operators.d @@ -534,8 +534,8 @@ class DotOperator : OperatorExpr type = member.type; // Make sure we only call static members when the owner is a - // type. - if(ot.isMeta && !member.isStatic) + // type or a package. + if((ot.isMeta || ot.isPackage) && !member.isStatic) fail("Can only access static members for " ~ owner.toString, loc); } diff --git a/monster/compiler/types.d b/monster/compiler/types.d index 5316899f3..b45c642a4 100644 --- a/monster/compiler/types.d +++ b/monster/compiler/types.d @@ -1702,11 +1702,21 @@ class TypeofType : ReplacerType // D. class GenericType : InternalType { + static GenericType sing; + this() { name = "var"; } static bool canParse(TokenArray toks) { return isNext(toks, TT.Var); } + static GenericType getSingleton() + { + if(sing is null) + sing = new GenericType; + + return sing; + } + override: bool isVar() { return true; } diff --git a/monster/compiler/variables.d b/monster/compiler/variables.d index 623209ec0..f4df1dffc 100644 --- a/monster/compiler/variables.d +++ b/monster/compiler/variables.d @@ -576,6 +576,7 @@ class MemberExpr : Expression isNext(toks, TT.Singleton) || isNext(toks, TT.State) || isNext(toks, TT.Clone) || + isNext(toks, TT.Var) || isNext(toks, TT.Const); } @@ -803,6 +804,13 @@ class MemberExpr : Expression if(name.type == TT.Const || name.type == TT.Clone) fail("Cannot use " ~ name.str ~ " as a variable", name.loc); + if(name.type == TT.Var) + { + type = GenericType.getSingleton(); + vtype = VType.Special; + return; + } + // Look ourselves up in the local scope, and include imported // scopes. look = sc.lookupImport(name); @@ -851,6 +859,9 @@ class MemberExpr : Expression void evalAsm() { + if(type.isVar) + fail("Cannot use 'var' as an expression", loc); + // Hairy. But does the trick for now. if(dotImport !is null && recurse) { @@ -1011,6 +1022,7 @@ class VarDeclStatement : Statement { VarDeclaration[] vars; bool reqSemi; + Type preKnownType = null; // Pass 'true' to the constructor to require a semi-colon (used eg // in for loops) @@ -1019,6 +1031,12 @@ class VarDeclStatement : Statement reqSemi = rs; } + // Used from the console, when the type is already known + this(Type type) + { + preKnownType = type; + } + static bool canParse(TokenArray toks) { if(Type.canParseRem(toks) && @@ -1030,7 +1048,12 @@ class VarDeclStatement : Statement void parse(ref TokenArray toks) { VarDeclaration varDec; - varDec = new VarDeclaration; + + if(preKnownType !is null) + varDec = new VarDeclaration(preKnownType); + else + varDec = new VarDeclaration; + varDec.parse(toks); vars ~= varDec; loc = varDec.var.name.loc; diff --git a/monster/modules/console.d b/monster/modules/console.d index a2f79fcfd..00a5f4540 100644 --- a/monster/modules/console.d +++ b/monster/modules/console.d @@ -134,19 +134,16 @@ class Console void putln(char[] str) { put(str, true); } - Statement[] parse(TokenArray toks) + Statement[] parse(TokenArray toks, Scope sc) { - Statement b = null; + Statement b; Statement[] res; repeat: - if(VarDeclStatement.canParse(toks)) - { - if(!allowVar) fail("Variable declaration not allowed here"); - b = new VarDeclStatement; - } - else if(CodeBlock.canParse(toks)) b = new CodeBlock; + b = null; + + if(CodeBlock.canParse(toks)) b = new CodeBlock; else if(IfStatement.canParse(toks)) b = new IfStatement; else if(DoWhileStatement.canParse(toks)) b = new DoWhileStatement; else if(WhileStatement.canParse(toks)) b = new WhileStatement; @@ -154,11 +151,24 @@ class Console else if(ForeachStatement.canParse(toks)) b = new ForeachStatement; else if(ImportStatement.canParse(toks)) b = new ImportStatement(true); - // If this is not one of the above, default to an expression - // statement. - else b = new ExprStatement; + if(b !is null) + { + // Parse and resolve + b.parse(toks); + b.resolve(sc); + } + else + { + // If this is not one of the above, default to a console + // statement. + auto es = new ConsoleStatement; + b = es; - b.parse(toks); + // Parse and resolve in one operation. + es.parseResolve(toks, sc, allowVar); + } + + assert(b !is null); res ~= b; // Are there more tokens waiting for us? @@ -269,51 +279,58 @@ class Console if(tokArr.length == 0) return CR.Empty; - // Phase II, parse + // Phase II & III, parse and resolve TokenArray toks = tokArr.arrayCopy(); - Statement[] sts = parse(toks); + Statement[] sts = parse(toks, sc); delete toks; assert(sts.length >= 1); // First, background the current thread (if any) and bring up - // our own. + // our own. This is necessary in order to keep the stack + // variables we make. store = cthread; if(store !is null) store.background(); assert(trd !is null); trd.foreground(); - // We have to push ourselves on the function stack, or call() - // will see that it's empty and kill the thread upon exit + // We have to push ourselves on the function stack, or + // Function.call() will see that it's empty and kill the thread + // upon exit trd.fstack.pushExt("Console"); // The rest must be performed separately for each statement on // the line. foreach(st; sts) { - // Phase III, resolve - st.resolve(sc); - // Phase IV, compile tasm.newFunc(); - // Is it an expression? - auto es = cast(ExprStatement)st; - if(es !is null) + ExprStatement es; + + // Is it an special console statement? + auto cs = cast(ConsoleStatement)st; + if(cs !is null) { - // Yes. But is the type usable? - if(es.left.type.canCastTo(ArrayType.getString()) - && es.right is null) + // Yes. Is the client an expression? + es = cast(ExprStatement)cs.client; + if(es !is null) { - // Yup. Get the type, and cast the expression to string. - scope auto ce = new - CastExpression(es.left, ArrayType.getString()); - ce.eval(); + // Ok. But is the type usable? + if(es.left.type.canCastTo(ArrayType.getString()) + && es.right is null) + { + // Yup. Get the type, and cast the expression to string. + scope auto ce = new + CastExpression(es.left, ArrayType.getString()); + ce.eval(); + } + else es = null; } - else es = null; } // No expression is being used, so compile the statement + // normally. if(es is null) st.compile(); @@ -336,28 +353,31 @@ class Console // function frame, ie. the same way we treat function // parameters. We do this by giving the variables negative // indices. - auto vs = cast(VarDeclStatement)st; - if(vs !is null) + if(cs !is null) { - // Add the new vars to the list - foreach(v; vs.vars) + auto vs = cast(VarDeclStatement)cs.client; + if(vs !is null) { - varList ~= v.var; + // Add the new vars to the list + foreach(v; vs.vars) + { + varList ~= v.var; - // Add the size as well - varSize += v.var.type.getSize; + // Add the size as well + varSize += v.var.type.getSize; + } + + // Recalculate all the indices backwards from zero + int place = 0; + foreach_reverse(v; varList) + { + place -= v.type.getSize; + v.number = place; + } + + // Reset the scope stack counters + sc.reset(); } - - // Recalculate all the indices backwards from zero - int place = 0; - foreach_reverse(v; varList) - { - place -= v.type.getSize; - v.number = place; - } - - // Reset the scope stack counters - sc.reset(); } } @@ -443,3 +463,71 @@ class Console } } } + +// Statement that handles variable declarations, function calls and +// expression statements in consoles. Since these are gramatically +// similar, we need the type to determine which +class ConsoleStatement : Statement +{ + // Used for variables and expression statements + Statement client; + + // Used for function calls + FunctionCallExpr func; + + void parseResolve(ref TokenArray toks, Scope sc, bool allowVar) + { + assert(toks.length != 0); + + // Get the first expression + auto first = Expression.identify(toks); + + // And the type right away + first.resolve(sc); + auto type = first.type; + assert(type !is null); + + // Type? If so, it's a variable declaration + if((type.isMeta || type.isVar) && allowVar) + { + if(type.isMeta) type = type.getBase(); + + client = new VarDeclStatement(type); + } + + // Function? + else if(type.isFunc) + func = new FunctionCallExpr(first, toks, true); + + // It's an expression statement + else + client = new ExprStatement(first); + + if(client !is null) + { + client.parse(toks); + client.resolve(sc); + } + else + { + assert(func !is null); + func.resolve(sc); + } + } + + override: + void parse(ref TokenArray) { assert(0); } + void resolve(Scope sc) { assert(0); } + + void compile() + { + if(client !is null) + { + client.compile(); + return; + } + + assert(func !is null); + func.evalPop(); + } +} diff --git a/monster/options.openmw b/monster/options.openmw index 6098c4a4f..f6d1485ab 100644 --- a/monster/options.openmw +++ b/monster/options.openmw @@ -116,9 +116,13 @@ long execLimit = 10000000; bool defaultLogToStdout = false; // If true, all function stack operations (pushes and pops) are logged -// with dbg.log(). +// 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/vm/thread.d b/monster/vm/thread.d index e0235ae02..1ce57dd2e 100644 --- a/monster/vm/thread.d +++ b/monster/vm/thread.d @@ -167,6 +167,9 @@ struct Thread list.remove(this); list = null; assert(isDead); + + static if(logThreads) + dbg.log(format("------ killing thread=%s ------", getIndex)); } // Stop the execution of a thread and cancel any scheduling. diff --git a/mscripts/console.mn b/mscripts/console.mn new file mode 100644 index 000000000..35e9888cb --- /dev/null +++ b/mscripts/console.mn @@ -0,0 +1,31 @@ +/* + OpenMW - The completely unofficial reimplementation of Morrowind + Copyright (C) 2008 Nicolay Korslund + Email: < korslund@gmail.com > + WWW: http://openmw.snaptoad.com/ + + This file (console.mn) 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/ . + + */ + +class Console + + +// This class contains all the functions available to the ingame +// console. + +import io; +import game; diff --git a/mscripts/game/npc.mn b/mscripts/game/npc.mn new file mode 100644 index 000000000..98c0a1573 --- /dev/null +++ b/mscripts/game/npc.mn @@ -0,0 +1,25 @@ +/* + OpenMW - The completely unofficial reimplementation of Morrowind + Copyright (C) 2008 Nicolay Korslund + Email: < korslund@gmail.com > + WWW: http://openmw.snaptoad.com/ + + This file (npc.mn) 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/ . + + */ + +class NPC : Person + diff --git a/mscripts/game/player.mn b/mscripts/game/player.mn new file mode 100644 index 000000000..092605613 --- /dev/null +++ b/mscripts/game/player.mn @@ -0,0 +1,27 @@ +/* + OpenMW - The completely unofficial reimplementation of Morrowind + Copyright (C) 2008 Nicolay Korslund + Email: < korslund@gmail.com > + WWW: http://openmw.snaptoad.com/ + + This file (player.mn) 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/ . + + */ + +singleton player : Person + +name="Player Name" +level = 5 // Just an example value diff --git a/mscripts/setup.d b/mscripts/setup.d index 5ac07bb82..11e568307 100644 --- a/mscripts/setup.d +++ b/mscripts/setup.d @@ -28,9 +28,11 @@ import monster.compiler.scopes : global; import monster.modules.timer; import core.config; -import ogre.gui; +import gui.gui; +import scene.player; import std.string; +import std.stdio; // Set up the base Monster classes we need in OpenMW void initMonsterScripts() @@ -45,6 +47,9 @@ void initMonsterScripts() // Get the Config singleton object config.mo = vm.load("Config").getSing(); + // Set up the player object. + playerData.setup(); + // Set up the GUI Monster module setupGUIScripts(); } @@ -62,7 +67,6 @@ void runGUIScripts() // This should probably not be here: import monster.vm.dbg; -import std.string; extern(C): void dbg_trace(char*str) { dbg.trace(toString(str)); } diff --git a/ogre/bindings.d b/ogre/bindings.d index fab1fb25a..3d2ce674a 100644 --- a/ogre/bindings.d +++ b/ogre/bindings.d @@ -164,28 +164,3 @@ void ogre_moveCameraRel(float x, float y, float z); // Insert a raw RGBA image into the texture system. //void ogre_insertTexture(char *name, int width, int height, void *data); - -// GUI functions. Under development. -typedef void* WidgetPtr; -void gui_setupGUI(int debugOut); -void gui_toggleGui(); -void gui_setCellName(char *str); - -// Get the widget type, as a string -char *gui_widgetType(WidgetPtr); - -// Get the height or width of a widget. If the argument is null, -// return the size of the screen. -int gui_getHeight(WidgetPtr); -int gui_getWidth(WidgetPtr); - -// Set various properties of a given widget -void gui_setCaption(WidgetPtr, char*); -void gui_setNeedMouseFocus(WidgetPtr, int); -void gui_setTextColor(WidgetPtr, float,float,float); -void gui_setCoord(WidgetPtr, int,int,int,int); - -// Various ways to get or create widgets -WidgetPtr gui_loadLayout(char *file, char *prefix, WidgetPtr parent); -WidgetPtr gui_getChild(WidgetPtr, char*); -WidgetPtr gui_createText(char *skin, int x, int y, int w, int h, char *layer); diff --git a/ogre/cpp_interface.cpp b/ogre/cpp_interface.cpp index 04ba18d68..a8fe32993 100644 --- a/ogre/cpp_interface.cpp +++ b/ogre/cpp_interface.cpp @@ -48,7 +48,7 @@ extern "C" int32_t ogre_configure( { // Set up logging first new LogManager; - Log *log = LogManager::getSingleton().createLog("default"); + Log *log = LogManager::getSingleton().createLog("Ogre.log"); if(debugOut) // Full log detail diff --git a/ogre/cpp_mygui.cpp b/ogre/cpp_mygui.cpp index 55ec17bd6..7c7b72ae1 100644 --- a/ogre/cpp_mygui.cpp +++ b/ogre/cpp_mygui.cpp @@ -24,7 +24,9 @@ extern "C" int32_t gui_getWidth(MyGUI::WidgetPtr p) // Set various properties of a given widget extern "C" void gui_setCaption(MyGUI::WidgetPtr p, char* s) -{ p->setCaption(s); } +{ + p->setCaption(s); +} extern "C" void gui_setNeedMouseFocus(MyGUI::WidgetPtr p, int32_t b) { p->setNeedMouseFocus(b); } diff --git a/openmw.d b/openmw.d index c8eadfc54..235afc423 100644 --- a/openmw.d +++ b/openmw.d @@ -30,6 +30,7 @@ import std.file; import ogre.ogre; import ogre.bindings; +import gui.bindings; import bullet.bullet; diff --git a/scene/celldata.d b/scene/celldata.d index f3d57cfbb..97324cb5a 100644 --- a/scene/celldata.d +++ b/scene/celldata.d @@ -453,7 +453,7 @@ class CellData { // Create a creature, based on current player level. LiveCreature ls; - ls.m = l.instCreature(playerData.level); + ls.m = l.instCreature(*playerData.level); if(ls.m != null) { // Note that this clones a creature object, not a @@ -565,7 +565,7 @@ class CellData if(door && !playerData.posSet) { playerData.posSet = true; - playerData.position = *pos; + *playerData.position = *pos; } } } // End of while(hasMoreSubs) diff --git a/scene/player.d b/scene/player.d index 8c2908581..c794fe350 100644 --- a/scene/player.d +++ b/scene/player.d @@ -24,6 +24,7 @@ module scene.player; import ogre.ogre; +import monster.monster; /* * Contains essential data about the player and other current game @@ -34,14 +35,30 @@ PlayerData playerData; struct PlayerData { - // Position and rotation. The rotation is not updated continuously, - // only the position. - Placement position; + MonsterObject *mo; - // Just an example value, we use it for resolving leveled lists - // (lists that determine eg. what creatures to put in a cave based - // on what level the player is.) - short level = 5; + Placement *position; + int *level; + + // Set up the player object. This is still pretty hackish and + // temporary. + void setup() + { + assert(mo is null); + mo = vm.load("game.player").createObject; + level = mo.getIntPtr("level"); + + // Still an ugly hack + position = cast(Placement*)mo.getFloatPtr("x"); + } + + /* + char[] getName() + { + assert(mo !is null); + return mo.getString8("name"); + } + */ // Temp. way of selecting start point - used in celldata bool posSet = false;