93 | function VehicleCharacter:characterLoaded(success, arguments) |
94 | if success then |
95 | -- Model was unloaded before finishing loading |
96 | if self.playerModel.rootNode == nil then |
97 | return |
98 | end |
99 | |
100 | local playerStyle = arguments.playerStyle |
101 | self.playerModel:setStyle(playerStyle, false, nil) |
102 | |
103 | -- Link to the vehicle |
104 | local linkNode = Utils.getNoNil(self.characterNode, self.vehicle.rootNode) |
105 | link(linkNode, self.playerModel.rootNode) |
106 | |
107 | -- Update IK |
108 | IKUtil.updateAlignNodes(self.playerModel.ikChains, nil, nil, linkNode) |
109 | for ikChainId, target in pairs(self.ikChainTargets) do |
110 | IKUtil.setTarget(self.playerModel:getIKChains(), ikChainId, target) |
111 | end |
112 | |
113 | if self.characterSpineRotation ~= nil and self.playerModel.thirdPersonSpineNode ~= nil then |
114 | setRotation(self.playerModel.thirdPersonSpineNode, unpack(self.characterSpineRotation)) |
115 | end |
116 | |
117 | self.characterDistanceRefNode = self.characterDistanceRefNodeCustom or self.playerModel.thirdPersonHeadNode |
118 | |
119 | if self.playerModel.skeleton ~= nil and getNumOfChildren(self.playerModel.skeleton) > 0 then |
120 | if self.useAnimation then |
121 | local skeleton = self.playerModel.skeleton |
122 | local animNode = g_animCache:getNode(AnimationCache.CHARACTER) |
123 | cloneAnimCharacterSet(getChildAt(animNode, 0), skeleton) |
124 | self.animationCharsetId = getAnimCharacterSet(getChildAt(skeleton, 0)) |
125 | local animationPlayer = createConditionalAnimation() |
126 | if animationPlayer ~= 0 then |
127 | self.animationPlayer = animationPlayer |
128 | end |
129 | |
130 | if self.animationCharsetId == 0 then |
131 | self.animationCharsetId = nil |
132 | Logging.devError("-- [VehicleCharacter:loadCharacter] Could not load animation CharSet from: [%s/%s]", getName(getParent(skeleton)), getName(skeleton)) |
133 | printScenegraph(getParent(skeleton)) |
134 | end |
135 | elseif self.useIdleAnimation then |
136 | local skeleton = self.playerModel.skeleton |
137 | local animNode = g_animCache:getNode(AnimationCache.VEHICLE_CHARACTER) |
138 | cloneAnimCharacterSet(getChildAt(animNode, 0), skeleton) |
139 | self.animationCharsetId = getAnimCharacterSet(skeleton) |
140 | if self.animationCharsetId ~= 0 then |
141 | self.idleClipIndex = getAnimClipIndex(self.animationCharsetId, "idleSource") |
142 | clearAnimTrackClip(self.animationCharsetId, 0) |
143 | assignAnimTrackClip(self.animationCharsetId, 0, self.idleClipIndex) |
144 | setAnimTrackLoopState(self.animationCharsetId, 0, true) |
145 | |
146 | self.idleAnimationState = false |
147 | else |
148 | self.useIdleAnimation = false |
149 | self.animationCharsetId = nil |
150 | Logging.devError("-- [VehicleCharacter:loadCharacter] Could not load animation CharSet from: [%s/%s]", getName(getParent(skeleton)), getName(skeleton)) |
151 | end |
152 | end |
153 | end |
154 | |
155 | self:setDirty(true) |
156 | self:setCharacterVisibility(true) |
157 | else |
158 | self.playerModel:delete() |
159 | self.playerModel = nil |
160 | |
161 | Logging.error("Failed to load vehicleCharacter") |
162 | end |
163 | |
164 | local asyncCallbackObject = arguments.asyncCallbackObject |
165 | local asyncCallbackFunction = arguments.asyncCallbackFunction |
166 | local asyncCallbackArguments = arguments.asyncCallbackArguments |
167 | |
168 | if asyncCallbackFunction ~= nil then |
169 | asyncCallbackFunction(asyncCallbackObject, success, asyncCallbackArguments) |
170 | end |
171 | end |
30 | function VehicleCharacter:load(xmlFile, xmlNode) |
31 | XMLUtil.checkDeprecatedXMLElements(xmlFile, xmlNode .. "#index", xmlNode .. "#node") --FS17 to FS19 |
32 | |
33 | self.characterNode = xmlFile:getValue(xmlNode.."#node", nil, self.vehicle.components, self.vehicle.i3dMappings) |
34 | if self.characterNode ~= nil then |
35 | self.parentComponent = self.vehicle:getParentComponent(self.characterNode) |
36 | self.characterCameraMinDistance = xmlFile:getValue(xmlNode.."#cameraMinDistance", 1.5) |
37 | self.characterDistanceRefNodeCustom = xmlFile:getValue(xmlNode.."#distanceRefNode", nil, self.vehicle.components, self.vehicle.i3dMappings) |
38 | self.characterDistanceRefNode = self.characterDistanceRefNodeCustom or self.characterNode |
39 | setVisibility(self.characterNode, false) |
40 | self.useAnimation = xmlFile:getValue(xmlNode.."#useAnimation", false) |
41 | self.useIdleAnimation = xmlFile:getValue(xmlNode.."#useIdleAnimation", not self.useAnimation) |
42 | |
43 | if not self.useAnimation then |
44 | self.ikChainTargets = {} |
45 | IKUtil.loadIKChainTargets(xmlFile, xmlNode, self.vehicle.components, self.ikChainTargets, self.vehicle.i3dMappings) |
46 | end |
47 | self.characterSpineRotation = xmlFile:getValue(xmlNode.."#spineRotation", nil, true) |
48 | self.characterSpineSpeedDepended = xmlFile:getValue(xmlNode.."#speedDependedSpine", false) |
49 | self.characterSpineNodeMinRot = xmlFile:getValue(xmlNode.."#spineNodeMinRot", 10) |
50 | self.characterSpineNodeMaxRot = xmlFile:getValue(xmlNode.."#spineNodeMaxRot", -10) |
51 | self.characterSpineNodeMinAcc = xmlFile:getValue(xmlNode.."#spineNodeMinAcc", -1) / (1000*1000) |
52 | self.characterSpineNodeMaxAcc = xmlFile:getValue(xmlNode.."#spineNodeMaxAcc", 1) / (1000*1000) |
53 | self.characterSpineNodeAccDeadZone = xmlFile:getValue(xmlNode.."#spineNodeAccDeadZone", 0.2) / (1000*1000) |
54 | self.characterSpineLastRotation = 0 |
55 | self:setCharacterVisibility(false) |
56 | |
57 | self.maxUpdateDistance = xmlFile:getValue(xmlNode.."#maxUpdateDistance", VehicleCharacter.DEFAULT_MAX_UPDATE_DISTANCE) |
58 | setClipDistance(self.characterNode, xmlFile:getValue(xmlNode.."#clipDistance", VehicleCharacter.DEFAULT_CLIP_DISTANCE)) |
59 | |
60 | return true |
61 | end |
62 | return false |
63 | end |
73 | function VehicleCharacter:loadCharacter(playerStyle, asyncCallbackObject, asyncCallbackFunction, asyncCallbackArguments) |
74 | --#debug assertWithCallstack(playerStyle ~= nil) |
75 | |
76 | if self.playerModel ~= nil then |
77 | self.playerModel:delete() |
78 | end |
79 | |
80 | self.playerModel = PlayerModel.new() |
81 | |
82 | local arguments = { |
83 | asyncCallbackObject = asyncCallbackObject, |
84 | asyncCallbackFunction = asyncCallbackFunction, |
85 | asyncCallbackArguments = asyncCallbackArguments, |
86 | playerStyle = playerStyle |
87 | } |
88 | self.playerModel:load(playerStyle.xmlFilename, false, false, self.useAnimation, self.characterLoaded, self, arguments) |
89 | end |
335 | function VehicleCharacter.registerCharacterXMLPaths(schema, basePath, name) |
336 | schema:register(XMLValueType.NODE_INDEX, basePath .. "#node", "Character root node") |
337 | schema:register(XMLValueType.FLOAT, basePath .. "#cameraMinDistance", "Min. distance until character is hidden", 1.5) |
338 | schema:register(XMLValueType.NODE_INDEX, basePath .. "#distanceRefNode", "Distance reference node", "Character root node") |
339 | schema:register(XMLValueType.BOOL, basePath .. "#useAnimation", "Use animation instead of ik chains", false) |
340 | schema:register(XMLValueType.BOOL, basePath .. "#useIdleAnimation", "Apply character idle animation additinally to ik chain control", "set if #useAnimation not set") |
341 | |
342 | schema:register(XMLValueType.VECTOR_ROT, basePath .. "#spineRotation", "Spine rotation") |
343 | schema:register(XMLValueType.BOOL, basePath .. "#speedDependedSpine", "Speed dependent spine", false) |
344 | schema:register(XMLValueType.ANGLE, basePath .. "#spineNodeMinRot", "Spine node min. rotation", 10) |
345 | schema:register(XMLValueType.ANGLE, basePath .. "#spineNodeMaxRot", "Spine node max. rotation", -10) |
346 | schema:register(XMLValueType.FLOAT, basePath .. "#spineNodeMinAcc", "Spine node min. acceleration", -1) |
347 | schema:register(XMLValueType.FLOAT, basePath .. "#spineNodeMaxAcc", "Spine node max. acceleration", 1) |
348 | schema:register(XMLValueType.FLOAT, basePath .. "#spineNodeAccDeadZone", "Spine node acceleration dead zone", 0.2) |
349 | |
350 | schema:register(XMLValueType.FLOAT, basePath .. "#maxUpdateDistance", "Max. distance to vehicle root to update ik chains of character", VehicleCharacter.DEFAULT_MAX_UPDATE_DISTANCE) |
351 | schema:register(XMLValueType.FLOAT, basePath .. "#clipDistance", "Clip distance of character", VehicleCharacter.DEFAULT_CLIP_DISTANCE) |
352 | |
353 | IKUtil.registerIKChainTargetsXMLPaths(schema, basePath) |
354 | end |