• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

arpeggiodragon

Members
  • Content count

    28
  • Joined

  • Last visited

Community Reputation

586 Good

About arpeggiodragon

  • Rank
    Member
  1. I actually got a little curious about this so I generated a 'as_unity_build' module to see how much code there would be without duplicate symbols. Must be a case of a bored late-night Monday I guess. :P   Compiling an "in house" release build on Visual Studio with '/MD' and removing the whole program optimization option ('/GL') results in a final object library size of 1.3 MB.  (I should note that for full public release builds you generally want link-time code generation, as this allows the linker to do many extra optimizations at the cost of longer link times.)   If anyone is interested here is the cpp file:   // as_unity_build.cpp // Builds the entire angelscript library simply by compiling this single file. // *note* This should be the only .cpp file that is compiled; do not include any others. #include "as_atomic.cpp" #include "as_builder.cpp" #include "as_bytecode.cpp" #include "as_callfunc.cpp" #include "as_callfunc_arm.cpp" #include "as_callfunc_mips.cpp" #include "as_callfunc_ppc.cpp" #include "as_callfunc_ppc_64.cpp" #include "as_callfunc_sh4.cpp" #include "as_callfunc_x64_gcc.cpp" #include "as_callfunc_x64_mingw.cpp" #include "as_callfunc_x64_msvc.cpp" #include "as_callfunc_x86.cpp" #include "as_callfunc_xenon.cpp" #include "as_compiler.cpp" #include "as_configgroup.cpp" #include "as_context.cpp" #include "as_datatype.cpp" #include "as_gc.cpp" #include "as_generic.cpp" #include "as_globalproperty.cpp" #include "as_memory.cpp" #include "as_module.cpp" #include "as_objecttype.cpp" #include "as_outputbuffer.cpp" #include "as_parser.cpp" #include "as_restore.cpp" #include "as_scriptcode.cpp" #include "as_scriptengine.cpp" #include "as_scriptfunction.cpp" #include "as_scriptnode.cpp" #include "as_scriptobject.cpp" #include "as_string.cpp" #include "as_string_util.cpp" #include "as_thread.cpp" #include "as_tokenizer.cpp" #include "as_typeinfo.cpp" #include "as_variablescope.cpp"
  2. So new features. Much awesome. wow! (Seriously I can't wait to play with this new stuff—I admittedly have not been keeping up-to-date this past year. Great work!)   Just updated to the latest revision (1854); with the default msvc project setting "treat warnings as errors" I get the following: 1>..\..\source\as_restore.cpp(828) : error C2220: warning treated as error - no 'object' file generated 1>..\..\source\as_restore.cpp(828) : warning C4389: '!=' : signed/unsigned mismatch 1>..\..\source\as_restore.cpp(840) : warning C4389: '!=' : signed/unsigned mismatch 1>c:\svn\angelscript\sdk\angelscript\source\as_scriptengine.cpp(436) : warning C4702: unreachable code 1>..\..\source\as_compiler.cpp(1447) : error C2220: warning treated as error - no 'object' file generated 1>..\..\source\as_compiler.cpp(1447) : warning C4244: '=' : conversion from 'int' to 'short', possible loss of data 1>..\..\source\as_compiler.cpp(2620) : warning C4244: 'argument' : conversion from 'int' to 'short', possible loss of data 1>..\..\source\as_compiler.cpp(2626) : warning C4244: 'argument' : conversion from 'int' to 'short', possible loss of data 1>..\..\source\as_compiler.cpp(2637) : warning C4244: 'argument' : conversion from 'int' to 'short', possible loss of data 1>..\..\source\as_compiler.cpp(2741) : warning C4244: 'argument' : conversion from 'int' to 'short', possible loss of data 1>c:\svn\angelscript\sdk\angelscript\source\as_builder.cpp(818) : warning C4706: assignment within conditional expression This option only appears to be in the debug configuration.
  3. <p>Ran into a minor problem compiling for MSVC 2008 with AS_NO_THREADS defined. 1>as_thread.cpp 1>..\..\source\as_thread.cpp(75) : error C2220: warning treated as error - no 'object' file generated 1>..\..\source\as_thread.cpp(75) : warning C4390: ';' : empty controlled statement found; is this the intent? 1>..\..\source\as_thread.cpp(81) : warning C4390: ';' : empty controlled statement found; is this the intent? 1>..\..\source\as_thread.cpp(87) : warning C4390: ';' : empty controlled statement found; is this the intent? 1>..\..\source\as_thread.cpp(93) : warning C4390: ';' : empty controlled statement found; is this the intent? Removing the \WX (treat warnings as errors) property fixed the error for me.EDIT: Awesome. I see you've added namespaces! (well they are new to me) [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img] EDIT2: What am I doing wrong here? r = engine->SetDefaultNamespace("input"); assert( r >= 0 ); r = engine->RegisterGlobalFunction( "::joystick@ get_joystick(int)", asFUNCTION(Input::GetJoystick), asCALL_CDECL); assert( r >= 0 ); r = engine->SetDefaultNamespace(""); assert( r >= 0 ); script: input::joystick[0]; //input is undeclared.
  4. Found it. [code] class A{} class B : A {} void func() { switch(0){ default: B @b = cast<B>( typo.createInstance() ); //typo is obviously not an object. if(b is null) ///... } [/code]
  5. Hi. In release mode while compiling scripts the application crashes without any log/console output. Taking a look in debug mode gives the following stack: [quote] msvcr90d.dll!_wassert(const wchar_t * expr=0x0080ae20, const wchar_t * filename=0x0080a1b4, unsigned int lineno=4071) Line 335 C > Engine.exe!asCCompiler::ImplicitConversion(asSExprContext * ctx=0x0012e908, const asCDataType & to={...}, asCScriptNode * node=0x0603b830, EImplicitConv convType=asIC_IMPLICIT_CONV, bool generateCode=true, asCArray<int> * reservedVars=0x00000000, bool allowObjectConstruct=false) Line 4071 + 0x35 bytes C++ Engine.exe!asCCompiler::PrepareForAssignment(asCDataType * lvalue=0x0012e814, asSExprContext * rctx=0x0012e908, asCScriptNode * node=0x0603b830, asSExprContext * lvalueExpr=0x00000000) Line 3468 C++ Engine.exe!asCCompiler::CompileDeclaration(asCScriptNode * decl=0x0603b0b0, asCByteCode * bc=0x0012ebec) Line 1785 C++ Engine.exe!asCCompiler::CompileStatementBlock(asCScriptNode * block=0x0603a810, bool ownVariableScope=true, bool * hasReturn=0x0012ecb3, asCByteCode * bc=0x0012ec70) Line 697 C++ Engine.exe!asCCompiler::CompileStatement(asCScriptNode * statement=0x0603a810, bool * hasReturn=0x0012ecb3, asCByteCode * bc=0x0012ec70) Line 2017 + 0x16 bytes C++ Engine.exe!asCCompiler::CompileCase(asCScriptNode * node=0x0603a810, asCByteCode * bc=0x0012ee80) Line 2353 C++ Engine.exe!asCCompiler::CompileSwitchStatement(asCScriptNode * snode=0x06039f10, bool * __formal=0x0012f0a3, asCByteCode * bc=0x0012ef5c) Line 2299 C++ Engine.exe!asCCompiler::CompileStatement(asCScriptNode * statement=0x06039f10, bool * hasReturn=0x0012f0a3, asCByteCode * bc=0x0012ef5c) Line 2033 + 0x14 bytes C++ Engine.exe!asCCompiler::CompileStatementBlock(asCScriptNode * block=0x05ebed18, bool ownVariableScope=true, bool * hasReturn=0x0012f0a3, asCByteCode * bc=0x0012f060) Line 700 C++ Engine.exe!asCCompiler::CompileStatement(asCScriptNode * statement=0x05ebed18, bool * hasReturn=0x0012f0a3, asCByteCode * bc=0x0012f060) Line 2017 + 0x16 bytes C++ Engine.exe!asCCompiler::CompileIfStatement(asCScriptNode * inode=0x060394f0, bool * hasReturn=0x0012f367, asCByteCode * bc=0x0012f184) Line 2412 C++ Engine.exe!asCCompiler::CompileStatement(asCScriptNode * statement=0x060394f0, bool * hasReturn=0x0012f367, asCByteCode * bc=0x0012f184) Line 2019 + 0x14 bytes C++ Engine.exe!asCCompiler::CompileStatementBlock(asCScriptNode * block=0x05e5f130, bool ownVariableScope=false, bool * hasReturn=0x0012f367, asCByteCode * bc=0x0012f324) Line 700 C++ Engine.exe!asCCompiler::CompileFunction(asCBuilder * builder=0x05de6ee0, asCScriptCode * script=0x05d781f0, asCScriptNode * func=0x05e3b268, asCScriptFunction * outFunc=0x05eef158) Line 322 C++ Engine.exe!asCBuilder::CompileFunctions() Line 513 C++ Engine.exe!asCBuilder::Build() Line 182 C++ Engine.exe!asCModule::Build() Line 140 + 0xb bytes C++ [/quote] And line in as_compiler.cpp where the assertion fails: [code] void asCCompiler::ImplicitConversion(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode, asCArray<int> *reservedVars, bool allowObjectConstruct) { asASSERT( ctx->type.dataType.GetTokenType() != ttUnrecognizedToken || ctx->type.dataType.IsNullHandle() ); [code] I can go through the scripts one error at a time instead of batch fixing (there are many scripts) them if you need more detailed information on this, or even post the offending script function (once I find it, that is) if it would help. I see that CompileStatementBlock() is recently called so I assume it is a local declaration after a case: statement? I haven't had any luck so far, I may have to resume the search tomorrow.
  6. ..or something similar with a better name. Basically just telling the parser to substitute '[' ']' for the actual "opIndex(..)" defined method. I noticed the current behavior for opIndex allows overloads. [code] r = engine->RegisterObjectMethod("Array<T>", "T &opIndex(uint)", asMETHOD(ScriptArrayTemplate, At1), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("Array<T>", "T &opIndex(uint,uint)", asMETHOD(ScriptArrayTemplate, At2), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("Array<T>", "T &opIndex(uint,uint,uint)", asMETHOD(ScriptArrayTemplate, At3), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("Array<T>", "const T &opIndex(uint) const", asMETHOD(ScriptArrayTemplate, At1), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("Array<T>", "const T &opIndex(uint,uint) const", asMETHOD(ScriptArrayTemplate, At2), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("Array<T>", "const T &opIndex(uint,uint,uint) const", asMETHOD(ScriptArrayTemplate, At3), asCALL_THISCALL); assert( r >= 0 ); [/code] However right now they can only be properly accessed by writing out the full method in the script. Is this intended? [code] //as script Array<int> a; a.opIndex(1,2) = 3; //ok a[1,2] = 3;//error ..could be rewritten as this with an engine property flag: a.opIndex(1,2) // '[', ']' have been expanded to the actual method //maintain compatibility Array< Array<int> > a2; a2[1][2] = 3; //a2.opIndex(1).opIndex(2) a2[1,2,3][4] ... [/code] Thought it worth mentioning as it seems like it would be really easy to implement and wouldn't break backwards or forwards compatibility between angelscript versions and gives a nice C# like array syntax if desired. Cheers. edit: Didn't want this to sound like a request, just something to add if you think it's a good idea. edit2: Actually put this behavior in using the pre-compiler (equivelent of CScriptBuilder), which simply replaces "[]" tokens with the full "opIndex()" declaration . Works great.
  7. Thanks! I will test these properly with the older version when I get the chance.
  8. .... Oh my god, I'm blind. There is in fact an asCALL_STDCALL. Time for a good 'ol fashioned facepalm eh? Thanks!
  9. Hi. I am really stumped by this one. This problem has come about from binding OpenGL API. Two of the registered functions: [code] r = engine->RegisterGlobalFunction( "void glTranslatef (float, float, float)", asFUNCTION(glTranslatef), asCALL_CDECL ); assert( r >= 0 ); r = engine->RegisterGlobalFunction( "void glEnd()", asFUNCTION(glTranslatef), asCALL_CDECL ); assert( r >= 0 ); //..etc [/code] Calling a function like glEnd() or glLoadIdentity() seems to work , whereas glTranslatef(..) and others will fail with a VC++ runtime check: Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention. ...With a crash to follow. As far as I can tell glFunctions on MSVC9 are defined "__declspec(dllimport) ret __stdcall decl()" Any help would be great.
  10. Hi. I've been getting some minor performance discrepancies with different scripts so I've been experimenting to try and minimize this. What I've found for value types is this: -Using this as a base for comparison: [code] float x = 0; float y = 0; float xx = 1; float yy = 2; for(int i=0;i<100000;++i) { x = xx; //simple assignment test.. this is actually pretty fast for built in value types! y = yy; xx = x; yy = y; } [/code] 3x slower [code] Vector2 a; Vector2 b; for(int i=0;i<100000;++i) { a.x = b.x; b.x = a.x; a.y = b.y; b.y = a.y; } [/code] This is still very fast. Only 2.1 times slower than the base test: [code] Vector2 a; Vector2 b; for(int i=0;i<100000;++i) { a = b; //evaluates to a function call. b = a; } [/code] 8x slower ??? [code] class test { Vector2 a; Vector2 b; void run() { for(int i=0;i<100000;++i) { a = b; // a, b are now class members, same speed as if declared global b = a; } } } [/code] also 8x slower [code] class V { Vector2 v; } V a; V b; for(int i=0;i<100000;++i) { a.v = b.v; b.v = a.v; } [/code] Tested these in release using windows performance timers. Is this expected in terms of speed? -Also wondering if there's any tricks to get class members to be better 'cached' when executing a function within that class? (I use a lot of classes) Thanks.
  11. Here's how I have mine: const std::string vec2 = "Vector2"; r = engine->RegisterObjectType( vec2.c_str(), sizeof(Vector2), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_CA); assert( r >= 0 ); /* members */ r = engine->RegisterObjectProperty( vec2.c_str(), "float x", offsetof(Vector2, x)); assert( r >= 0 ); r = engine->RegisterObjectProperty( vec2.c_str(), "float y", offsetof(Vector2, y)); assert( r >= 0 ); /* constructors */ r = engine->RegisterObjectBehaviour( vec2.c_str(), asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Vector2DefaultConstructor), asCALL_CDECL_OBJLAST); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( vec2.c_str(), asBEHAVE_CONSTRUCT, "void f(const Vector2 &in)", asFUNCTION(Vector2CopyConstructor), asCALL_CDECL_OBJLAST); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( vec2.c_str(), asBEHAVE_CONSTRUCT, "void f(float, float)", asFUNCTION(Vector2InitConstructor), asCALL_CDECL_OBJLAST); assert( r >= 0 ); /* operator overloads */ r = engine->RegisterObjectMethod( vec2.c_str(), "bool opEquals(const Vector2 &in) const", asMETHODPR(Vector2, operator ==, (const Vector2&) const, bool), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "bool opEquals(const Vector2 &in) const", asMETHODPR(Vector2, operator !=, (const Vector2&) const, bool), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "bool opCmp(const Vector2 &in) const", asMETHODPR(Vector2, operator >, (const Vector2&) const, bool), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "bool opCmp(const Vector2 &in) const", asMETHODPR(Vector2, operator <, (const Vector2&) const, bool), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "bool opCmp(const Vector2 &in) const", asMETHODPR(Vector2, operator >=, (const Vector2&) const, bool), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "bool opCmp(const Vector2 &in) const", asMETHODPR(Vector2, operator <=, (const Vector2&) const, bool), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 &opAddAssign(const Vector2 &in)", asMETHODPR(Vector2, operator +=, (const Vector2&), Vector2&), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 &opSubAssign(const Vector2 &in)", asMETHODPR(Vector2, operator -=, (const Vector2&), Vector2&), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 &opMulAssign(const Vector2 &in)", asMETHODPR(Vector2, operator *=, (const Vector2&), Vector2&), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 &opDivAssign(const Vector2 &in)", asMETHODPR(Vector2, operator /=, (const Vector2&), Vector2&), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 &opAddAssign(float)", asMETHODPR(Vector2, operator +=, (float), Vector2&), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 &opSubAssign(float)", asMETHODPR(Vector2, operator -=, (float), Vector2&), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 &opMulAssign(float)", asMETHODPR(Vector2, operator *=, (float), Vector2&), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 &opDivAssign(float)", asMETHODPR(Vector2, operator /=, (float), Vector2&), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 opAdd(const Vector2 &in) const", asMETHODPR(Vector2, operator +, (const Vector2&) const, Vector2), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 opSub(const Vector2 &in) const", asMETHODPR(Vector2, operator -, (const Vector2&) const, Vector2), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 opMul(const Vector2 &in) const", asMETHODPR(Vector2, operator *, (const Vector2&) const, Vector2), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 opDiv(const Vector2 &in) const", asMETHODPR(Vector2, operator /, (const Vector2&) const, Vector2), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 opAdd(float) const", asMETHODPR(Vector2, operator +, (float) const, Vector2), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 opSub(float) const", asMETHODPR(Vector2, operator -, (float) const, Vector2), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 opMul(float) const", asMETHODPR(Vector2, operator *, (float) const, Vector2), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 opDiv(float) const", asMETHODPR(Vector2, operator /, (float) const, Vector2), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 opAdd(float, const Vector2 &in) const", asFUNCTIONPR(operator +, (float, const Vector2&), Vector2), asCALL_CDECL_OBJLAST); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 opSub(float, const Vector2 &in) const", asFUNCTIONPR(operator -, (float, const Vector2&), Vector2), asCALL_CDECL_OBJLAST); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 opMul(float, const Vector2 &in) const", asFUNCTIONPR(operator *, (float, const Vector2&), Vector2), asCALL_CDECL_OBJLAST); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 opDiv(float, const Vector2 &in) const", asFUNCTIONPR(operator /, (float, const Vector2&), Vector2), asCALL_CDECL_OBJLAST); assert( r >= 0 ); // Register the object methods r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 normal() const", asMETHODPR( Vector2, Normal, (void) const, Vector2), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "float length() const", asMETHODPR( Vector2, Length, (void) const, float), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "float length_squared() const", asMETHODPR( Vector2, LengthSquared, (void) const, float), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "float distance(const Vector2 &in) const", asMETHODPR( Vector2, Distance, (const Vector2 &v) const, float), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "float distance_squared(const Vector2 &in) const", asMETHODPR( Vector2, DistanceSquared, (const Vector2 &v) const, float), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "float dot(const Vector2 &in) const", asMETHODPR( Vector2, Dot, (const Vector2 &v) const, float), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "float cross(const Vector2 &in) const", asMETHODPR( Vector2, Cross, (const Vector2 &v) const, float), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 min(const Vector2 &in) const", asMETHODPR( Vector2, Min, (const Vector2&) const, Vector2), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 max(const Vector2 &in) const", asMETHODPR( Vector2, Max, (const Vector2&) const, Vector2), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 to_degrees() const", asMETHODPR( Vector2, ToDegrees, (void) const, Vector2), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( vec2.c_str(), "Vector2 to_radians() const", asMETHODPR( Vector2, ToRadians, (void) const, Vector2), asCALL_THISCALL ); assert( r >= 0 ); Half of those have not been tested but you get the idea.
  12. [EDIT]: nvrmnd, got it working. Okay, I edited this thinking I got it working but I was wrong. What I am doing is trying to get a multi-dimensional array class with template args working. It's only meant to be used right now by basic types handled with template specialization so it's not very robust, but I need a class that can handle up to three-dimensional arrays of different types. What happens right now is I get a crash on Array<int> arr; arr.resize( 64, 64, 64 ); //works int temp = arr.at( 2 ); <--here I looked at the array add_on and I think I do the reference counting the same, though I'd wager dollars to donuts that I am making some very simple mistake. Hopefully someone can spot it quickly. Here is the code: namespace scriptarraytemplate { template<class T> class ScriptArray { public: ScriptArray() : self(), ref_count(1), type(0) {} ScriptArray( uint x ) : self(x), ref_count(1), type(0) {} ScriptArray( uint y, uint x ) : self(y,x), ref_count(1), type(0) {} ScriptArray( uint z, uint y, uint x ) : self(z,y,x), ref_count(1), type(0) {} ScriptArray( const ScriptArray<T>& other ) : self(other.self), ref_count(1), type(0) {} ~ScriptArray() { if( type ) type->Release(); } void AddTypeRef( asIObjectType *objType ) { type = objType; type->AddRef(); } static ScriptArray<T>* ScriptArrayFactory() { ScriptArray<T> *a = new ScriptArray<T>(); return CheckScriptException( a ); } static ScriptArray<T>* ScriptArrayFactory1( uint x ) { ScriptArray<T> *a = new ScriptArray<T>( x ); return CheckScriptException( a ); } static ScriptArray<T>* ScriptArrayFactory2( uint y, uint x ) { ScriptArray<T> *a = new ScriptArray<T>( y, x ); return CheckScriptException( a ); } static ScriptArray<T>* ScriptArrayFactory3( uint z, uint y, uint x ) { ScriptArray<T> *a = new ScriptArray<T>( z, y, x ); return CheckScriptException( a ); } static ScriptArray<T>* ScriptArrayFactoryCopy( const ScriptArray<T>& _Array ) { ScriptArray<T> *a = new ScriptArray<T>( _Array ); return CheckScriptException( a ); } ///////////////////////////////////////////////////////////// static ScriptArray<T>* _ScriptArrayFactory( asIObjectType *objType ) { ScriptArray<T> *a = new ScriptArray<T>(); a->AddTypeRef( objType ); return CheckScriptException( a ); } static ScriptArray<T>* _ScriptArrayFactory1( asIObjectType *objType, uint x ) { ScriptArray<T> *a = new ScriptArray<T>( x ); a->AddTypeRef( objType ); return CheckScriptException( a ); } static ScriptArray<T>* _ScriptArrayFactory2( asIObjectType *objType, uint y, uint x ) { ScriptArray<T> *a = new ScriptArray<T>( y, x ); a->AddTypeRef( objType ); return CheckScriptException( a ); } static ScriptArray<T>* _ScriptArrayFactory3( asIObjectType *objType, uint z, uint y, uint x ) { ScriptArray<T> *a = new ScriptArray<T>( z, y, x ); a->AddTypeRef( objType ); return CheckScriptException( a ); } static ScriptArray<T>* _ScriptArrayFactoryCopy( asIObjectType *objType, const ScriptArray<T>& _Array ) { ScriptArray<T> *a = new ScriptArray<T>( _Array ); a->AddTypeRef( objType ); return CheckScriptException( a ); } ////////////////////////////////////////////////////////////// static ScriptArray<T> *CheckScriptException( ScriptArray<T>* _Array ) { // It's possible the constructor raised a script exception, in which case we // need to free the memory and return null instead, else we get a memory leak. asIScriptContext *ctx = asGetActiveContext(); if( ctx && ctx->GetState() == asEXECUTION_EXCEPTION ) { delete _Array; return 0; } return _Array; } ScriptArray<T>& AssignmentOperator( const ScriptArray<T>& rhs ) { self = rhs.self; return *this; } T* At1( uint x ) { if( x >= self.Size() ) { asIScriptContext* activeContext = asGetActiveContext(); if( activeContext ) activeContext->SetException("Array Index Out of Bounds."); return 0; } return &self( x ); } T* At2( uint y, uint x ) { if( self.Offset(y, x) >= self.Size() ) { asIScriptContext* activeContext = asGetActiveContext(); if( activeContext ) activeContext->SetException("Array Index Out of Bounds."); return 0; } return &self( y, x ); } T* At3( uint z, uint y, uint x ) { if( self.Offset(z, y, x) >= self.Size() ) { asIScriptContext* activeContext = asGetActiveContext(); if( activeContext ) activeContext->SetException("Array Index Out of Bounds."); return 0; } return &self( z, y, x ); } uint Size() { return self.Size(); } void Resize1( uint x ) { self.Resize(x); } void Resize2( uint y, uint x ) { self.Resize(y, x); } void Resize3( uint z, uint y, uint x ) { self.Resize(z, y, x); } bool Empty() { return self.Empty(); } uint Offset1( uint x, Array<T>* self ) { return x; } uint Offset2( uint y, uint x ) { return self.Offset(y, x); } uint Offset3( uint z, uint y, uint x ) { return self.Offset(z, y, x); } void Assign( uint begin, uint end, const T& value ) { self.Assign( begin, end, value ); } void AddRef() { ++ref_count; } void Release() { if( --ref_count <= 0 ) { delete this; } } protected: Array<T> self; int ref_count; asIObjectType *type; }; } //namespace scriptarraytemplate void ScriptingEngine::RegisterScriptArrayTemplateSpecializations() { RegisterArrayTemplate<int>( "Array<T>", "T" ); RegisterArrayTemplateSpecialization<int> ( "Array<int>", "int" ); //RegisterArrayTemplateSpecialization<float> ( "Array<float>", "float" ); //RegisterArrayTemplateSpecialization<ubColor> ( "Array<Color>", "Color" ); //RegisterArrayTemplateSpecialization<Vector2> ( "Array<Vector2>", "Vector2" ); } template <class T> void ScriptingEngine::RegisterArrayTemplateSpecialization( const std::string decl, const std::string type ) { int r(0); using namespace scriptarraytemplate; const std::string const_ref( (std::string("const ") + type) + " &in" ); // register the array type r = engine->RegisterObjectType( decl.c_str(), 0, asOBJ_REF ); assert( r >= 0 ); // constructors r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY, ( decl + " @f()" ).c_str(), asFUNCTION(ScriptArray<T>::ScriptArrayFactory), asCALL_CDECL ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY, (((decl + " @f(") + const_ref) + ")" ).c_str(), asFUNCTION(ScriptArray<T>::ScriptArrayFactory1), asCALL_CDECL ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY, (((((decl + " @f(") + const_ref) + "," ) + const_ref ) + ")" ).c_str(), asFUNCTION(ScriptArray<T>::ScriptArrayFactory2), asCALL_CDECL ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY, (((((((decl + " @f(") + const_ref) + "," ) + const_ref ) + "," ) + const_ref ) + ")" ).c_str(), asFUNCTION(ScriptArray<T>::ScriptArrayFactory3), asCALL_CDECL ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY, (((decl + " @f(const ") + decl) + " &in)" ).c_str(), asFUNCTION(ScriptArray<T>::ScriptArrayFactoryCopy), asCALL_CDECL ); assert( r >= 0 ); // index methods r = engine->RegisterObjectMethod( decl.c_str(), ( type + "& at(uint)" ).c_str(), asMETHOD(ScriptArray<T>, At1), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), ( type + "& at(uint, uint)" ).c_str(), asMETHOD(ScriptArray<T>, At2), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), ( type + "& at(uint, uint, uint)" ).c_str(), asMETHOD(ScriptArray<T>, At3), asCALL_THISCALL ); assert( r >= 0 ); // resize methods r = engine->RegisterObjectMethod( decl.c_str(), "void resize(uint)", asMETHOD(ScriptArray<T>, Resize1), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), "void resize(uint, uint)", asMETHOD(ScriptArray<T>, Resize2), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), "void resize(uint, uint, uint)", asMETHOD(ScriptArray<T>, Resize3), asCALL_THISCALL ); assert( r >= 0 ); // operators r = engine->RegisterObjectMethod( decl.c_str(), ( decl + "& opAssign(const " + type + " &in)" ).c_str(), asMETHOD(ScriptArray<T>, AssignmentOperator), asCALL_THISCALL ); assert( r >= 0 ); // methods r = engine->RegisterObjectMethod( decl.c_str(), "bool empty() const", asMETHOD(ScriptArray<T>, Empty), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), "uint size() const", asMETHOD(ScriptArray<T>, Size), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), "uint offset(uint)", asMETHOD(ScriptArray<T>, Offset1), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), "uint offset(uint, uint)", asMETHOD(ScriptArray<T>, Offset2), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), "uint offset(uint, uint, uint)", asMETHOD(ScriptArray<T>, Offset3), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), (( std::string( "void assign(uint, uint, " ) + const_ref ) + ")" ).c_str(), asMETHOD(ScriptArray<T>, Assign), asCALL_THISCALL ); assert( r >= 0 ); // memory management r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_ADDREF, "void f()", asMETHOD(ScriptArray<T>, AddRef), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_RELEASE, "void f()", asMETHOD(ScriptArray<T>, Release), asCALL_THISCALL); assert( r >= 0 ); } template <class T> void ScriptingEngine::RegisterArrayTemplate( const std::string decl, const std::string type ) { int r(0); using namespace scriptarraytemplate; const std::string const_ref( (std::string("const ") + type) + " &in" ); // register the array type r = engine->RegisterObjectType( "Array<class T>", 0, asOBJ_REF | asOBJ_TEMPLATE ); assert( r >= 0 ); // constructors r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY, ( decl + " @f(int &in)" ).c_str(), asFUNCTION(ScriptArray<T>::_ScriptArrayFactory), asCALL_CDECL ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY, (((decl + " @f(int &in, ") + const_ref) + ")" ).c_str(), asFUNCTION(ScriptArray<T>::_ScriptArrayFactory1), asCALL_CDECL ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY, (((((decl + " @f(int &in, ") + const_ref) + "," ) + const_ref ) + ")" ).c_str(), asFUNCTION(ScriptArray<T>::_ScriptArrayFactory2), asCALL_CDECL ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY, (((((((decl + " @f(int &in, ") + const_ref) + "," ) + const_ref ) + "," ) + const_ref ) + ")" ).c_str(), asFUNCTION(ScriptArray<T>::_ScriptArrayFactory3), asCALL_CDECL ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_FACTORY, (((decl + " @f(int &in, const ") + decl) + " &in)" ).c_str(), asFUNCTION(ScriptArray<T>::_ScriptArrayFactoryCopy), asCALL_CDECL ); assert( r >= 0 ); // index methods r = engine->RegisterObjectMethod( decl.c_str(), ( type + "& at(uint)" ).c_str(), asMETHOD(ScriptArray<T>, At1), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), ( type + "& at(uint, uint)" ).c_str(), asMETHOD(ScriptArray<T>, At2), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), ( type + "& at(uint, uint, uint)" ).c_str(), asMETHOD(ScriptArray<T>, At3), asCALL_THISCALL ); assert( r >= 0 ); // resize methods r = engine->RegisterObjectMethod( decl.c_str(), "void resize(uint)", asMETHOD(ScriptArray<T>, Resize1), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), "void resize(uint, uint)", asMETHOD(ScriptArray<T>, Resize2), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), "void resize(uint, uint, uint)", asMETHOD(ScriptArray<T>, Resize3), asCALL_THISCALL ); assert( r >= 0 ); // operators r = engine->RegisterObjectMethod( decl.c_str(), ( decl + "& opAssign(const " + type + " &in)" ).c_str(), asMETHOD(ScriptArray<T>, AssignmentOperator), asCALL_THISCALL ); assert( r >= 0 ); // methods r = engine->RegisterObjectMethod( decl.c_str(), "bool empty() const", asMETHOD(ScriptArray<T>, Empty), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), "uint size() const", asMETHOD(ScriptArray<T>, Size), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), "uint offset(uint)", asMETHOD(ScriptArray<T>, Offset1), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), "uint offset(uint, uint)", asMETHOD(ScriptArray<T>, Offset2), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), "uint offset(uint, uint, uint)", asMETHOD(ScriptArray<T>, Offset3), asCALL_THISCALL ); assert( r >= 0 ); r = engine->RegisterObjectMethod( decl.c_str(), (( std::string( "void assign(uint, uint, " ) + const_ref ) + ")" ).c_str(), asMETHOD(ScriptArray<T>, Assign), asCALL_THISCALL ); assert( r >= 0 ); // memory management r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_ADDREF, "void f()", asMETHOD(ScriptArray<T>, AddRef), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( decl.c_str(), asBEHAVE_RELEASE, "void f()", asMETHOD(ScriptArray<T>, Release), asCALL_THISCALL); assert( r >= 0 ); } Just curious; Any plans to allow a class to register their own index operator? Like: "T& uint[][][] f()" or something which might translate to "T& f(uint,uint,uint)"? It's a quick mock-up but that's the idea. Right now index ops can take only a single value. [Edited by - arpeggiodragon on September 22, 2010 6:49:35 PM]
  13. I don't know. I'm pretty new at using angelscript interfaces. :P Here's how they are declared: //c++ r = engine->RegisterInterface( "GameObject" ); assert( r >= 0 ); r = engine->RegisterObjectMethod( e_str.c_str(), "GameObject@ create(const string &in)", asFUNCTIONPR(CreateEnemy, (const std::string &), asIScriptObject *), callConvType); assert( r >= 0 ); //as class Enemy : GameObject { //... } class MyEnemy : Enemy { MyEnemy(){} MyEnemy(const Vector2 &in pos); void run(){...} } I just tried casting instead and it works fine though. Enemy @e = cast<Enemy> ( enemy.create( "MyEnemy" ) ); if( e is null ) { error("Enemy is null"); } MyEnemy @me = cast<MyEnemy>(e); if( me is null ) { error("MyEnemy is null"); }
  14. Quote:The factory function returns a handle to the object. GetAddressOfReturnValue returns the address to the location where this handle is stored, so you must dereference that to get the actual handle. Yep, this was indeed the problem; coupled with a bug where contexts would get reused and still be in suspended state was causing some major mischief for me. Everything's finally working now. Thank you!
  15. Okay, The problem was I didn't reference count them. :\ Thing is there is no place to release the reference so I assumed to not even add them... Anyway, I get a compile error; "No copy operator available." from this line: GameObject @go = enemy.create( "MyEnemy" ); if( go is null ) { error("GameObject is null"); } How do you define an assignment operator for handles of an interface? [Edited by - arpeggiodragon on September 21, 2010 2:20:28 AM]