202 | function WindrowerEffect:getCurrentTestAreaWidth(real) |
203 | local minX = self.width / 2 + self.dropOffset |
204 | local maxX = -self.width / 2 - self.dropOffset |
205 | local foundFillType = FillType.UNKNOWN |
206 | |
207 | for _, testArea in ipairs(self.testAreas) do |
208 | local x0, y0, z0 = getWorldTranslation(testArea.start) |
209 | local x1, y1, z1 = getWorldTranslation(testArea.width) |
210 | local x2, _, z2 = getWorldTranslation(testArea.height) |
211 | |
212 | local fillType = DensityMapHeightUtil.getFillTypeAtArea(x0,z0, x1,z1, x2,z2) |
213 | if fillType ~= FillType.UNKNOWN then |
214 | local xStart, _, _ = worldToLocal(self.node, x0, y0, z0) |
215 | local xWidth, _, _ = worldToLocal(self.node, x1, y1, z1) |
216 | |
217 | if xStart < minX then |
218 | minX = xStart |
219 | end |
220 | |
221 | if xWidth > maxX then |
222 | maxX = xWidth |
223 | end |
224 | |
225 | foundFillType = fillType |
226 | end |
227 | end |
228 | |
229 | if not real or real == nil then |
230 | if self.unloadDirection ~= 0 then |
231 | if self.unloadDirection < 0 then |
232 | minX = -self.width / 2 - self.dropOffset |
233 | end |
234 | |
235 | if self.unloadDirection > 0 then |
236 | maxX = self.width / 2 + self.dropOffset |
237 | end |
238 | end |
239 | end |
240 | |
241 | return minX, maxX, foundFillType |
242 | end |
22 | function WindrowerEffect:loadEffectAttributes(xmlFile, key, node, i3dNode, i3dMapping) |
23 | if not WindrowerEffect:superClass().loadEffectAttributes(self, xmlFile, key, node, i3dNode, i3dMapping) then |
24 | return false |
25 | end |
26 | |
27 | self.unloadDirection = Utils.getNoNil(Effect.getValue(xmlFile, key, getXMLInt, node, "unloadDirection"), 0) |
28 | self.width = Utils.getNoNil(Effect.getValue(xmlFile, key, getXMLInt, node, "width"), 0) |
29 | self.dropOffset = Utils.getNoNil(Effect.getValue(xmlFile, key, getXMLInt, node, "dropOffset"), 0) |
30 | self.turnOffRequiredEffect = Utils.getNoNil(Effect.getValue(xmlFile, key, getXMLInt, node, "turnOffRequiredEffect"), 0) |
31 | self.testAreas = {} |
32 | |
33 | local i = 0 |
34 | while true do |
35 | local areaKey = key..string.format(".testArea(%d)", i) |
36 | if not hasXMLProperty(xmlFile, areaKey) then |
37 | break |
38 | end |
39 | |
40 | local start = I3DUtil.indexToObject(self.rootNodes, Effect.getValue(xmlFile, areaKey, getXMLString, node, "startNode"), i3dMapping) |
41 | local width = I3DUtil.indexToObject(self.rootNodes, Effect.getValue(xmlFile, areaKey, getXMLString, node, "widthNode"), i3dMapping) |
42 | local height = I3DUtil.indexToObject(self.rootNodes, Effect.getValue(xmlFile, areaKey, getXMLString, node, "heightNode"), i3dMapping) |
43 | |
44 | table.insert(self.testAreas, {start=start, width=width, height=height}) |
45 | |
46 | i = i + 1 |
47 | end |
48 | |
49 | self.particleSystems = {} |
50 | i = 0 |
51 | while true do |
52 | local particleKey = key..string.format(".particleSystem(%d)", i) |
53 | if not hasXMLProperty(xmlFile, particleKey) then |
54 | break |
55 | end |
56 | |
57 | local emitterShape = I3DUtil.indexToObject(self.rootNodes, getXMLString(xmlFile, particleKey.."#emitterShape"), i3dMapping) |
58 | local particleType = getXMLString(xmlFile, particleKey.."#particleType") |
59 | local fillTypeNames = Utils.getNoNil(getXMLString(xmlFile, particleKey.."#fillTypes"), "grass_windrow dryGrass_windrow straw") |
60 | local fadeInRange = StringUtil.getVectorNFromString(getXMLString(xmlFile, particleKey.."#fadeInRange"), 2) |
61 | local fadeOutRange = StringUtil.getVectorNFromString(getXMLString(xmlFile, particleKey.."#fadeOutRange"), 2) |
62 | |
63 | if emitterShape ~= nil then |
64 | local x, y, z = getWorldTranslation(emitterShape) |
65 | local xOffset, _, _ = worldToLocal(self.node, x, y, z) |
66 | local particleSystems = {} |
67 | |
68 | local fillTypes = g_fillTypeManager:getFillTypesByNames(fillTypeNames) |
69 | for _, fillType in pairs(fillTypes) do |
70 | local particleSystem = g_particleSystemManager:getParticleSystem(fillType, particleType) |
71 | if particleSystem ~= nil then |
72 | local ps = ParticleUtil.copyParticleSystem(xmlFile, particleKey, particleSystem, emitterShape) |
73 | ps.fillType = fillType |
74 | |
75 | table.insert(particleSystems, ps) |
76 | end |
77 | end |
78 | |
79 | table.insert(self.particleSystems, {xOffset=xOffset, fadeInRange=fadeInRange, fadeOutRange=fadeOutRange, particleSystems=particleSystems}) |
80 | end |
81 | |
82 | i = i + 1 |
83 | end |
84 | |
85 | self.lastChargeTime = 0 |
86 | self.updateTick = 0 |
87 | self.scrollUpdate = false |
88 | self.particleSystemsTurnedOff = false |
89 | |
90 | return true |
91 | end |
105 | function WindrowerEffect:update(dt) |
106 | WindrowerEffect:superClass().update(self, dt) |
107 | |
108 | if self.updateTick > 5 and self.state ~= ShaderPlaneEffect.STATE_OFF then |
109 | local minX, maxX, foundFillType = WindrowerEffect.getCurrentTestAreaWidth(self) |
110 | setShaderParameter(self.node, "offsetUV", self.scrollPosition, 0, minX, maxX, false) |
111 | |
112 | for _, particleSystemData in ipairs(self.particleSystems) do |
113 | local inFadeInRange = self.fadeCur[1] >= particleSystemData.fadeInRange[1] and self.fadeCur[1] <= particleSystemData.fadeInRange[2] |
114 | local inFadeOutRange = self.fadeCur[2] >= particleSystemData.fadeOutRange[1] and self.fadeCur[2] <= particleSystemData.fadeOutRange[2] |
115 | |
116 | local inXRange = minX <= particleSystemData.xOffset and maxX >= particleSystemData.xOffset |
117 | if inXRange and inFadeInRange and inFadeOutRange and self.state ~= ShaderPlaneEffect.STATE_OFF then |
118 | for _, ps in ipairs(particleSystemData.particleSystems) do |
119 | ParticleUtil.setEmittingState(ps, ps.fillType == foundFillType) |
120 | end |
121 | else |
122 | for _, ps in ipairs(particleSystemData.particleSystems) do |
123 | ParticleUtil.setEmittingState(ps, false) |
124 | end |
125 | end |
126 | end |
127 | |
128 | self.updateTick = 0 |
129 | self.particleSystemsTurnedOff = false |
130 | elseif not self.particleSystemsTurnedOff then |
131 | for _, particleSystemData in ipairs(self.particleSystems) do |
132 | for _, ps in ipairs(particleSystemData.particleSystems) do |
133 | ParticleUtil.setEmittingState(ps, false) |
134 | end |
135 | end |
136 | |
137 | self.particleSystemsTurnedOff = true |
138 | end |
139 | |
140 | local _, y, z, w = getShaderParameter(self.node, "offsetUV") |
141 | self.scrollPosition = (self.scrollPosition + dt*self.scrollSpeed) % self.scrollLength |
142 | setShaderParameter(self.node, "offsetUV", self.scrollPosition, y, z, w, false) |
143 | |
144 | self.updateTick = self.updateTick + 1 |
145 | end |