Skip to content

Commit

Permalink
👼 Script: added SE_ANGELSCRIPT_LINECALLBACK for extra diag.
Browse files Browse the repository at this point in the history
    * LineCallback = Optional callback which receives diagnostic info for every executed statement.
    * https://www.angelcode.com/angelscript/sdk/docs/manual/classas_i_script_context.html#lineCallback
    * see included 'example_angelscript_linecallback.as'
  • Loading branch information
ohlidalp committed Jul 25, 2023
1 parent 1755f6f commit 7a4df24
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 2 deletions.
62 changes: 62 additions & 0 deletions resources/scripts/example_angelscript_linecallback.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// TEST SCRIPT - angelscript linecallback (tracks executed lines)
// ===================================================

// GUI (intentionally at the top to have fewer lines in the output):
void frameStep(float dt)
{
ImGui::TextDisabled("Frames:"+framecounter+", Samples: "+totalSamples+"(per frame :"+linenumsLite.length()+')');
ImGui::Text("[Line] Total");

for (uint i=0; i<lineHitsAggregatedLite.length(); i++) {
float y = ImGui::GetCursorPosY();
ImGui::TextDisabled("[ "+formatInt(i+1, "0", 2)+" ]");
ImGui::SameLine(); ImGui::Text(""+formatInt(lineHitsAggregatedLite[i], '0', 4));
// manual linebreak, to align with the editor window
ImGui::SetCursorPosY(y + ImGui::GetTextLineHeight());
}
framecounter++;
}

//CONTEXT:
int lowestLinenum = 999999;
int highestLinenum = 0;
int totalSamples = 0;
array<int> linenumsLite;
array<int> lineHitsAggregatedLite;
int framecounter = 0;

// SETUP:
void main(){
// this automagically attaches the LineCallback to angelscript.
game.registerForEvent(SE_ANGELSCRIPT_LINECALLBACK);
}

// EVENT HANDLING:
void eventCallbackEx(scriptEvents ev, int a1, int a2, int a3, int a4, string a5, string a6, string a7, string a8)
{
if (ev == SE_ANGELSCRIPT_LINECALLBACK) { addSample(a2); }
}

// HELPERS:
void addSample(int a2)
{
if (a2 < lowestLinenum) { lowestLinenum=a2; }
else if (a2 > highestLinenum) { highestLinenum = a2; }
// detect repeating
if (a2 < highestLinenum && a2 == lowestLinenum) { aggregateLineHitsLite(); }
linenumsLite.insertLast(a2);
totalSamples++;
}

void aggregateLineHitsLite()
{
// allocate
lineHitsAggregatedLite.resize(highestLinenum+1);

// aggregate
for (uint i=0; i<linenumsLite.length(); i++) {
lineHitsAggregatedLite[linenumsLite[i]] ++;
}
// reset
linenumsLite.resize(0); // clear all
}
5 changes: 3 additions & 2 deletions source/main/gameplay/ScriptEvents.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ enum scriptEvents

SE_ANGELSCRIPT_MANIPULATIONS = BITMASK(18), //!< triggered when the user tries to dynamically use the scripting capabilities (prevent cheating) args: #1 angelScriptManipulationType, #2 ScriptUnitId_t, #3 RoR::ScriptCategory, #4 unused, #5 filename
SE_ANGELSCRIPT_MSGCALLBACK = BITMASK(19), //!< The diagnostic info directly from AngelScript engine (see `asSMessageInfo`), args: #1 ScriptUnitID, #2 asEMsgType, #3 row, #4 col, #5 sectionName, #6 message
SE_ANGELSCRIPT_THREAD_STATUS = BITMASK(20), //!< Sent by background threads (i.e. CURL) when there's something important (like finishing a download). args: #1 type, see `RoR::angelScriptThreadStatus`.
SE_ANGELSCRIPT_LINECALLBACK = BITMASK(20), //!< The diagnostic info directly from AngelScript engine (see `SetLineCallback()`), args: #1 ScriptUnitID, #2 LineNumber, #3 CallstackSize, #4 unused, #5 FunctionName, #6 FunctionObjectTypeName #7 ObjectName
SE_ANGELSCRIPT_THREAD_STATUS = BITMASK(21), //!< Sent by background threads (i.e. CURL) when there's something important (like finishing a download). args: #1 type, see `RoR::angelScriptThreadStatus`.

SE_GENERIC_MESSAGEBOX_CLICK = BITMASK(21), //!< triggered when the user clicks on a message box button, the argument refers to the button pressed
SE_GENERIC_MESSAGEBOX_CLICK = BITMASK(22), //!< triggered when the user clicks on a message box button, the argument refers to the button pressed

SE_ALL_EVENTS = 0xffffffff,

Expand Down
27 changes: 27 additions & 0 deletions source/main/scripting/ScriptEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,26 @@ void ScriptEngine::msgCallback(const AngelScript::asSMessageInfo *msg)
msg->section, msg->message); // strings
}

std::string ptr2str(const char* ptr) { if (ptr) return ptr; else return ""; }

void ScriptEngine::lineCallback(AngelScript::asIScriptContext* ctx)
{
std::string funcName, funcObjTypeName, objName;
if (ctx->GetFunction())
{
funcName = ptr2str(ctx->GetFunction()->GetName());
objName = ptr2str(ctx->GetFunction()->GetObjectName());
if (ctx->GetFunction()->GetObjectType())
funcObjTypeName = ptr2str(ctx->GetFunction()->GetObjectType()->GetName());
}
TRIGGER_EVENT_ASYNC(SE_ANGELSCRIPT_LINECALLBACK,
// ints
m_currently_executing_script_unit, ctx->GetLineNumber(), ctx->GetCallstackSize(), 0,
// strings
funcName, funcObjTypeName, objName
);
}

int ScriptEngine::framestep(Real dt)
{
// Check if we need to execute any strings
Expand All @@ -221,6 +241,10 @@ int ScriptEngine::framestep(Real dt)

context->Prepare(m_script_units[id].frameStepFunctionPtr);

// Automatically attach the LineCallback if the script registered for the event.
if (m_script_units[id].eventMask & SE_ANGELSCRIPT_LINECALLBACK)
context->SetLineCallback(asMETHOD(ScriptEngine, lineCallback), this, asCALL_THISCALL);

// Set the function arguments
context->SetArgFloat(0, dt);

Expand All @@ -232,6 +256,9 @@ int ScriptEngine::framestep(Real dt)
// The return value is only valid if the execution finished successfully
AngelScript::asDWORD ret = context->GetReturnDWord();
}

// Clear the line callback so it doesn't intercept game callbacks (causes infinite loop).
context->ClearLineCallback();
}
return 0;
}
Expand Down
6 changes: 6 additions & 0 deletions source/main/scripting/ScriptEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,12 @@ class ScriptEngine : public Ogre::LogListener
*/
void msgCallback(const AngelScript::asSMessageInfo* msg);

/**
* Optional callback which receives diagnostic info for every executed statement.
* https://www.angelcode.com/angelscript/sdk/docs/manual/classas_i_script_context.html#ae2747f643bf9a07364f922c460ef57dd
*/
void lineCallback(AngelScript::asIScriptContext* ctx);

Ogre::String composeModuleName(Ogre::String const& scriptName, ScriptCategory origin, ScriptUnitId_t id);

/**
Expand Down
1 change: 1 addition & 0 deletions source/main/scripting/bindings/ScriptEventsAngelscript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ void RoR::RegisterScriptEvents(asIScriptEngine *engine)

result = engine->RegisterEnumValue("scriptEvents", "SE_ANGELSCRIPT_MANIPULATIONS", SE_ANGELSCRIPT_MANIPULATIONS); ROR_ASSERT(result>=0);
result = engine->RegisterEnumValue("scriptEvents", "SE_ANGELSCRIPT_MSGCALLBACK", SE_ANGELSCRIPT_MSGCALLBACK); ROR_ASSERT(result>=0);
result = engine->RegisterEnumValue("scriptEvents", "SE_ANGELSCRIPT_LINECALLBACK", SE_ANGELSCRIPT_LINECALLBACK); ROR_ASSERT(result>=0);
result = engine->RegisterEnumValue("scriptEvents", "SE_ANGELSCRIPT_THREAD_STATUS", SE_ANGELSCRIPT_THREAD_STATUS); ROR_ASSERT(result>=0);

result = engine->RegisterEnumValue("scriptEvents", "SE_GENERIC_MESSAGEBOX_CLICK", SE_GENERIC_MESSAGEBOX_CLICK); ROR_ASSERT(result>=0);
Expand Down

0 comments on commit 7a4df24

Please sign in to comment.