changeset 18803:4444cc87af24 draft

(svn r23651) -Feature: [NoGo] GSText now accepts string arguments as parameters to the constructor
author yexo <yexo@openttd.org>
date Wed, 21 Dec 2011 14:55:28 +0000
parents 6a35af277c5e
children 71d835830d4c
files src/script/api/ai/ai_text.hpp.sq src/script/api/game/game_text.hpp.sq src/script/api/script_text.cpp src/script/api/script_text.hpp src/script/api/squirrel_export.awk src/script/squirrel_class.hpp src/script/squirrel_helper.hpp
diffstat 7 files changed, 76 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/script/api/ai/ai_text.hpp.sq
+++ b/src/script/api/ai/ai_text.hpp.sq
@@ -19,7 +19,7 @@
 {
 	DefSQClass<ScriptText, ST_AI> SQAIText("AIText");
 	SQAIText.PreRegister(engine);
-	SQAIText.AddConstructor<void (ScriptText::*)(StringID string), 2>(engine, "xi");
+	SQAIText.AddSQAdvancedConstructor(engine);
 
 	SQAIText.DefSQConst(engine, ScriptText::SCRIPT_TEXT_MAX_PARAMETERS, "SCRIPT_TEXT_MAX_PARAMETERS");
 
--- a/src/script/api/game/game_text.hpp.sq
+++ b/src/script/api/game/game_text.hpp.sq
@@ -19,7 +19,7 @@
 {
 	DefSQClass<ScriptText, ST_GS> SQGSText("GSText");
 	SQGSText.PreRegister(engine);
-	SQGSText.AddConstructor<void (ScriptText::*)(StringID string), 2>(engine, "xi");
+	SQGSText.AddSQAdvancedConstructor(engine);
 
 	SQGSText.DefSQConst(engine, ScriptText::SCRIPT_TEXT_MAX_PARAMETERS, "SCRIPT_TEXT_MAX_PARAMETERS");
 
--- a/src/script/api/script_text.cpp
+++ b/src/script/api/script_text.cpp
@@ -15,10 +15,34 @@
 #include "../squirrel.hpp"
 #include "../../table/control_codes.h"
 
-ScriptText::ScriptText(StringID string) :
-	ZeroedMemoryAllocator(),
-	string(string)
+ScriptText::ScriptText(HSQUIRRELVM vm) :
+	ZeroedMemoryAllocator()
 {
+	int nparam = sq_gettop(vm) - 1;
+	if (nparam < 1) {
+		throw sq_throwerror(vm, _SC("You need to pass at least a StringID to the constructor"));
+	}
+
+	/* First resolve the StringID. */
+	SQInteger sqstring;
+	if (SQ_FAILED(sq_getinteger(vm, 2, &sqstring))) {
+		throw sq_throwerror(vm, _SC("First argument must be a valid StringID"));
+	}
+	this->string = sqstring;
+
+	/* The rest of the parameters must be arguments. */
+	for (int i = 0; i < nparam - 1; i++) {
+		/* Push the parameter to the top of the stack. */
+		sq_push(vm, i + 3);
+
+		if (SQ_FAILED(this->_SetParam(i, vm))) {
+			this->~ScriptText();
+			throw sq_throwerror(vm, _SC("Invalid parameter"));
+		}
+
+		/* Pop the parameter again. */
+		sq_pop(vm, 1);
+	}
 }
 
 ScriptText::~ScriptText()
--- a/src/script/api/script_text.hpp
+++ b/src/script/api/script_text.hpp
@@ -59,8 +59,11 @@
  *
  * If you use parameters in your strings, you will have to define those
  *  parameters, for example like this:
- * local text = ScriptText(ScriptText.STR_NEWS); text.AddParam(1);
- * This will set the {COMPANY} to the name of Company 1.
+ * \code local text = ScriptText(ScriptText.STR_NEWS);
+ * text.AddParam(1); \endcode
+ * This will set the {COMPANY} to the name of Company 1. Alternatively you
+ *  can directly give those arguments to the ScriptText constructor, like this:
+ * \code local text = ScriptText(ScriptText.STR_NEWS, 1); \endcode
  *
  * @api ai game
  */
@@ -68,12 +71,20 @@
 public:
 	static const int SCRIPT_TEXT_MAX_PARAMETERS = 20; ///< The maximum amount of parameters you can give to one object.
 
+#ifndef DOXYGEN_API
+	/**
+	 * The constructor wrapper from Squirrel.
+	 */
+	ScriptText(HSQUIRRELVM vm);
+#else
 	/**
 	 * Generate a text from string. You can set parameters to the instance which
 	 *  can be required for the string.
 	 * @param string The string of the text.
+	 * @param ... Optional arguments for this string.
 	 */
-	ScriptText(StringID string);
+	ScriptText(StringID string, ...);
+#endif
 	~ScriptText();
 
 #ifndef DOXYGEN_API
--- a/src/script/api/squirrel_export.awk
+++ b/src/script/api/squirrel_export.awk
@@ -341,7 +341,11 @@
 		print "	SQ" api_cls ".PreRegister(engine, \"" api_super_cls "\");"
 	}
 	if (virtual_class == "false" && super_cls != "ScriptEvent") {
-		print "	SQ" api_cls ".AddConstructor<void (" cls "::*)(" cls_param[0] "), " cls_param[1]">(engine, \"" cls_param[2] "\");"
+		if (cls_param[2] == "v") {
+			print "	SQ" api_cls ".AddSQAdvancedConstructor(engine);"
+		} else {
+			print "	SQ" api_cls ".AddConstructor<void (" cls "::*)(" cls_param[0] "), " cls_param[1]">(engine, \"" cls_param[2] "\");"
+		}
 	}
 	print ""
 
--- a/src/script/squirrel_class.hpp
+++ b/src/script/squirrel_class.hpp
@@ -117,6 +117,12 @@
 		engine->AddMethod("constructor", DefSQConstructorCallback<CL, Func, Tnparam>, Tnparam, params);
 	}
 
+	void AddSQAdvancedConstructor(Squirrel *engine)
+	{
+		using namespace SQConvert;
+		engine->AddMethod("constructor", DefSQAdvancedConstructorCallback<CL>, 0, NULL);
+	}
+
 	void PostRegister(Squirrel *engine)
 	{
 		engine->AddClassEnd();
--- a/src/script/squirrel_helper.hpp
+++ b/src/script/squirrel_helper.hpp
@@ -885,6 +885,28 @@
 		}
 	}
 
+	/**
+	 * A general template to handle creating of an instance with a complex
+	 *  constructor.
+	 */
+	template <typename Tcls>
+	inline SQInteger DefSQAdvancedConstructorCallback(HSQUIRRELVM vm)
+	{
+		try {
+			/* Find the amount of params we got */
+			int nparam = sq_gettop(vm);
+
+			/* Create the real instance */
+			Tcls *instance = new Tcls(vm);
+			sq_setinstanceup(vm, -nparam, instance);
+			sq_setreleasehook(vm, -nparam, DefSQDestructorCallback<Tcls>);
+			instance->AddRef();
+			return 0;
+		} catch (SQInteger e) {
+			return e;
+		}
+	}
+
 } // namespace SQConvert
 
 #endif /* SQUIRREL_HELPER_HPP */