Scripting mit AngelScript

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2636
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Scripting mit AngelScript

Beitrag von Jonathan »

NytroX hat geschrieben: 06.03.2025, 21:29 Ich hab das hier gefunden:
https://gist.github.com/MartinBspheroid/10103958

Kannst du da nicht einfach selbst was schreiben? Sieht für mich erstmal nicht so kompliziert aus...
Das scheint halt das uralte Binding von diesem Anthony zu sein, was vor 15 Jahren mal als Test-Code inoffiziell Teil von AngelScript war (wie in dem einen Forum-Thread erwähnt). In den aktuellen Download fehlt davon jede Spur, es ist auch eine neue Major-Version, ich nehme an, dass das Ding lang überholt ist und vermutlich nicht mehr funktioniert.

Selber schreiben sollte in der Tat gehen, nur muss man dafür vermutlich viel über die internen Dinge von AS lesen um es richtig zu machen. Und in der offziellen Doku gibts halt kein einziges Beispiel dazu, das ist alles sehr dürftig.
Schrompf hat geschrieben: 06.03.2025, 23:23 Ich hab hier ein angelscript/add_on/scriptarray/scriptarray.cpp
Keine Ahnung, woher das Ding stammt, aber es meldet ein Template an, was zwar array heißt, aber auch push_back(), insert(), find(), resize() und so kann. Ist aber ein Wrapper für einen eigenen Array-Typ, und ich glaube, wir haben das nie benutzt.

Die paar Mal, wo ich wirklich ein nacktes Array haben wollte, hab ich dann domainspezifische Getter geschrieben: FindeAlleMonsterIn() und dann GetAnzahlGefundeneMonster() und GetGefundenesMonster(int x). Damit haben wir um das Problem drumrum gebaut, stimmt schon, aber irgendwie war's nie so oft und so problematisch, dass ich jemals wirklich gelitten hätte.
Das ist dieses offizelle CScriptArray, das ich oben schonmal erwähnt hab. Wie es scheint, muss ich damit bei jeder Schnittstelle zwischen C++ und AS einen Container umkopieren, aber das ist schon ok, da ich es nicht so oft brauche. Ich werde das jetzt so erstmal umsetzen.

An die andere Lösung (GetGefundenesMonster) hatte ich auch schon mal kurz gedacht, aber dafür muss man dann auf C++ Seite zu viel vorhalten. Mal schauen.

Aber danke an euch beide für die Unterstützung. Ich setz mich mal dran und poste Updates.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Jonathan
Establishment
Beiträge: 2636
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Scripting mit AngelScript

Beitrag von Jonathan »

Es läuft jetzt für meine Zwecke :)

AngelScript hat ein bisschen extra Syntax mit templates und so, so dass man dann ein "array<int>" haben kann. Letztendlich kann man das aber einfacher haben, indem man einfach seine eigene Klasse registriert und den IndexOperator "array[ i ]" anmeldet. Mir ist dann etwas später aufgefallen, dass der Link von NytroX genau das macht (die Klasse heißt dann einfach "vector_int", was Namenskonflikte vermeidet).

Die nächste Frage betraf das Memory-Management. Referenzen sind am einfachsten, aber dann muss der Host (die C++ Seite) sich um Speicherverwaltung kümmern. Ich will aber sowas haben:

Code: Alles auswählen

std::vector<ComponentBuilding*> City::GetAllBuildings()
{
	std::vector<ComponentBuilding*> result;

	for(auto& entity : m_Game.GetSceneManager().GetAllEntities())
	{
		ComponentBuilding *c = entity->GetComponent<ComponentBuilding>();
		if(c)
		{
			result.push_back(c);
		}
	}

	return result;
}
D.h., ich brauche den Vektor als Value, sonst müsste der nach Skript-Aufruf manuell zerstört werden. AngelScript kann zwar auch irgendwie GarbageCollection, aber das will ich mir gerade nicht angucken :D

Glücklicherweise verwendete der Beispielschnipsel aber auch genau Value-Types. Man muss dann nur ein paar Funktionen (CTor, DTor, usw.) für AS registrieren. Am Ende brauchte ich nur eine Anpassung, um Referenztypen zu unterstützen:

Code: Alles auswählen

	std::string V_AS = string("vector_") + T_AS;
	if(V_AS.ends_with("@")) // for reference types, the @ should not be part of the name (vector_obj instead of vector_obj@)
		V_AS.pop_back();
(ohne weitere Erklärung, das macht aber sofort Sinn wenn man selber versucht es zu verwenden und ich poste es als Referenz).

Und damit kann ich jetzt oben gezeigt Funktion bequem registrieren:

Code: Alles auswählen

RegisterVector<ComponentBuilding*>("Building@", m_Engine);
m_Engine->RegisterGlobalFunction("vector_Building get_all_buildings(string type)", asMETHOD(City,  GetAllBuildings), asCALL_THISCALL_ASGLOBAL, &city);
und im Skript verwenden:

Code: Alles auswählen

vector_Building buildings = get_all_buildings("");
add_message("Number of buildings: "+buildings.size(), 10.f);
for( int i = 0; i<buildings.size(); ++i)
{
    add_message(buildings[i].get_type(), 3.f);
}
Ich bin derzeit sehr zufrieden mit der Lösung. Man musste schon erst einiges lesen und verstehen, aber dann war es eigentlich gar nicht so viel Arbeit. Und es ist genau das, was ich haben wollte und noch mehr (denn ich müsste jetzt vectoren auch auf Skriptseite erzeugen und zurück geben können, usw.). Ein gutes Ergebnis also!
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Antworten