void LuaScriptInstance::HandleFixedUpdate(StringHash eventType, VariantMap& eventData) { using namespace PhysicsPreStep; float timeStep = eventData[P_TIMESTEP].GetFloat(); WeakPtr<LuaFunction> function = scriptObjectMethods_[LSOM_FIXEDUPDATE]; if (function && function->BeginCall(this)) { function->PushFloat(timeStep); function->EndCall(); } }
void LuaScriptInstance::SetScriptNetworkDataAttr(PODVector<unsigned char> data) { if (scriptObjectRef_ == LUA_REFNIL) return; WeakPtr<LuaFunction> function = scriptObjectMethods_[LSOM_READNETWORKUPDATE]; if (function && function->BeginCall(this)) { MemoryBuffer buf(data); function->PushUserType((Deserializer&)buf, "Deserializer"); function->EndCall(); } }
void LuaScript::HandleEvent(StringHash eventType, VariantMap& eventData) { LuaFunctionVector& functions = eventHandleFunctions_[eventType]; for (unsigned i = 0; i < functions.Size(); ++i) { WeakPtr<LuaFunction> function = functions[i]; if (function && function->BeginCall()) { function->PushUserType(eventType, "StringHash"); function->PushUserType(eventData, "VariantMap"); function->EndCall(); } } }
void LuaScriptInstance::OnMarkedDirty(Node* node) { // Script functions are not safe from worker threads Scene* scene = GetScene(); if (scene && scene->IsThreadedUpdate()) { scene->DelayedMarkedDirty(this); return; } WeakPtr<LuaFunction> function = scriptObjectMethods_[LSOM_TRANSFORMCHANGED]; if (function && function->BeginCall(this)) { function->EndCall(); } }
PODVector<unsigned char> LuaScriptInstance::GetScriptNetworkDataAttr() const { if (scriptObjectRef_ == LUA_REFNIL) return PODVector<unsigned char>(); VectorBuffer buf; WeakPtr<LuaFunction> function = scriptObjectMethods_[LSOM_WRITENETWORKUPDATE]; if (function && function->BeginCall(this)) { function->PushUserType((Serializer&)buf, "Serializer"); function->EndCall(); } return buf.GetBuffer(); }
void LuaScriptInstance::ReleaseObject() { if (scriptObjectRef_ == LUA_REFNIL) return; if (IsEnabledEffective()) UnsubscribeFromScriptMethodEvents(); // Unref script object luaL_unref(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_); scriptObjectRef_ = LUA_REFNIL; WeakPtr<LuaFunction> function = luaScript_->GetFunction("DestroyScriptObjectInstance"); if (function && function->BeginCall()) { function->PushUserType((void*)this, "LuaScriptInstance"); function->EndCall(); } }
void LuaScriptInstance::SetScriptObjectType(const String& scriptObjectType) { if (scriptObjectType_ == scriptObjectType) return; ReleaseObject(); WeakPtr<LuaFunction> function = luaScript_->GetFunction("CreateScriptObjectInstance"); if (!function || !function->BeginCall()) return; function->PushLuaTable(scriptObjectType); function->PushUserType((void*)this, "LuaScriptInstance"); if (!function->EndCall(1)) return; scriptObjectType_ = scriptObjectType; scriptObjectRef_ = luaL_ref(luaState_, LUA_REGISTRYINDEX); // Find script object method refs FindScriptObjectMethodRefs(); }
void LuaScriptInstance::OnSetAttribute(const AttributeInfo& attr, const Variant& src) { if (attr.ptr_ != (void*)0xffffffff) { Serializable::OnSetAttribute(attr, src); return; } if (scriptObjectRef_ == LUA_REFNIL) return; String name = attr.name_; unsigned length = name.Length(); if (name.Back() == '_') length -= 1; int top = lua_gettop(luaState_); String functionName = String("Set") + name.Substring(0, 1).ToUpper() + name.Substring(1, length - 1); WeakPtr<LuaFunction> function = GetScriptObjectFunction(functionName); // If set function exist if (function) { if (function->BeginCall(this)) { function->PushVariant(src); function->EndCall(); } } else { lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_); lua_pushstring(luaState_, name.CString()); switch (attr.type_) { case VAR_BOOL: lua_pushboolean(luaState_, src.GetBool()); break; case VAR_FLOAT: lua_pushnumber(luaState_, src.GetFloat()); break; case VAR_STRING: tolua_pushurho3dstring(luaState_, src.GetString()); break; case VAR_VECTOR2: { Vector2* value = new Vector2(src.GetVector2()); tolua_pushusertype(luaState_, value, "Vector2"); tolua_register_gc(luaState_, lua_gettop(luaState_)); } break; case VAR_VECTOR3: { Vector3* value = new Vector3(src.GetVector3()); tolua_pushusertype(luaState_, value, "Vector3"); tolua_register_gc(luaState_, lua_gettop(luaState_)); } break; case VAR_VECTOR4: { Vector4* value = new Vector4(src.GetVector4()); tolua_pushusertype(luaState_, value, "Vector4"); tolua_register_gc(luaState_, lua_gettop(luaState_)); } break; case VAR_QUATERNION: { Quaternion* value = new Quaternion(src.GetQuaternion()); tolua_pushusertype(luaState_, value, "Quaternion"); tolua_register_gc(luaState_, lua_gettop(luaState_)); } break; case VAR_COLOR: { Color* value = new Color(src.GetColor()); tolua_pushusertype(luaState_, value, "Color"); tolua_register_gc(luaState_, lua_gettop(luaState_)); } break; case VAR_INTRECT: { IntRect* value = new IntRect(src.GetIntRect()); tolua_pushusertype(luaState_, value, "IntRect"); tolua_register_gc(luaState_, lua_gettop(luaState_)); } break; case VAR_INTVECTOR2: { IntVector2* value = new IntVector2(src.GetIntVector2()); tolua_pushusertype(luaState_, value, "IntVector2"); tolua_register_gc(luaState_, lua_gettop(luaState_)); } break; default: LOGERROR("Unsupported data type"); lua_settop(luaState_, top); return; } lua_settable(luaState_, -3); } lua_settop(luaState_, top); }
void LuaScriptInstance::OnGetAttribute(const AttributeInfo& attr, Variant& dest) const { if (attr.ptr_ != (void*)0xffffffff) { Serializable::OnGetAttribute(attr, dest); return; } if (scriptObjectRef_ == LUA_REFNIL) return; String name = attr.name_; unsigned length = name.Length(); if (name.Back() == '_') length -= 1; int top = lua_gettop(luaState_); String functionName = String("Get") + name.Substring(0, 1).ToUpper() + name.Substring(1, length - 1); WeakPtr<LuaFunction> function = GetScriptObjectFunction(functionName); // If get function exist if (function) { if (function->BeginCall(this)) function->EndCall(1); } else { lua_rawgeti(luaState_, LUA_REGISTRYINDEX, scriptObjectRef_); lua_pushstring(luaState_, name.CString()); lua_gettable(luaState_, -2); } switch (attr.type_) { case VAR_BOOL: dest = lua_toboolean(luaState_, -1) != 0; break; case VAR_FLOAT: dest = (float)lua_tonumber(luaState_, -1); break; case VAR_STRING: dest = tolua_tourho3dstring(luaState_, -1, ""); break; case VAR_VECTOR2: dest = *((Vector2*)tolua_tousertype(luaState_, -1, 0)); break; case VAR_VECTOR3: dest = *((Vector3*)tolua_tousertype(luaState_, -1, 0)); break; case VAR_VECTOR4: dest = *((Vector4*)tolua_tousertype(luaState_, -1, 0)); break; case VAR_QUATERNION: dest = *((Quaternion*)tolua_tousertype(luaState_, -1, 0)); break; case VAR_COLOR: dest = *((Color*)tolua_tousertype(luaState_, -1, 0)); break; case VAR_INTRECT: dest = *((IntRect*)tolua_tousertype(luaState_, -1, 0)); break; case VAR_INTVECTOR2: dest = *((IntVector2*)tolua_tousertype(luaState_, -1, 0)); break; default: LOGERROR("Unsupported data type"); return; } lua_settop(luaState_, top); }
void LuaIntegration::CreateScene() { ResourceCache* cache = GetSubsystem<ResourceCache>(); scene_ = new Scene(context_); // Create the Octree component to the scene so that drawable objects can be rendered. Use default volume // (-1000, -1000, -1000) to (1000, 1000, 1000) scene_->CreateComponent<Octree>(); // Create a Zone component into a child scene node. The Zone controls ambient lighting and fog settings. Like the Octree, // it also defines its volume with a bounding box, but can be rotated (so it does not need to be aligned to the world X, Y // and Z axes.) Drawable objects "pick up" the zone they belong to and use it when rendering; several zones can exist Node* zoneNode = scene_->CreateChild("Zone"); Zone* zone = zoneNode->CreateComponent<Zone>(); // Set same volume as the Octree, set a close bluish fog and some ambient light zone->SetBoundingBox(BoundingBox(-1000.0f, 1000.0f)); zone->SetAmbientColor(Color(0.05f, 0.1f, 0.15f)); zone->SetFogColor(Color(0.1f, 0.2f, 0.3f)); zone->SetFogStart(10.0f); zone->SetFogEnd(100.0f); LuaFile* scriptFile = cache->GetResource<LuaFile>("LuaScripts/Rotator.lua"); if (!scriptFile) return; // Create randomly positioned and oriented box StaticModels in the scene const unsigned NUM_OBJECTS = 2000; for (unsigned i = 0; i < NUM_OBJECTS; ++i) { Node* boxNode = scene_->CreateChild("Box"); boxNode->SetPosition(Vector3(Random(200.0f) - 100.0f, Random(200.0f) - 100.0f, Random(200.0f) - 100.0f)); // Orient using random pitch, yaw and roll Euler angles boxNode->SetRotation(Quaternion(Random(360.0f), Random(360.0f), Random(360.0f))); StaticModel* boxObject = boxNode->CreateComponent<StaticModel>(); boxObject->SetModel(cache->GetResource<Model>("Models/Box.mdl")); boxObject->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml")); // Add our custom Rotator script object (using the LuaScriptInstance C++ component to instantiate / store it) which will // rotate the scene node each frame, when the scene sends its update event LuaScriptInstance* instance = boxNode->CreateComponent<LuaScriptInstance>(); instance->CreateObject(scriptFile, "Rotator"); // Call the script object's "SetRotationSpeed" function. WeakPtr<LuaFunction> function = instance->GetScriptObjectFunction("SetRotationSpeed"); if (function && function->BeginCall(instance)) { function->PushUserType(Vector3(10.0f, 20.0f, 30.0f), "Vector3"); function->EndCall(); } } // Create the camera. Let the starting position be at the world origin. As the fog limits maximum visible distance, we can // bring the far clip plane closer for more effective culling of distant objects cameraNode_ = scene_->CreateChild("Camera"); Camera* camera = cameraNode_->CreateComponent<Camera>(); camera->SetFarClip(100.0f); // Create a point light to the camera scene node Light* light = cameraNode_->CreateComponent<Light>(); light->SetLightType(LIGHT_POINT); light->SetRange(30.0f); }
bool LuaScript::ExecuteFunction(const String& functionName) { WeakPtr<LuaFunction> function = GetFunction(functionName); return function && function->BeginCall() && function->EndCall(); }