|
|
@@ -1,563 +0,0 @@
|
|
|
-require "LuaScripts/Utilities/Network"
|
|
|
-
|
|
|
-local testScene
|
|
|
-local camera
|
|
|
-local cameraNode
|
|
|
-
|
|
|
-local yaw = 0
|
|
|
-local pitch = 0
|
|
|
-local drawDebug = 0
|
|
|
-
|
|
|
-function Start()
|
|
|
- if not engine:IsHeadless() then
|
|
|
- InitConsole()
|
|
|
- InitUI()
|
|
|
- else
|
|
|
- OpenConsoleWindow()
|
|
|
- end
|
|
|
-
|
|
|
- ParseNetworkArguments()
|
|
|
-
|
|
|
- InitScene()
|
|
|
-
|
|
|
- SubscribeToEvent("Update", "HandleUpdate")
|
|
|
- SubscribeToEvent("KeyDown", "HandleKeyDown")
|
|
|
- SubscribeToEvent("MouseMove", "HandleMouseMove")
|
|
|
- SubscribeToEvent("MouseButtonDown", "HandleMouseButtonDown")
|
|
|
- SubscribeToEvent("MouseButtonUp", "HandleMouseButtonUp")
|
|
|
- SubscribeToEvent("PostRenderUpdate", "HandlePostRenderUpdate")
|
|
|
- SubscribeToEvent("SpawnBox", "HandleSpawnBox")
|
|
|
- SubscribeToEvent("PhysicsCollision", "HandlePhysicsCollision")
|
|
|
-
|
|
|
- network:RegisterRemoteEvent("SpawnBox")
|
|
|
-
|
|
|
- if runServer then
|
|
|
- network:StartServer(serverPort)
|
|
|
- SubscribeToEvent("ClientConnected", "HandleClientConnected")
|
|
|
-
|
|
|
- -- Disable physics interpolation to ensure clients get sent physically correct transforms
|
|
|
- testScene:GetComponent("PhysicsWorld"):SetInterpolation(false)
|
|
|
- end
|
|
|
-
|
|
|
- if runClient then
|
|
|
- network:Connect(serverAddress, serverPort, testScene)
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-function Stop()
|
|
|
- testScene = nil
|
|
|
- camera = nil
|
|
|
- cameraNode = nil
|
|
|
-end
|
|
|
-
|
|
|
-function InitConsole()
|
|
|
- local uiStyle = cache:GetResource("XMLFile", "UI/DefaultStyle.xml")
|
|
|
-
|
|
|
- engine:CreateDebugHud()
|
|
|
- debugHud.defaultStyle = uiStyle
|
|
|
- debugHud.mode = DEBUGHUD_SHOW_ALL
|
|
|
-
|
|
|
- engine:CreateConsole()
|
|
|
- console.defaultStyle = uiStyle
|
|
|
-end
|
|
|
-
|
|
|
-function InitUI()
|
|
|
- local uiStyle = cache:GetResource("XMLFile", "UI/DefaultStyle.xml")
|
|
|
-
|
|
|
- local newCursor = Cursor:new()
|
|
|
- newCursor.styleAuto = uiStyle
|
|
|
- newCursor.position = IntVector2(graphics:GetWidth()/ 2, graphics:GetHeight() / 2)
|
|
|
- ui.cursor = newCursor
|
|
|
-
|
|
|
- if GetPlatform() == "Android" or GetPlatform() == "iOS" then
|
|
|
- ui.cursor.visible = false
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-function InitScene()
|
|
|
- testScene = Scene()
|
|
|
-
|
|
|
- -- Create the camera outside the scene so it is unaffected by scene load/save
|
|
|
- cameraNode = Node()
|
|
|
- camera = cameraNode:CreateComponent("Camera")
|
|
|
- cameraNode.position = Vector3(0, 2, 0)
|
|
|
-
|
|
|
- if not engine:IsHeadless() then
|
|
|
- renderer:SetViewport(0, Viewport:new(testScene, camera))
|
|
|
-
|
|
|
- -- Add bloom & FXAA effects to the renderpath. Clone the default renderpath so that we don't affect it
|
|
|
- -- local newRenderPathPtr = renderer:GetViewport(0):GetRenderPath():Clone()
|
|
|
- -- local newRenderPath = newRenderPathPtr:Get()
|
|
|
- local newRenderPath = renderer:GetViewport(0):GetRenderPath():Clone()
|
|
|
- newRenderPath:Append(cache:GetResource("XMLFile", "PostProcess/Bloom.xml"))
|
|
|
- newRenderPath:Append(cache:GetResource("XMLFile", "PostProcess/EdgeFilter.xml"))
|
|
|
- newRenderPath:SetEnabled("Bloom", false)
|
|
|
- newRenderPath:SetEnabled("EdgeFilter", false)
|
|
|
- renderer:GetViewport(0):SetRenderPath(newRenderPath)
|
|
|
- audio:SetListener(cameraNode:CreateComponent("SoundListener"))
|
|
|
- end
|
|
|
-
|
|
|
- if runClient then
|
|
|
- return
|
|
|
- end
|
|
|
-
|
|
|
- local world = testScene:CreateComponent("PhysicsWorld")
|
|
|
- testScene:CreateComponent("Octree")
|
|
|
- testScene:CreateComponent("DebugRenderer")
|
|
|
-
|
|
|
- local zoneNode = testScene:CreateChild("Zone")
|
|
|
- local zone = zoneNode:CreateComponent("Zone")
|
|
|
- zone.ambientColor = Color(0.15, 0.15, 0.15)
|
|
|
- zone.fogColor = Color(0.5, 0.5, 0.7)
|
|
|
- zone.fogStart = 100.0
|
|
|
- zone.fogEnd = 300.0
|
|
|
- zone.boundingBox = BoundingBox(-1000, 1000)
|
|
|
-
|
|
|
- if true then
|
|
|
- local lightNode = testScene:CreateChild("GlobalLight")
|
|
|
- lightNode.direction = Vector3(0.3, -0.5, 0.425)
|
|
|
-
|
|
|
- local light = lightNode:CreateComponent("Light")
|
|
|
- light.lightType = LIGHT_DIRECTIONAL
|
|
|
- light.castShadows = true
|
|
|
- light.shadowBias = BiasParameters(0.00025, 0.5)
|
|
|
- light.shadowCascade = CascadeParameters(10.0, 50.0, 200.0, 0.0, 0.8)
|
|
|
- light.specularIntensity = 0.5
|
|
|
- end
|
|
|
-
|
|
|
- if true then
|
|
|
- local objectNode = testScene:CreateChild("Floor")
|
|
|
- objectNode.position = Vector3(0, -0.5, 0)
|
|
|
- objectNode.scale = Vector3(200, 1, 200)
|
|
|
-
|
|
|
- local object = objectNode:CreateComponent("StaticModel")
|
|
|
- object.model = cache:GetResource("Model", "Models/Box.mdl")
|
|
|
- object.material = cache:GetResource("Material", "Materials/StoneTiled.xml")
|
|
|
- object.occluder = true
|
|
|
-
|
|
|
- local body = objectNode:CreateComponent("RigidBody")
|
|
|
- local shape = objectNode:CreateComponent("CollisionShape")
|
|
|
- shape:SetBox(Vector3(1, 1, 1))
|
|
|
- end
|
|
|
-
|
|
|
- for i = 1, 50 do
|
|
|
- local objectNode = testScene:CreateChild("Box")
|
|
|
- objectNode.position = Vector3(Random() * 180 - 90, 1, Random() * 180 - 90)
|
|
|
- objectNode:SetScale(2)
|
|
|
-
|
|
|
- local object = objectNode:CreateComponent("StaticModel")
|
|
|
- object.model = cache:GetResource("Model", "Models/Box.mdl")
|
|
|
- object.material = cache:GetResource("Material", "Materials/Stone.xml")
|
|
|
- object.castShadows = true
|
|
|
-
|
|
|
- local body = objectNode:CreateComponent("RigidBody")
|
|
|
- local shape = objectNode:CreateComponent("CollisionShape")
|
|
|
- shape:SetBox(Vector3(1, 1, 1))
|
|
|
- end
|
|
|
-
|
|
|
- for i = 1, 10 do
|
|
|
- local objectNode = testScene:CreateChild("Box")
|
|
|
- objectNode.position = Vector3(Random() * 180 - 90, 10, Random() * 180 - 90)
|
|
|
- objectNode:SetScale(20)
|
|
|
-
|
|
|
- local object = objectNode:CreateComponent("StaticModel")
|
|
|
- object.model = cache:GetResource("Model", "Models/Box.mdl")
|
|
|
- object.material = cache:GetResource("Material", "Materials/Stone.xml")
|
|
|
- object.castShadows = true
|
|
|
- object.occluder = true
|
|
|
-
|
|
|
- local body = objectNode:CreateComponent("RigidBody")
|
|
|
- local shape = objectNode:CreateComponent("CollisionShape")
|
|
|
- shape:SetBox(Vector3(1, 1, 1))
|
|
|
- end
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- for i = 1, 50 do
|
|
|
- local objectNode = testScene:CreateChild("Mushroom")
|
|
|
- objectNode.position = Vector3(Random() * 180 - 90, 0, Random() * 180 - 90)
|
|
|
- objectNode.rotation = Quaternion(0, Random(360.0), 0)
|
|
|
- objectNode:SetScale(5)
|
|
|
-
|
|
|
- local object = objectNode:CreateComponent("StaticModel")
|
|
|
- object.model = cache:GetResource("Model", "Models/Mushroom.mdl")
|
|
|
- object.material = cache:GetResource("Material", "Materials/Mushroom.xml")
|
|
|
- object.castShadows = true
|
|
|
-
|
|
|
- local body = objectNode:CreateComponent("RigidBody")
|
|
|
- local shape = objectNode:CreateComponent("CollisionShape")
|
|
|
- shape:SetTriangleMesh(object:GetModel())
|
|
|
- end
|
|
|
-
|
|
|
-
|
|
|
- for i = 1, 50 do
|
|
|
- local objectNode = testScene:CreateChild("Jack")
|
|
|
- objectNode:SetPosition(Vector3(Random() * 180 - 90, 0, Random() * 180 - 90))
|
|
|
- objectNode:SetRotation(Quaternion(0, Random() * 360, 0))
|
|
|
-
|
|
|
- local object = objectNode:CreateComponent("AnimatedModel")
|
|
|
- object.model = cache:GetResource("Model", "Models/Jack.mdl")
|
|
|
- object.material = cache:GetResource("Material", "Materials/Jack.xml")
|
|
|
- object.castShadows = true
|
|
|
-
|
|
|
- -- Create a capsule shape for detecting collisions
|
|
|
- local body = objectNode:CreateComponent("RigidBody")
|
|
|
- body.trigger = true
|
|
|
-
|
|
|
- local shape = objectNode:CreateComponent("CollisionShape")
|
|
|
- shape:SetCapsule(0.7, 1.8, Vector3(0.0, 0.9, 0.0))
|
|
|
- local ctrl = objectNode:CreateComponent("AnimationController")
|
|
|
- ctrl:Play("Models/Jack_Walk.ani", 0, true, 0.0)
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-function HandleUpdate(eventType, eventData)
|
|
|
- local timeStep = eventData:GetFloat("TimeStep")
|
|
|
-
|
|
|
- if ui:GetFocusElement() == nil then
|
|
|
- local speedMultiplier = 1.0
|
|
|
- if input:GetKeyDown(KEY_LSHIFT) then
|
|
|
- speedMultiplier = 5.0
|
|
|
- end
|
|
|
- if input:GetKeyDown(KEY_LCTRL) then
|
|
|
- speedMultiplier = 0.1
|
|
|
- end
|
|
|
-
|
|
|
- local speed = timeStep * speedMultiplier
|
|
|
-
|
|
|
- if input:GetKeyDown(KEY_W) then
|
|
|
- cameraNode:Translate(Vector3(0, 0, 10) * speed)
|
|
|
- end
|
|
|
- if input:GetKeyDown(KEY_S) then
|
|
|
- cameraNode:Translate(Vector3(0, 0, -10) * speed)
|
|
|
- end
|
|
|
- if input:GetKeyDown(KEY_A) then
|
|
|
- cameraNode:Translate(Vector3(-10, 0, 0) * speed)
|
|
|
- end
|
|
|
- if input:GetKeyDown(KEY_D) then
|
|
|
- cameraNode:Translate(Vector3(10, 0, 0) * speed)
|
|
|
- end
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-function HandleKeyDown(eventType, eventData)
|
|
|
- local key = eventData:GetInt("Key")
|
|
|
-
|
|
|
- if key == KEY_ESC then
|
|
|
- if ui:GetFocusElement() == nil then
|
|
|
- engine:Exit()
|
|
|
- else
|
|
|
- console:SetVisible(false)
|
|
|
- end
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_F1 then
|
|
|
- console:Toggle()
|
|
|
- end
|
|
|
-
|
|
|
- if ui:GetFocusElement() == nil then
|
|
|
- if key == KEY_1 then
|
|
|
- local quality = renderer:GetTextureQuality()
|
|
|
- quality = quality + 1
|
|
|
- if quality > 2 then
|
|
|
- quality = 0
|
|
|
- end
|
|
|
- renderer:SetTextureQuality(quality)
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_2 then
|
|
|
- local quality = renderer:GetMaterialQuality()
|
|
|
- quality = quality + 1
|
|
|
- if quality > 2 then
|
|
|
- quality = 0
|
|
|
- end
|
|
|
- renderer:SetMaterialQuality(quality)
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_3 then
|
|
|
- renderer:SetSpecularLighting(not renderer:GetSpecularLighting())
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_4 then
|
|
|
- renderer:SetDrawShadows(not renderer:GetDrawShadows())
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_5 then
|
|
|
- local size = renderer:GetShadowMapSize()
|
|
|
- size = size * 2
|
|
|
- if size > 2048 then
|
|
|
- size = 512
|
|
|
- end
|
|
|
- renderer:SetShadowMapSize(size)
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_6 then
|
|
|
- renderer:SetShadowQuality(renderer:GetShadowQuality() + 1)
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_7 then
|
|
|
- local occlusion = renderer:GetMaxOccluderTriangles() > 0
|
|
|
- occlusion = not occlusion
|
|
|
- if occlusion then
|
|
|
- renderer:SetMaxOccluderTriangles(5000)
|
|
|
- else
|
|
|
- renderer:SetMaxOccluderTriangles(0)
|
|
|
- end
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_8 then
|
|
|
- renderer:SetDynamicInstancing(not renderer:GetDynamicInstancing())
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_SPACE then
|
|
|
- drawDebug = drawDebug + 1
|
|
|
- if drawDebug > 2 then
|
|
|
- drawDebug = 0
|
|
|
- end
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_B then
|
|
|
- renderer:GetViewport(0):GetRenderPath():ToggleEnabled("Bloom")
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_F then
|
|
|
- renderer:GetViewport(0):GetRenderPath():ToggleEnabled("EdgeFilter")
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_O then
|
|
|
- camera:SetOrthographic(not camera:IsOrthographic())
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_T then
|
|
|
- debugHud:Toggle(DEBUGHUD_SHOW_PROFILER)
|
|
|
- end
|
|
|
-
|
|
|
-
|
|
|
- if key == KEY_F5 then
|
|
|
- testScene:SaveXML(fileSystem:GetProgramDir() + "Data/Scenes/LuaTestScene.xml")
|
|
|
- end
|
|
|
-
|
|
|
- if key == KEY_F7 then
|
|
|
- testScene:LoadXML(fileSystem:GetProgramDir() + "Data/Scenes/LuaTestScene.xml")
|
|
|
- end
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-function HandleMouseMove(eventType, eventData)
|
|
|
- local buttons = eventData:GetInt("Buttons")
|
|
|
- if buttons == MOUSEB_RIGHT then
|
|
|
- local mousedx = eventData:GetInt("DX")
|
|
|
- local mousedy = eventData:GetInt("DY")
|
|
|
- yaw = yaw + (mousedx / 10.0)
|
|
|
- pitch = pitch + (mousedy / 10.0)
|
|
|
- if pitch < -90.0 then
|
|
|
- pitch = -90.0
|
|
|
- end
|
|
|
- if pitch > 90.0 then
|
|
|
- pitch = 90.0
|
|
|
- end
|
|
|
- cameraNode:SetRotation(Quaternion(pitch, yaw, 0))
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-
|
|
|
-function HandleMouseButtonDown(eventType, eventData)
|
|
|
- local button = eventData:GetInt("Button")
|
|
|
- if button == MOUSEB_RIGHT then
|
|
|
- local cursor = ui:GetCursor()
|
|
|
- cursor:SetVisible(false)
|
|
|
- end
|
|
|
-
|
|
|
- -- Test either creating a new physics object or painting a decal (SHIFT down)
|
|
|
- if button == MOUSEB_LEFT and ui:GetElementAt(ui:GetCursorPosition(), true) == nil and ui:GetFocusElement() == nil then
|
|
|
- if not input:GetQualifierDown(QUAL_SHIFT) then
|
|
|
- local eventData = VariantMap()
|
|
|
- eventData:SetVector3("Pos", cameraNode:GetPosition())
|
|
|
- eventData:SetQuaternion("Rot", cameraNode:GetRotation())
|
|
|
-
|
|
|
- -- If we are the client, send the spawn command as a remote event, else send locally
|
|
|
- if runClient then
|
|
|
- if network:GetServerConnection() ~= nil then
|
|
|
- network:GetServerConnection():SendRemoteEvent("SpawnBox", true, eventData)
|
|
|
- end
|
|
|
- else
|
|
|
- SendEvent("SpawnBox", eventData)
|
|
|
- end
|
|
|
- else
|
|
|
- local pos = ui:GetCursorPosition()
|
|
|
- if ui:GetElementAt(pos, true) == nil and testScene:GetComponent("Octree") ~= nil then
|
|
|
- local cameraRay = camera:GetScreenRay(pos.x / graphics:GetWidth(), pos.y / graphics:GetHeight())
|
|
|
- local result = testScene:GetComponent("Octree"):RaycastSingle(cameraRay, RAY_TRIANGLE, 250.0, DRAWABLE_GEOMETRY)
|
|
|
- if result.drawable ~= nil then
|
|
|
- local rayHitPos = cameraRay.origin + cameraRay.direction * result.distance
|
|
|
- local decal = result.drawable:GetNode():GetComponent("DecalSet")
|
|
|
- if decal == nil then
|
|
|
- decal = result.drawable:GetNode():CreateComponent("DecalSet")
|
|
|
- decal.material = cache:GetResource("Material", "Materials/UrhoDecal.xml")
|
|
|
- -- Increase max. vertices/indices if the target is skinned
|
|
|
- if result.drawable:GetTypeName() == "AnimatedModel" then
|
|
|
- decal.maxVertices = 2048
|
|
|
- decal.maxIndices = 4096
|
|
|
- end
|
|
|
- end
|
|
|
- decal:AddDecal(result.drawable, rayHitPos, cameraNode:GetWorldRotation(), 0.5, 1.0, 1.0, Vector2(0, 0), Vector2(1, 1))
|
|
|
- end
|
|
|
- end
|
|
|
- end
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-function HandleSpawnBox(eventType, eventData)
|
|
|
- local position = eventData:GetVector3("Pos")
|
|
|
- local rotation = eventData:GetQuaternion("Rot")
|
|
|
-
|
|
|
- local newNode = testScene:CreateChild("")
|
|
|
- newNode.position = position
|
|
|
- newNode.rotation =rotation
|
|
|
- newNode:SetScale(0.2)
|
|
|
-
|
|
|
- local body = newNode:CreateComponent("RigidBody")
|
|
|
- body.mass = 1.0
|
|
|
- body.friction = 1.0
|
|
|
- body.linearVelocity = rotation * Vector3(0.0, 1.0, 10.0)
|
|
|
-
|
|
|
- local shape = newNode:CreateComponent("CollisionShape")
|
|
|
- shape:SetBox(Vector3(1, 1, 1))
|
|
|
-
|
|
|
- local object = newNode:CreateComponent("StaticModel")
|
|
|
- object.model = cache:GetResource("Model", "Models/Box.mdl")
|
|
|
- object.material = cache:GetResource("Material", "Materials/StoneSmall.xml")
|
|
|
- object.castShadows = true
|
|
|
- object.shadowDistance = 150.0
|
|
|
- object.drawDistance = 200.0
|
|
|
-end
|
|
|
-
|
|
|
-function HandleMouseButtonUp(eventType, eventData)
|
|
|
- if eventData:GetInt("Button") == MOUSEB_RIGHT then
|
|
|
- ui:GetCursor():SetVisible(true)
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-function HandlePostRenderUpdate()
|
|
|
- if engine.headless then
|
|
|
- return
|
|
|
- end
|
|
|
-
|
|
|
- -- Draw rendering debug geometry without depth test to see the effect of occlusion
|
|
|
- if drawDebug == 1 then
|
|
|
- renderer:DrawDebugGeometry(true)
|
|
|
- end
|
|
|
- if drawDebug == 2 then
|
|
|
- testScene:GetComponent("PhysicsWorld"):DrawDebugGeometry(true)
|
|
|
- end
|
|
|
-
|
|
|
- local pos = ui.cursorPosition
|
|
|
- if ui:GetElementAt(pos, true) == nil and testScene:GetComponent("Octree") ~= nil then
|
|
|
- local cameraRay = camera:GetScreenRay(pos.x / graphics:GetWidth(), pos.y / graphics:GetHeight())
|
|
|
- local result = testScene:GetComponent("Octree"):RaycastSingle(cameraRay, RAY_TRIANGLE, 250.0, DRAWABLE_GEOMETRY)
|
|
|
- if result.drawable ~= nil then
|
|
|
- local rayHitPos = cameraRay.origin + cameraRay.direction * result.distance
|
|
|
- testScene:GetComponent("DebugRenderer"):AddBoundingBox(BoundingBox(rayHitPos + Vector3(-0.01, -0.01, -0.01), rayHitPos +
|
|
|
- Vector3(0.01, 0.01, 0.01)), Color(1.0, 1.0, 1.0), true)
|
|
|
- end
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-function HandleClientConnected(eventType, eventData)
|
|
|
- local connection = eventData:GetPtr("Connection", "Connection")
|
|
|
- connection.scene = testScene -- Begin scene replication to the client
|
|
|
- connection.logStatistics = true
|
|
|
-end
|
|
|
-
|
|
|
-
|
|
|
-function HandlePhysicsCollision(eventType, eventData)
|
|
|
- -- Check if either of the nodes has an AnimatedModel component
|
|
|
- local nodeA = eventData:GetPtr("Node", "NodeA")
|
|
|
- local nodeB = eventData:GetPtr("Node", "NodeB")
|
|
|
- if nodeA:HasComponent("AnimatedModel") then
|
|
|
- HandleHit(nodeA)
|
|
|
- elseif nodeB:HasComponent("AnimatedModel") then
|
|
|
- HandleHit(nodeB)
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-function HandleHit(node)
|
|
|
- -- Remove the trigger physics shape, and create the ragdoll
|
|
|
- node:RemoveComponent("RigidBody")
|
|
|
- node:RemoveComponent("CollisionShape")
|
|
|
- CreateRagdoll(node:GetComponent("AnimatedModel"))
|
|
|
-end
|
|
|
-
|
|
|
-function CreateRagdoll(model)
|
|
|
- local root = model:GetNode()
|
|
|
- CreateRagdollBone(root, "Bip01_Pelvis", SHAPE_BOX, Vector3(0.3, 0.2, 0.25), Vector3(0, 0, 0), Quaternion(0, 0, 0))
|
|
|
- CreateRagdollBone(root, "Bip01_Spine1", SHAPE_BOX, Vector3(0.35, 0.2, 0.3), Vector3(0.15, 0, 0), Quaternion(0, 0, 0))
|
|
|
- CreateRagdollBone(root, "Bip01_L_Thigh", SHAPE_CAPSULE, Vector3(0.175, 0.45, 0.175), Vector3(0.25, 0, 0), Quaternion(0, 0, 90))
|
|
|
- CreateRagdollBone(root, "Bip01_R_Thigh", SHAPE_CAPSULE, Vector3(0.175, 0.45, 0.175), Vector3(0.25, 0, 0), Quaternion(0, 0, 90))
|
|
|
- CreateRagdollBone(root, "Bip01_L_Calf", SHAPE_CAPSULE, Vector3(0.15, 0.55, 0.15), Vector3(0.25, 0, 0), Quaternion(0, 0, 90))
|
|
|
- CreateRagdollBone(root, "Bip01_R_Calf", SHAPE_CAPSULE, Vector3(0.15, 0.55, 0.15), Vector3(0.25, 0, 0), Quaternion(0, 0, 90))
|
|
|
- CreateRagdollBone(root, "Bip01_Head", SHAPE_BOX, Vector3(0.2, 0.2, 0.2), Vector3(0.1, 0, 0), Quaternion(0, 0, 0))
|
|
|
- CreateRagdollBone(root, "Bip01_L_UpperArm", SHAPE_CAPSULE, Vector3(0.15, 0.35, 0.15), Vector3(0.1, 0, 0), Quaternion(0, 0, 90))
|
|
|
- CreateRagdollBone(root, "Bip01_R_UpperArm", SHAPE_CAPSULE, Vector3(0.15, 0.35, 0.15), Vector3(0.1, 0, 0), Quaternion(0, 0, 90))
|
|
|
- CreateRagdollBone(root, "Bip01_L_Forearm", SHAPE_CAPSULE, Vector3(0.125, 0.4, 0.125), Vector3(0.2, 0, 0), Quaternion(0, 0, 90))
|
|
|
- CreateRagdollBone(root, "Bip01_R_Forearm", SHAPE_CAPSULE, Vector3(0.125, 0.4, 0.125), Vector3(0.2, 0, 0), Quaternion(0, 0, 90))
|
|
|
-
|
|
|
- CreateRagdollConstraint(root, "Bip01_L_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(45, 45), Vector2(0, 0), true)
|
|
|
- CreateRagdollConstraint(root, "Bip01_R_Thigh", "Bip01_Pelvis", CONSTRAINT_CONETWIST, Vector3(0, 0, -1), Vector3(0, 0, 1), Vector2(45, 45), Vector2(0, 0), true)
|
|
|
- CreateRagdollConstraint(root, "Bip01_L_Calf", "Bip01_L_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0), true)
|
|
|
- CreateRagdollConstraint(root, "Bip01_R_Calf", "Bip01_R_Thigh", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0), true)
|
|
|
- CreateRagdollConstraint(root, "Bip01_Spine1", "Bip01_Pelvis", CONSTRAINT_HINGE, Vector3(0, 0, 1), Vector3(0, 0, 1), Vector2(45, 0), Vector2(-10, 0), true)
|
|
|
- CreateRagdollConstraint(root, "Bip01_Head", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(1, 0, 0), Vector3(1, 0, 0), Vector2(0, 30), Vector2(0, 0), true)
|
|
|
- CreateRagdollConstraint(root, "Bip01_L_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(45, 45), Vector2(0, 0), false)
|
|
|
- CreateRagdollConstraint(root, "Bip01_R_UpperArm", "Bip01_Spine1", CONSTRAINT_CONETWIST, Vector3(0, -1, 0), Vector3(0, 1, 0), Vector2(45, 45), Vector2(0, 0), false)
|
|
|
- CreateRagdollConstraint(root, "Bip01_L_Forearm", "Bip01_L_UpperArm", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0), true)
|
|
|
- CreateRagdollConstraint(root, "Bip01_R_Forearm", "Bip01_R_UpperArm", CONSTRAINT_HINGE, Vector3(0, 0, -1), Vector3(0, 0, -1), Vector2(90, 0), Vector2(0, 0), true)
|
|
|
-
|
|
|
- -- Disable animation from all bones (both physical and non-physical) to not interfere
|
|
|
- local skel = model:GetSkeleton()
|
|
|
- for i = 1, skel:GetNumBones() do
|
|
|
- skel:GetBone(i-1).animated = false
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
-function CreateRagdollBone(root, boneName, type, size, position, rotation)
|
|
|
- local boneNode = root:GetChild(boneName, true)
|
|
|
- if boneNode == nil or boneNode:HasComponent("RigidBody") then
|
|
|
- return
|
|
|
- end
|
|
|
-
|
|
|
- -- In networked operation both client and server detect collisions separately, and create ragdolls on their own
|
|
|
- -- (bones are not synced over network.) To prevent replicated component ID range clashes when the client creates
|
|
|
- -- any components, it is important that the LOCAL creation mode is specified.
|
|
|
- local body = boneNode:CreateComponent("RigidBody", LOCAL)
|
|
|
- body.mass = 1.0
|
|
|
- body.linearDamping = 0.05
|
|
|
- body.angularDamping = 0.85
|
|
|
- body.linearRestThreshold = 1.5
|
|
|
- body.angularRestThreshold = 2.5
|
|
|
-
|
|
|
- local shape = boneNode:CreateComponent("CollisionShape", LOCAL)
|
|
|
- shape.shapeType = type
|
|
|
- shape.size = size
|
|
|
- shape.position = position
|
|
|
- shape.rotation = rotation
|
|
|
-end
|
|
|
-
|
|
|
-function CreateRagdollConstraint(root, boneName, parentName, type, axis, parentAxis, highLimit, lowLimit, disableCollision)
|
|
|
- local boneNode = root:GetChild(boneName, true)
|
|
|
- local parentNode = root:GetChild(parentName, true)
|
|
|
- if boneNode == nil or parentNode == nil or boneNode:HasComponent("Constraint") then
|
|
|
- return
|
|
|
- end
|
|
|
-
|
|
|
- local constraint = boneNode:CreateComponent("Constraint", LOCAL)
|
|
|
- constraint.constraintType = type
|
|
|
- constraint.disableCollision = disableCollision
|
|
|
- -- The connected body must be specified before setting the world position
|
|
|
- constraint.otherBody = parentNode:GetComponent("RigidBody")
|
|
|
- constraint.worldPosition = boneNode.worldPosition
|
|
|
- constraint:SetAxis(axis)
|
|
|
- constraint:SetOtherAxis(parentAxis)
|
|
|
- constraint.highLimit = highLimit
|
|
|
- constraint.lowLimit = lowLimit
|
|
|
-end
|