/** GDevelop - Function Extension Copyright (c) 2008-2016 Florian Rival (Florian.Rival@gmail.com) This project is released under the MIT License. */ #include "GDCpp/Extensions/ExtensionBase.h" #include "GDCore/Events/CodeGeneration/ExpressionsCodeGeneration.h" #include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h" #include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h" #include "GDCore/Events/Tools/EventsCodeNameMangler.h" #include "GDCpp/Extensions/CppPlatform.h" #include "GDCpp/Runtime/Project/Project.h" #include "GDCpp/Runtime/Project/Layout.h" #include "GDCpp/Runtime/CommonTools.h" #if defined(GD_IDE_ONLY) #include "GDCore/Events/Parsers/ExpressionParser.h" #include "GDCore/Events/Instruction.h" #endif #include "FunctionEvent.h" /** * \brief This class declares information about the extension. */ class Extension : public ExtensionBase { public: /** * Constructor of an extension declares everything the extension contains: objects, actions, conditions and expressions. */ Extension() { SetExtensionInformation("Function", _("Function events"), _("This Extension allows you to use events that behave like functions."), "Florian Rival", "Open source (MIT License)"); #if defined(GD_IDE_ONLY) AddAction("LaunchFunction", _("Launch a function"), _("Launch a function"), _("Launch _PARAM0_ (_PARAM1_, _PARAM2_, _PARAM3_, _PARAM4_, _PARAM5_, _PARAM6_, _PARAM7_)"), _("Functions"), "res/actions/function24.png", "res/actions/function.png") .AddParameter("", _("Name of the function")) .AddParameter("string", _("Parameter 1"), "", true) .AddParameter("string", _("Parameter 2"), "", true) .AddParameter("string", _("Parameter 3"), "", true) .AddParameter("string", _("Parameter 4"), "", true) .AddParameter("string", _("Parameter 5"), "", true) .AddParameter("string", _("Parameter 6"), "", true) .AddParameter("string", _("Parameter 7"), "", true) .codeExtraInformation.SetCustomCodeGenerator([](gd::Instruction & instruction, gd::EventsCodeGenerator & codeGenerator, gd::EventsCodeGenerationContext & context) { gd::String functionName = instruction.GetParameter(0).GetPlainString(); const gd::Project & project = codeGenerator.GetProject(); const gd::Layout & layout = codeGenerator.GetLayout(); const FunctionEvent * functionEvent = FunctionEvent::SearchForFunctionInEvents(project, layout.GetEvents(), functionName); if ( !functionEvent ) { std::cout << "Function \""+functionName+"\" not found!" << std::endl; return "//Function \""+functionName+"\" not found.\n"; } codeGenerator.AddGlobalDeclaration("void "+FunctionEvent::MangleFunctionName(layout, *functionEvent)+"(RuntimeContext *, std::map *>, std::vector &);\n"); gd::String code; //Generate code for objects passed as arguments gd::String objectsAsArgumentCode; { objectsAsArgumentCode += "runtimeContext->ClearObjectListsMap()"; std::vector realObjects = codeGenerator.ExpandObjectsName(functionEvent->GetObjectsPassedAsArgument(), context); for (std::size_t i = 0;i()) .SetCodeGenerator([](gd::BaseEvent & event_, gd::EventsCodeGenerator & codeGenerator, gd::EventsCodeGenerationContext & /* The function has nothing to do with the current context */){ FunctionEvent & event = dynamic_cast(event_); const gd::Layout & layout = codeGenerator.GetLayout(); //Declaring function prototype. codeGenerator.AddGlobalDeclaration("void "+FunctionEvent::MangleFunctionName(layout, event)+"(RuntimeContext *, std::map *>, std::vector &);\n"); //Generating function code: gd::String functionCode; functionCode += "\nvoid "+FunctionEvent::MangleFunctionName(layout, event)+"(RuntimeContext * runtimeContext, std::map *> objectsListsMap, std::vector & currentFunctionParameters)\n{\n"; gd::EventsCodeGenerationContext callerContext; { std::vector realObjects = codeGenerator.ExpandObjectsName(event.GetObjectsPassedAsArgument(), callerContext); for (std::size_t i = 0;i & parameters, gd::EventsCodeGenerator & codeGenerator, gd::EventsCodeGenerationContext & context) { codeGenerator.AddIncludeFile("Function/FunctionTools.h"); const gd::Project & game = codeGenerator.GetProject(); const gd::Layout & scene = codeGenerator.GetLayout(); //Ensure currentFunctionParameters vector is always existing. gd::String mainFakeParameters = "std::vector currentFunctionParameters;\n"; if (codeGenerator.GetCustomCodeInMain().find(mainFakeParameters) == gd::String::npos) codeGenerator.AddCustomCodeInMain(mainFakeParameters); //Generate code for evaluating index gd::String expression; gd::CallbacksForGeneratingExpressionCode callbacks(expression, codeGenerator, context); gd::ExpressionParser parser(parameters[0].GetPlainString()); if (!parser.ParseMathExpression(codeGenerator.GetPlatform(), game, scene, callbacks) || expression.empty()) expression = "0"; gd::String code; code += "GDpriv::FunctionTools::GetSafelyStringFromVector(currentFunctionParameters, "+expression+")"; return code; }); #endif GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION(); }; }; /** * Used by GDevelop to create the extension class * -- Do not need to be modified. -- */ extern "C" ExtensionBase * GD_EXTENSION_API CreateGDExtension() { return new Extension; }