198 | function PlayerModel:loadFileFinished(rootNode, failedReason, arguments) |
199 | |
200 | if failedReason == LoadI3DFailedReason.FILE_NOT_FOUND then |
201 | Logging.error("Player model file '%s' does not exist!", self.filename) |
202 | return self.asyncLoadCallbackFunction(self.asyncLoadCallbackObject, false, self.asyncLoadCallbackArguments) |
203 | end |
204 | |
205 | if failedReason == LoadI3DFailedReason.UNKNOWN or rootNode == nil or rootNode == 0 then |
206 | Logging.error("Failed to load player model %s", self.filename, failedReason) |
207 | return self.asyncLoadCallbackFunction(self.asyncLoadCallbackObject, false, self.asyncLoadCallbackArguments) |
208 | end |
209 | |
210 | local xmlFile = loadXMLFile("playerXML", self.xmlFilename) |
211 | if xmlFile == 0 then |
212 | return self.asyncLoadCallbackFunction(self.asyncLoadCallbackObject, false, self.asyncLoadCallbackArguments) |
213 | end |
214 | |
215 | local isRealPlayer = arguments[1] |
216 | local isOwner = arguments[2] |
217 | local isAnimated = arguments[3] |
218 | |
219 | self.rootNode = rootNode |
220 | |
221 | -- Find nodes references in the XML first, before re-linking other nodes that change the hierarchy |
222 | if isRealPlayer then |
223 | local cNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.camera#index")) |
224 | if cNode == nil then |
225 | Logging.devError("Error: Failed to find player camera position in '%s'", self.filename) |
226 | end |
227 | |
228 | local x, y, z = localToLocal(cNode, rootNode, 0, 0, 0) |
229 | |
230 | local target = createTransformGroup("1p_camera_target") |
231 | link(rootNode, target) |
232 | setTranslation(target, x, y, z) |
233 | |
234 | self.firstPersonCameraTarget = target |
235 | end |
236 | |
237 | if isRealPlayer then |
238 | self.animRootThirdPerson = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#animRootNode")) |
239 | if self.animRootThirdPerson == nil then |
240 | Logging.devError("Error: Failed to find animation root node in '%s'", self.filename) |
241 | return self.asyncLoadCallbackFunction(self.asyncLoadCallbackObject, false, self.asyncLoadCallbackArguments) |
242 | end |
243 | |
244 | -- Capsule information |
245 | self.capsuleHeight = getXMLFloat(xmlFile, "player.character#physicsCapsuleHeight") |
246 | self.capsuleRadius = getXMLFloat(xmlFile, "player.character#physicsCapsuleRadius") |
247 | self.capsuleTotalHeight = self.capsuleHeight + self.capsuleRadius * 2 |
248 | end |
249 | |
250 | -- Avator customization |
251 | self.style = PlayerStyle.new() |
252 | -- self.style:loadConfigurationXML(self.xmlFilename) |
253 | |
254 | self.skeleton = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#skeleton")) |
255 | if self.skeleton == nil then |
256 | Logging.devError("Error: Failed to find skeleton root node in '%s'", self.filename) |
257 | end |
258 | |
259 | self.mesh = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#mesh")) |
260 | if self.mesh == nil then |
261 | Logging.devError("Error: Failed to find player mesh in '%s'", self.filename) |
262 | end |
263 | |
264 | -- Used for linking elements (handtools, lights) |
265 | self.thirdPersonSpineNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#spine")) |
266 | self.thirdPersonSuspensionNode = Utils.getNoNil(I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#suspension")), self.thirdPersonSpineNode) |
267 | self.thirdPersonRightHandNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#rightHandNode")) |
268 | self.thirdPersonLeftHandNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#leftHandNode")) |
269 | self.thirdPersonHeadNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.character.thirdPerson#headNode")) |
270 | |
271 | -- Torchlight |
272 | self.lightNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.light#index")) |
273 | if self.lightNode ~= nil then |
274 | setVisibility(self.lightNode, false) |
275 | end |
276 | |
277 | -- Relink only after the lights and cameras are loaded: indexing changes |
278 | if self.mesh ~= nil then |
279 | -- link(self.rootNode, self.mesh) |
280 | setClipDistance(self.mesh, 200) |
281 | end |
282 | |
283 | local pickUpKinematicHelperNode = I3DUtil.indexToObject(rootNode, getXMLString(xmlFile, "player.pickUpKinematicHelper#index")) |
284 | if pickUpKinematicHelperNode ~= nil then |
285 | if getRigidBodyType(pickUpKinematicHelperNode) == RigidBodyType.KINEMATIC then |
286 | self.pickUpKinematicHelperNode = pickUpKinematicHelperNode |
287 | self.pickUpKinematicHelperNodeChild = createTransformGroup("pickUpKinematicHelperNodeChild") |
288 | link(self.pickUpKinematicHelperNode, self.pickUpKinematicHelperNodeChild) |
289 | |
290 | addToPhysics(self.pickUpKinematicHelperNode) |
291 | else |
292 | Logging.xmlWarning(xmlFile, "Given pickUpKinematicHelper '%s' is not a kinematic object", getName(pickUpKinematicHelperNode)) |
293 | end |
294 | end |
295 | |
296 | -- IK Chains |
297 | self:loadIKChains(xmlFile, rootNode, isRealPlayer) |
298 | |
299 | if isAnimated then |
300 | if self.skeleton ~= nil and getNumOfChildren(self.skeleton) > 0 then |
301 | local animNode = g_animCache:getNode(AnimationCache.CHARACTER) |
302 | cloneAnimCharacterSet(animNode, getParent(self.skeleton)) |
303 | local animCharsetId = getAnimCharacterSet(getChildAt(self.skeleton, 0)) |
304 | self.animationInformation.player = createConditionalAnimation() |
305 | |
306 | for key, parameter in pairs(self.animationInformation.parameters) do |
307 | conditionalAnimationRegisterParameter(self.animationInformation.player, parameter.id, parameter.type, key) |
308 | end |
309 | initConditionalAnimation(self.animationInformation.player, animCharsetId, self.xmlFilename, "player.conditionalAnimation") |
310 | setConditionalAnimationSpecificParameterIds(self.animationInformation.player, self.animationInformation.parameters.absForwardVelocity.id, self.animationInformation.parameters.yawVelocity.id) |
311 | end |
312 | end |
313 | |
314 | if isRealPlayer then |
315 | self.skeletonRootNode = createTransformGroup("player_skeletonRootNode") |
316 | |
317 | link(getRootNode(), self.rootNode) |
318 | link(self.rootNode, self.skeletonRootNode) |
319 | |
320 | if self.animRootThirdPerson ~= nil then |
321 | link(self.skeletonRootNode, self.animRootThirdPerson) |
322 | if self.skeleton ~= nil then |
323 | link(self.animRootThirdPerson, self.skeleton) |
324 | end |
325 | end |
326 | |
327 | self.leftArmToolNode = createTransformGroup("leftArmToolNode") |
328 | self.rightArmToolNode = createTransformGroup("rightArmToolNode") |
329 | |
330 | if isOwner then |
331 | local toolRotation = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#firstPersonRotation"), "0 0 0"), 3) |
332 | local rotX, rotY, rotZ = unpack(toolRotation) |
333 | setRotation(self.rightArmToolNode, math.rad(rotX), math.rad(rotY), math.rad(rotZ)) |
334 | local toolTranslate = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#firstPersonTranslation"), "0 0 0"), 3) |
335 | local transX, transY, transZ = unpack(toolTranslate) |
336 | setTranslation(self.rightArmToolNode, transX, transY, transZ) |
337 | else |
338 | -- right hand tool |
339 | local toolRotationR = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#thirdPersonRightNodeRotation"), "0 0 0"), 3) |
340 | local rotRX, rotRY, rotRZ = unpack(toolRotationR) |
341 | setRotation(self.rightArmToolNode, math.rad(rotRX), math.rad(rotRY), math.rad(rotRZ)) |
342 | local toolTranslateR = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#thirdPersonRightNodeTranslation"), "0 0 0"), 3) |
343 | local transRX, transRY, transRZ = unpack(toolTranslateR) |
344 | setTranslation(self.rightArmToolNode, transRX, transRY, transRZ) |
345 | link(self.thirdPersonRightHandNode, self.rightArmToolNode) |
346 | |
347 | -- left hand tool |
348 | local toolRotationL = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#thirdPersonLeftNodeRotation"), "0 0 0"), 3) |
349 | local rotLX, rotLY, rotLZ = unpack(toolRotationL) |
350 | setRotation(self.leftArmToolNode, math.rad(rotLX), math.rad(rotLY), math.rad(rotLZ)) |
351 | local toolTranslateL = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.character.toolNode#thirdPersonLeftNodeTranslation"), "0 0 0"), 3) |
352 | local transLX, transLY, transLZ = unpack(toolTranslateL) |
353 | setTranslation(self.leftArmToolNode, transLX, transLY, transLZ) |
354 | link(self.thirdPersonLeftHandNode, self.leftArmToolNode) |
355 | |
356 | -- light: attached to the head |
357 | link(self.thirdPersonHeadNode, self.lightNode) |
358 | local lightRotation = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.light#thirdPersonRotation"), "0 0 0"), 3) |
359 | local lightRotX, lightRotY, lightRotZ = unpack(lightRotation) |
360 | local lightTranslate = string.getVectorN(Utils.getNoNil(getXMLString(xmlFile, "player.light#thirdPersonTranslation"), "0 0 0"), 3) |
361 | local lightTransX, lightTransY, lightTransZ = unpack(lightTranslate) |
362 | setRotation(self.lightNode, math.rad(lightRotX), math.rad(lightRotY), math.rad(lightRotZ)) |
363 | setTranslation(self.lightNode, lightTransX, lightTransY, lightTransZ) |
364 | end |
365 | |
366 | -- Fx |
367 | self.particleSystemsInformation.swimNode = createTransformGroup("swimFXNode") |
368 | link(getRootNode(), self.particleSystemsInformation.swimNode) |
369 | self.particleSystemsInformation.plungeNode = createTransformGroup("plungeFXNode") |
370 | link(getRootNode(), self.particleSystemsInformation.plungeNode) |
371 | |
372 | ParticleUtil.loadParticleSystem(xmlFile, self.particleSystemsInformation.systems.swim, "player.particleSystems.swim", self.particleSystemsInformation.swimNode, false, nil, self.baseDirectory) |
373 | ParticleUtil.loadParticleSystem(xmlFile, self.particleSystemsInformation.systems.plunge, "player.particleSystems.plunge", self.particleSystemsInformation.plungeNode, false, nil, self.baseDirectory) |
374 | else |
375 | -- Will be re-linked in linkTo: |
376 | if not isAnimated then |
377 | local linkNode = createTransformGroup("characterLinkNode") |
378 | link(self.rootNode, linkNode) |
379 | link(linkNode, self.skeleton) |
380 | |
381 | local x, y, z = localToLocal(self.thirdPersonSpineNode, self.skeleton, 0, 0, 0) |
382 | setTranslation(linkNode, -x, -y, -z) |
383 | else |
384 | link(self.rootNode, self.skeleton) |
385 | end |
386 | |
387 | if self.pickUpKinematicHelperNode ~= nil then |
388 | delete(self.pickUpKinematicHelperNode) |
389 | self.pickUpKinematicHelperNode = nil |
390 | end |
391 | if self.lightNode ~= nil then |
392 | delete(self.lightNode) |
393 | self.lightNode = nil |
394 | end |
395 | -- if self.cameraNode ~= nil then |
396 | -- delete(self.cameraNode) |
397 | -- self.cameraNode = nil |
398 | -- end |
399 | |
400 | -- self.visualInformation:applySelection() |
401 | -- self.visualInformation:setVisibility(true) |
402 | end |
403 | |
404 | -- Sound |
405 | if isRealPlayer and Platform.hasPlayer then |
406 | self:loadSounds(xmlFile, isOwner) |
407 | end |
408 | |
409 | delete(xmlFile) |
410 | |
411 | self.isLoaded = true |
412 | |
413 | return self.asyncLoadCallbackFunction(self.asyncLoadCallbackObject, true, self.asyncLoadCallbackArguments) |
414 | end |