#include "CComponent.h" #include "U_Scripting.h" #include "CScriptingManager.h" #include "CEngine.h" #include "U_Log.h" const std::type_info& CComponent::GetTypeInfo() const { return typeid(CComponent); } template static std::function GetOutTransformer() { return [](const sol::function& func, CComponent* comp) -> Ret { sol::table comp_table = comp->GetScriptTable(func.lua_state()); if constexpr (std::is_void_v) { SafeCallLua(func, comp_table); //func(comp_table); } else { sol::object ret = SafeCallLuaReturn(func, comp_table); return ret.valid() ? ret.as() : false; } }; } template static std::function*, sol::variadic_args)> GetInTransformer() { return [](CFunctionBase* func, sol::variadic_args va) -> sol::object { if(va.size() < 1) { return sol::make_object(va.lua_state(), 1); } auto arg = va.get(0); if(!arg.valid()) { return sol::make_object(va.lua_state(), 2); } sol::state_view state(va.lua_state()); CComponent* component = nullptr; CEngine::GetInstance()->Components.Trace([&component, &state, &arg](CComponent* comp) { sol::table tabl = comp->GetScriptTable(state); if(tabl == arg) { component = comp; } }); if(!component) { return sol::make_object(va.lua_state(), 3); } sol::object ret = sol::lua_nil; if constexpr (!std::is_void_v) { ret = sol::make_object(va.lua_state(), func->Call(component)); } else { func->Call(component); } return ret; }; } CComponent::CComponent() { OnInit.SetupLuaTransformers(GetOutTransformer(), GetInTransformer()); OnUpdate.SetupLuaTransformers(GetOutTransformer(), GetInTransformer()); OnPostInit.SetupLuaTransformers(GetOutTransformer(), GetInTransformer()); OnDestruct.SetupLuaTransformers(GetOutTransformer(), GetInTransformer()); OnDeInit.SetupLuaTransformers(GetOutTransformer(), GetInTransformer()); } bool CComponent::V_BaseScriptInit(std::shared_ptr _state, sol::table _table) { static std::vector Priorities = { "default", "indexed", "first", "last", "after" }; if(_state->get("priority") == sol::lua_nil) { sol::table priority = _state->create_named_table("priority"); size_t index = 0; for(auto& pr : Priorities) { priority.set(pr, index); index++; } } _table.set_function("setPriority", [this](int _type, sol::variadic_args va) { if(_type < 0 || _type >= Priorities.size()) { return; } std::string type = Priorities.at(_type); if(type == "default") { SetPriority(std::make_unique()); } else if(type == "indexed") { if(va.size() == 0) { return; } if(va.get_type(0) != sol::type::number) { return; } int index = va.get(0); SetPriority(std::make_unique(index)); } else if(type == "first") { SetPriority(std::make_unique()); } else if(type == "last") { SetPriority(std::make_unique()); } else if(type == "after") { std::vector afterComps; for(auto arg : va) { if(arg.get_type() != sol::type::string) { continue; } afterComps.push_back(arg.get()); } if(!afterComps.empty()) { SetPriority(std::make_unique(afterComps)); } } }); _table.set_function("init", [this]() { Init(); }); _table.set_function("postinit", [this]() { PostInit(); }); _table.set_function("update", [this]() { Update(); }); auto fieldsMan_pair = CScriptFieldsManager::ValidateFieldsManager(_table); auto fieldsMan = fieldsMan_pair.first; fieldsMan->AddField("type", std::make_unique([this](sol::state_view ts) -> sol::object { return sol::make_object(ts, this->GetType()); })); fieldsMan->AddField("oninit", std::make_unique([this](sol::state_view ts) -> sol::object { return OnInit.GetScriptTable(ts); })); fieldsMan->AddField("onpostinit", std::make_unique([this](sol::state_view ts) -> sol::object { return OnPostInit.GetScriptTable(ts); })); fieldsMan->AddField("onupdate", std::make_unique([this](sol::state_view ts) -> sol::object { return OnUpdate.GetScriptTable(ts); })); fieldsMan->AddField("ondestruct", std::make_unique([this](sol::state_view ts) -> sol::object { return OnDestruct.GetScriptTable(ts); })); fieldsMan->AddField("ondeinit", std::make_unique([this](sol::state_view ts) -> sol::object { return OnDeInit.GetScriptTable(ts); })); fieldsMan->FieldCreationAbility = true; if(!fieldsMan_pair.second) { fieldsMan->CreateMetaTable(_table); } return true; } CComponent::~CComponent() { OnDestruct(this); } std::string CComponent::GetType() const { return {}; } bool CComponent::V_Init() { return true; } void CComponent::V_Update() {} void CComponent::V_PostInit() {} void CComponent::V_DeInit() {} bool CComponent::Init() { bool res = V_Init(); auto results = OnInit.CallWithReturns(this); CEngine::GetInstance()->Components.OnComponentInit(GetType()); auto man = CEngine::GetInstance()->Components.GetComponentTyped(); if(man) { man->CallHook(GetType() + "_init"); } return (res && (std::find(results.begin(), results.end(), false) == results.end())); } void CComponent::PostInit() { V_PostInit(); OnPostInit(this); CEngine::GetInstance()->Components.OnComponentPostInit(GetType()); auto man = CEngine::GetInstance()->Components.GetComponentTyped(); if(man) { man->CallHook(GetType() + "_postinit"); } } void CComponent::Update() { V_Update(); OnUpdate(this); } void CComponent::DeInit() { V_DeInit(); OnDeInit(this); } void CComponent::SetPriority(std::unique_ptr priority) { Priority = std::move(priority); } void CComponent::ResetPriority() { Priority.reset(); } CComponentPriority* CComponent::GetPriority() const { return Priority.get(); }