-
Notifications
You must be signed in to change notification settings - Fork 7
Script
I. Moduły
- Nowy moduł.
class NewModule : public Module<..., Script>
{
// ...
public:
// ...
NewModule() {
LOG_INFO(this, "NewModule constructed");
initScript(); // <<<< inicjacja modułu do skryptu
}
// ...
// Jeżeli do modułu NewModule należą klasy ClassA, ClassB i ClassC
// to metoda initScript będzie wyglądać następująco
void initScript() {
using namespace new_module; // <<<< o ile takowy namespace istnieje
Script& script = getModule<Script>();
auto module = script.newModule("NewModule"); // <<<< Ta zmienna MUSI nazywać się "module"
/* Obszar dodawania funkcjonalności */
// np. (więcej o tym makro niżej)
SCRIPT_SET_MODULE(NewModule, getPos, setPos, getSize, setSize)
// Inicjacja klas modułu (zawierających metodę statyczną "initScript")
script.initClasses<ClassA, ClassB, ClassC>();
}
};
- Dostępne opcje dodawania funkcjonalności.
a) Makro SCRIPT_SET_MODULE
SCRIPT_SET_MODULE(NewModule, a, b, c, ...)
SCRIPT_SET_MODULE(NewModule, d, e)
// gdzie:
// a, b, c, d, e, ... - argumenty w postaci metod i TYLKO metod (max 16 na makro)
Tak naprawdę makro SCRIPT_SET_MODULE(NewModule, a, b, c)
wywołuje takie instrukcje:
module.set_function("a", &NewModule::a, this);
module.set_function("b", &NewModule::b, this);
module.set_function("c", &NewModule::c, this);
b) set_function (dla lambd)
module.set_function("functionName", [&](int a, int b){return a+b;});
- Przeciążanie nazw metod o różnych i takich samych nazwach.
Przykłady opracowane dla metod:
void M::setValue(int value);
void M::setValue(const string &value);
void M::setValueFromInt(int value));
void M::setValueFromString(const string &value);
Możliwe kombinacje:
// A
module.set_function("setValue", sol::overload(&M::setValueFromInt, &M::setValueFromString), this);
// B
module.set_function("setValue", sol::overload(sol::resolve<void(int)>(&M::setValue), &M::setValueFromString), this);
// C
module.set_function("setValue", sol::overload(sol::resolve<void(int)>(&M::setValue), sol::resolve<void(const string&)>(&M::setValue)), this);
II. Klasy
- Nowa klasa.
class NewClass
{
//...
public:
//...
static void initScript(Script& script) {
// 1. Zmienna poniżej MUSI nazywać się "object"
// 2. Trzeci argument jest nieobowiązkowy (jest to ścieżka do pliku, który ma się wykonać podczas inicjalizacji klasy)
auto object = script.newClass<NewClass>("NewClass", "NewModule", "../NewClass.lua");
/* Obszar dodawania funkcjonalności */
SCRIPT_SET_CLASS(NewClass, field_1, setField_1, getField_1, setField_2, getField_2, getField_3) // Podobnie jak wcześniej
// Makery (nieobowiązkowe)
object.makeInstance();
object.makeStatter();
// Inicjacja nowej klasy do skryptu
object.init();
}
};
- Dostępne opcje dodawania funkcjonalności.
a) Makro SCRIPT_SET_CLASS
SCRIPT_SET_CLASS(MyClass, a, setA, getA, setB)
SCRIPT_SET_CLASS(MyClass, getB, getC, ...)
// gdzie:
// a, setA, getA, setB, getB, getC, ... - składowe i metody MyClass (max 16 na makro)
Tak naprawdę makro SCRIPT_SET_CLASS(NewClass, a, b, c)
wywołuje takie instrukcje:
object.set("a", &NewClass::a);
object.set("b", &NewClass::b);
object.set("c", &NewClass::c);
b) Metoda set
Przykłady:
// A
object.set("size", &NewClass::size); // size musi być publiczne
// B
object.set("getSize", &NewClass::getSize); // nie ma znaczenia czy metoda coś zwraca
// C
object.set("createObject", &NewClass::createObject); // dla statycznych też działa
// D
object.set("hello", [](){std::cout<<"Hello world!";}); // lambdy również nie straszne
c) Metoda 'setProperty' Przykłady:
// A
object.setProperty("size", &NewClass::getSize, &NewClass::setSize) // args: name, getter, setter
// przykład użycia w skrypcie:
// obj.size = 5; print(obj.size); // UWAGA! Mimo, że wywołujemy metody nie używamy ':' tylko '.'
// B
object.setProperty("flag", [](NewClass &obj){return obj.flag;}, [](NewClass &obj, bool value){obj.setFlag(value);});
// przykład użycia w skrypcie:
// obj.flag = true; print(obj.flag);
// C
object.setProperty("flag", [](){}, [](NewClass &obj, bool value){obj.setFlag(value);});
// przykład użycia w skrypcie:
// obj.flag = true; // bez gettera
d) Metoda 'setOverload' Przykłady:
// A
object.setOverload("setType", &NewClass::setTypeFormInt, &NewClass::setTypeFormString, &NewClass::setTypeFormEnemy, ...)
// ... - możliwość podania nieskończonej liczby argumentów
// B
object.setOverload("set", &NewClass::set<int>, &NewClass::set<const string&>);
// Funkcje szablonowe też są możliwe do oskryptowania, ale należy zainicjować każdą z osobna
- Przeciążanie nazw metod o różnych i takich samych nazwach.
Przykłady opracowane dla metod:
void M::setValue(int value);
void M::setValue(const string &value);
void M::setValueFromInt(int value);
void M::setValueFromString(const string &value);
Możliwe kombinacje:
// A
object.set("setValue", sol::overload(&M::setValueFromInt, &M::setValueFromString), this);
// B
object.set("setValue", sol::overload(sol::resolve<void(int)>(&M::setValue), &M::setValueFromString), this);
// C
object.set("setValue", sol::overload(sol::resolve<void(int)>(&M::setValue), sol::resolve<void(const string&)>(&M::setValue)), this);
Rozwiązań wykorzystujących sol::resolve
można używać również w innych metodach np. setProperty, setOverload.
UWAGA! W setProperty
NIE WOLNO używać sol::overload
, property nie jest przeciążalne.
- Maker: Automatyczny
instance
Po dodaniu linijki object.makeInstance();
,
W skrypcie będzie możliwe stworzenie instancji danej klasy w taki sposób:
-- UWAGA! Wymagany konstruktor bezargumentowy.
local obj = Module.Class.instance()
Dodatkowo jeżeli (już bezpośrednio w skrypcie) stworzymy metodę _instance
wewnątrz naszej klasy
to wywoła się ona zawsze wraz z wywołaniem metody instance
.
- Maker: Automatyczny
stat
Po dodaniu linijkiobject.makeStatter();
, jeżeli w klasie istnieje specjalna metoda statycznasetStat
, możliwe będzie ustawienie wielu statusów jednocześnie (takie jakby "multi propreties").
Przykład:
// Metoda statyczna
void NewClass::setStat(sol::table stat) { // Tablice w lua przesyłamy przez "kopię" (w rzeczywistości to jest referencja)
if(stat["position"].valid()) setPosition(stat["position"][1], stat["position"][2]);
if(stat["size"].valid()) { size.x = stat["size"][1]; size.y = stat["size"][2]; }
if(stat["hp"].valid()) setHp(stat["hp"]);
}
Przykład użycia:
local obj = Module.Class.instance()
obj.stat = {
hp = 20; -- możliwa dowolna kolejność
position = {40, 70}
-- nie trzeba używać wszystkich możliwych statusów
}