Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
1 | -- |
2 | -- WorkParticles |
3 | -- Class for all vehicles with animated work particles |
4 | -- |
5 | -- @author Manuel Leithner |
6 | -- @date 21/07/14 |
7 | -- |
8 | -- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved. |
9 | |
10 | WorkParticles = {}; |
11 | |
12 | function WorkParticles.prerequisitesPresent(specializations) |
13 | return true; |
14 | end; |
15 | |
16 | function WorkParticles:preLoad(xmlFile) |
17 | self.loadGroundReferenceNodeFromXML = Utils.overwrittenFunction(self.loadGroundReferenceNodeFromXML, WorkParticles.loadGroundReferenceNodeFromXML); |
18 | assert(self.getDoGroundManipulation == nil, "WorkParticles needs to be the first specialization which implements getDoGroundManipulation"); |
19 | self.getDoGroundManipulation = WorkParticles.getDoGroundManipulation; |
20 | end |
21 | |
22 | function WorkParticles:load(xmlFile) |
23 | |
24 | if self.isClient then |
25 | if hasXMLProperty(xmlFile, "vehicle.groundParticleSystem") then |
26 | print("Warning: vehicle.groundParticleSystem is not supported anymore in "..self.configFileName..". Use vehicle.groundParticleSystems.groundParticleSystem instead!"); |
27 | end; |
28 | |
29 | self.groundParticleAnimations = {}; |
30 | local i = 0; |
31 | while true do |
32 | local baseName = string.format("vehicle.groundParticleAnimations.groundParticleAnimation(%d)", i); |
33 | if not hasXMLProperty(xmlFile, baseName) then |
34 | break; |
35 | end; |
36 | local animation = {}; |
37 | local filenameStr = getXMLString(xmlFile, baseName .. "#file"); |
38 | local i3dNode = Utils.loadSharedI3DFile(filenameStr, self.baseDirectory); |
39 | if i3dNode ~= 0 then |
40 | animation.filename = filenameStr; |
41 | animation.mappings = {}; |
42 | local j = 0; |
43 | while true do |
44 | local nodeBaseName = string.format(baseName .. ".node(%d)", j); |
45 | if not hasXMLProperty(xmlFile, nodeBaseName) then |
46 | break; |
47 | end; |
48 | |
49 | local node = Utils.indexToObject(self.components, getXMLString(xmlFile, nodeBaseName.."#index")); |
50 | local animNode = Utils.indexToObject(i3dNode, getXMLString(xmlFile, nodeBaseName.."#animMeshIndex")); |
51 | local groundRefIndex = getXMLInt(xmlFile, nodeBaseName .. "#refNodeIndex"); |
52 | if node == nil then |
53 | print("Warning: Invalid node index '"..getXMLString(xmlFile, nodeBaseName.."#index").."' in '"..self.configFileName.."'!"); |
54 | break; |
55 | end; |
56 | if animNode == nil then |
57 | print("Warning: Invalid animMesh index '"..getXMLString(xmlFile, nodeBaseName.."#animMeshIndex").."' in '"..self.configFileName.."'!"); |
58 | break; |
59 | end; |
60 | if groundRefIndex == nil or self.groundReferenceNodes[groundRefIndex+1] == nil then |
61 | print("Warning: Invalid refNodeIndex '"..getXMLString(xmlFile, nodeBaseName.."#refNodeIndex").."' in '"..self.configFileName.."'!"); |
62 | break; |
63 | end; |
64 | |
65 | local mapping = {}; |
66 | mapping.node = node; |
67 | mapping.animNode = animNode; |
68 | mapping.groundRefNode = self.groundReferenceNodes[groundRefIndex+1]; |
69 | mapping.lastDepth = 0; |
70 | mapping.speed = 0; |
71 | mapping.maxWorkDepth = Utils.getNoNil(getXMLFloat(xmlFile, nodeBaseName.."#maxDepth"), -0.1); |
72 | table.insert(animation.mappings, mapping); |
73 | j = j + 1; |
74 | end; |
75 | |
76 | -- link after loading to make sure all indices are correct |
77 | for _, mapping in pairs(animation.mappings) do |
78 | link(mapping.node, mapping.animNode); |
79 | setVisibility(mapping.animNode, false); |
80 | end; |
81 | |
82 | delete(i3dNode); |
83 | end; |
84 | |
85 | table.insert(self.groundParticleAnimations, animation); |
86 | i = i+1; |
87 | end; |
88 | |
89 | self.groundParticles = {}; |
90 | local i = 0; |
91 | while true do |
92 | local baseName = string.format("vehicle.groundParticleAnimations.groundParticle(%d)", i); |
93 | if not hasXMLProperty(xmlFile, baseName) then |
94 | break; |
95 | end; |
96 | local particle = {}; |
97 | local filenameStr = getXMLString(xmlFile, baseName .. "#file"); |
98 | local filename = Utils.getFilename(filenameStr, self.baseDirectory) |
99 | local i3dNode = loadI3DFile(filename, true, true, false); |
100 | if i3dNode ~= 0 then |
101 | particle.filename = filename; |
102 | particle.mappings = {}; |
103 | local j = 0; |
104 | while true do |
105 | local nodeBaseName = string.format(baseName .. ".node(%d)", j); |
106 | if not hasXMLProperty(xmlFile, nodeBaseName) then |
107 | break; |
108 | end; |
109 | |
110 | local node = Utils.indexToObject(self.components, getXMLString(xmlFile, nodeBaseName.."#index")); |
111 | local particleNode = Utils.indexToObject(i3dNode, getXMLString(xmlFile, nodeBaseName.."#particleIndex")); |
112 | local groundRefIndex = getXMLInt(xmlFile, nodeBaseName .. "#refNodeIndex"); |
113 | if node == nil then |
114 | print("Warning: Invalid node index '"..getXMLString(xmlFile, nodeBaseName.."#index").."' in '"..self.configFileName.."'!"); |
115 | break; |
116 | end; |
117 | if particleNode == nil then |
118 | print("Warning: Invalid particle index '"..getXMLString(xmlFile, nodeBaseName.."#particleIndex").."' in '"..self.configFileName.."'!"); |
119 | break; |
120 | end; |
121 | if groundRefIndex == nil or self.groundReferenceNodes[groundRefIndex+1] == nil then |
122 | print("Warning: Invalid refNodeIndex '"..getXMLString(xmlFile, nodeBaseName.."#refNodeIndex").."' in '"..self.configFileName.."'!"); |
123 | break; |
124 | end; |
125 | |
126 | local mapping = {}; |
127 | mapping.particles = {}; |
128 | mapping.node = node; |
129 | mapping.particleNode = particleNode; |
130 | mapping.groundRefNode = self.groundReferenceNodes[groundRefIndex+1]; |
131 | table.insert(particle.mappings, mapping); |
132 | j = j + 1; |
133 | end; |
134 | |
135 | -- link after loading to make sure all indices are correct |
136 | for _, mapping in pairs(particle.mappings) do |
137 | link(mapping.node, mapping.particleNode); |
138 | Utils.loadParticleSystemFromNode(mapping.particleNode, mapping.particles, false); |
139 | end; |
140 | |
141 | delete(i3dNode); |
142 | end; |
143 | |
144 | table.insert(self.groundParticles, particle); |
145 | i = i+1; |
146 | end; |
147 | |
148 | -- Fallback |
149 | local i=0; |
150 | while true do |
151 | local baseName = string.format("vehicle.groundParticleSystems.groundParticleSystem(%d)", i); |
152 | if not hasXMLProperty(xmlFile, baseName) then |
153 | break; |
154 | end; |
155 | local mapping = {}; |
156 | mapping.particles = {}; |
157 | Utils.loadParticleSystem(xmlFile, mapping.particles, baseName, self.components, false, nil, self.baseDirectory); |
158 | if table.getn(mapping.particles) > 0 then |
159 | local groundRefIndex = Utils.getNoNil(getXMLInt(xmlFile, baseName .. "#refNodeIndex"), 0); |
160 | if self.groundReferenceNodes[groundRefIndex+1] == nil then |
161 | groundRefIndex = 0; |
162 | print("Warning: Invalid refNodeIndex '"..groundRefIndex.."' in '"..self.configFileName.."'! Using default groundreferencenode!"); |
163 | end; |
164 | mapping.groundRefNode = self.groundReferenceNodes[groundRefIndex+1]; |
165 | |
166 | local particle = {mappings = {}}; |
167 | table.insert(particle.mappings, mapping); |
168 | table.insert(self.groundParticles, particle); |
169 | end |
170 | i = i+1; |
171 | end; |
172 | end; |
173 | |
174 | self.groundManipulationSpeedThreshold = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.groundManipulationSpeedThreshold#value"), 5); |
175 | end; |
176 | |
177 | function WorkParticles:delete() |
178 | if self.isClient then |
179 | for _, animation in pairs(self.groundParticleAnimations) do |
180 | Utils.releaseSharedI3DFile(animation.filename, self.baseDirectory, true); |
181 | end; |
182 | |
183 | for _, ps in pairs(self.groundParticles) do |
184 | for _, mapping in ipairs(ps.mappings) do |
185 | Utils.deleteParticleSystem(mapping.particles); |
186 | end; |
187 | end; |
188 | end; |
189 | end; |
190 | |
191 | function WorkParticles:mouseEvent(posX, posY, isDown, isUp, button) |
192 | end; |
193 | |
194 | function WorkParticles:keyEvent(unicode, sym, modifier, isDown) |
195 | end; |
196 | |
197 | function WorkParticles:update(dt) |
198 | end; |
199 | |
200 | function WorkParticles:updateTick(dt) |
201 | if self.isClient then |
202 | if self:getIsActive() then |
203 | for _, animation in pairs(self.groundParticleAnimations) do |
204 | for _, mapping in pairs(animation.mappings) do |
205 | local refNode = mapping.groundRefNode; |
206 | if refNode ~= nil and refNode.depthNode ~= nil then |
207 | local depth = Utils.clamp(refNode.depth / mapping.maxWorkDepth, 0, 1); |
208 | depth = Utils.clamp(math.min(depth, mapping.lastDepth + refNode.movingDirection*(refNode.movedDistance/0.5)), 0 ,1); |
209 | mapping.lastDepth = depth; |
210 | mapping.speed = mapping.speed - refNode.movedDistance*refNode.movingDirection; |
211 | setVisibility(mapping.animNode, depth ~= 0); |
212 | setShaderParameter(mapping.animNode, "VertxoffsetVertexdeformMotionUVscale", -6, depth, mapping.speed, 1.5, false); |
213 | end; |
214 | end; |
215 | end; |
216 | |
217 | for _,ps in pairs(self.groundParticles) do |
218 | local enabled = self:getDoGroundManipulation(); |
219 | for _, mapping in pairs(ps.mappings) do |
220 | local nodeEnabled = enabled; |
221 | if nodeEnabled then |
222 | nodeEnabled = mapping.groundRefNode.isActive; |
223 | end; |
224 | Utils.setEmittingState(mapping.particles, nodeEnabled); |
225 | end; |
226 | end; |
227 | end; |
228 | end; |
229 | end; |
230 | |
231 | function WorkParticles:draw() |
232 | end; |
233 | |
234 | function WorkParticles:onDeactivate() |
235 | if self.isClient then |
236 | for _,ps in pairs(self.groundParticles) do |
237 | for _, mapping in pairs(ps.mappings) do |
238 | Utils.setEmittingState(mapping.particles, false); |
239 | end; |
240 | end; |
241 | end; |
242 | end; |
243 | |
244 | function WorkParticles:getDoGroundManipulation() |
245 | return self:getLastSpeed() > self.groundManipulationSpeedThreshold; |
246 | end; |
247 | |
248 | function WorkParticles:loadGroundReferenceNodeFromXML(superFunc, groundReferenceNode, xmlFile, key) |
249 | groundReferenceNode.depthNode = Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#depthNode")); |
250 | groundReferenceNode.movedDistance = 0; |
251 | groundReferenceNode.depth = 0; |
252 | |
253 | if superFunc ~= nil then |
254 | return superFunc(self, groundReferenceNode, xmlFile, key); |
255 | end; |
256 | return true; |
257 | end; |
258 | |
259 | function WorkParticles:updateGroundReferenceNode(groundReferenceNode, x, y, z, terrainHeight) |
260 | if self.isClient and groundReferenceNode.depthNode ~= nil then |
261 | local newX, newY, newZ = getWorldTranslation(groundReferenceNode.depthNode); |
262 | if groundReferenceNode.lastPosition == nil then |
263 | groundReferenceNode.lastPosition = {newX, newY, newZ}; |
264 | end; |
265 | local dx, dy, dz = worldDirectionToLocal(groundReferenceNode.depthNode, newX-groundReferenceNode.lastPosition[1], newY-groundReferenceNode.lastPosition[2], newZ-groundReferenceNode.lastPosition[3]); |
266 | groundReferenceNode.movingDirection = 0; |
267 | if dz > 0.0001 then |
268 | groundReferenceNode.movingDirection = 1; |
269 | elseif dz < -0.0001 then |
270 | groundReferenceNode.movingDirection = -1; |
271 | end; |
272 | groundReferenceNode.movedDistance = Utils.vector3Length(dx, dy, dz); |
273 | groundReferenceNode.lastPosition = {newX, newY, newZ}; |
274 | local terrainHeightDepthNode = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, newX, newY, newZ); |
275 | groundReferenceNode.depth = newY - terrainHeightDepthNode; |
276 | end; |
277 | end;
|
Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de