289 | function ConveyorBelt:onFillUnitFillLevelChanged(fillUnitIndex, fillLevelDelta, fillType, toolType, fillPositionData, appliedDelta) |
290 | local spec = self.spec_conveyorBelt |
291 | if spec.fillUnitIndex == fillUnitIndex then |
292 | local fillLevel = self:getFillUnitFillLevel(fillUnitIndex) |
293 | |
294 | if fillLevelDelta > 0 then |
295 | spec.morphStartPos = 0 |
296 | spec.morphEndPos = math.max(spec.morphEndPos, fillLevel / self:getFillUnitCapacity(fillUnitIndex)) |
297 | spec.isEffectDirty = true |
298 | end |
299 | |
300 | if fillLevelDelta ~= 0 then |
301 | spec.scrollUpdateTime = 1000 |
302 | end |
303 | |
304 | if fillLevel == 0 then |
305 | g_effectManager:stopEffects(spec.effects) |
306 | spec.morphStartPos = 0 |
307 | spec.morphEndPos = 0 |
308 | spec.isEffectDirty = true |
309 | else |
310 | g_effectManager:setFillType(spec.effects, fillType) |
311 | g_effectManager:startEffects(spec.effects) |
312 | end |
313 | end |
314 | end |
44 | function ConveyorBelt:onLoad(savegame) |
45 | |
46 | local spec = self.spec_conveyorBelt |
47 | |
48 | self.showOnMap = true |
49 | |
50 | if self.isClient then |
51 | spec.animationNodes = g_animationManager:loadAnimations(self.xmlFile, "vehicle.conveyorBelt.animationNodes", self.components, self, self.i3dMappings) |
52 | end |
53 | |
54 | spec.effects = g_effectManager:loadEffect(self.xmlFile, "vehicle.conveyorBelt.effects", self.components, self, self.i3dMappings) |
55 | spec.currentDelay = 0 |
56 | table.sort(spec.effects, function(effect1, effect2) return effect1.startDelay < effect2.startDelay end) |
57 | |
58 | for _, effect in pairs(spec.effects) do |
59 | if effect.planeFadeTime ~= nil then |
60 | spec.currentDelay = spec.currentDelay + effect.planeFadeTime |
61 | end |
62 | if effect.setScrollUpdate ~= nil then |
63 | effect:setScrollUpdate(false) |
64 | end |
65 | end |
66 | spec.maxDelay = spec.currentDelay |
67 | |
68 | spec.morphStartPos = 0 |
69 | spec.morphEndPos = 0 |
70 | spec.isEffectDirty = false |
71 | spec.emptyFactor = 1 |
72 | spec.scrollUpdateTime = 0 |
73 | spec.lastScrollUpdate = false |
74 | |
75 | spec.dischargeNodeIndex = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.conveyorBelt#dischargeNodeIndex"), 1) |
76 | self:setCurrentDischargeNodeIndex(spec.dischargeNodeIndex) |
77 | local dischargeNode = self:getDischargeNodeByIndex(spec.dischargeNodeIndex) |
78 | local capacity = self:getFillUnitCapacity(dischargeNode.fillUnitIndex) |
79 | spec.fillUnitIndex = dischargeNode.fillUnitIndex |
80 | spec.startFillLevel = capacity * Utils.getNoNil(getXMLFloat(self.xmlFile, "vehicle.conveyorBelt#startPercentage"), 0.9) |
81 | |
82 | local i = 0 |
83 | while true do |
84 | local key = string.format("vehicle.conveyorBelt.offset(%d)", i) |
85 | if not hasXMLProperty(self.xmlFile, key) then |
86 | break |
87 | end |
88 | |
89 | local movingToolNode = I3DUtil.indexToObject(self.components, getXMLString(self.xmlFile, key.."#movingToolNode"), self.i3dMappings) |
90 | if movingToolNode ~= nil then |
91 | if spec.offsets == nil then |
92 | spec.offsets = {} |
93 | end |
94 | |
95 | local offset = {} |
96 | offset.lastState = 0 |
97 | offset.movingToolNode = movingToolNode |
98 | offset.effects = {} |
99 | local j = 0 |
100 | while true do |
101 | local effectKey = string.format(key..".effect(%d)", j) |
102 | if not hasXMLProperty(self.xmlFile, effectKey) then |
103 | break |
104 | end |
105 | |
106 | local effectIndex = Utils.getNoNil(getXMLInt(self.xmlFile, effectKey.."#index"), 0) |
107 | local effect = spec.effects[effectIndex] |
108 | if effect ~= nil and effect.setOffset ~= nil then |
109 | local entry = {} |
110 | entry.effect = effect |
111 | entry.minValue = Utils.getNoNil(getXMLFloat(self.xmlFile, effectKey.."#minOffset"), 0)*1000 |
112 | entry.maxValue = Utils.getNoNil(getXMLFloat(self.xmlFile, effectKey.."#maxOffset"), 1)*1000 |
113 | entry.inverted = Utils.getNoNil(getXMLBool(self.xmlFile, effectKey.."#inverted"), false) |
114 | table.insert(offset.effects, entry) |
115 | else |
116 | g_logManager:xmlWarning(self.configFileName, "Effect index '%d' not found!", effectIndex) |
117 | end |
118 | j = j + 1 |
119 | end |
120 | |
121 | table.insert(spec.offsets, offset) |
122 | else |
123 | g_logManager:xmlWarning(self.configFileName, "Missing movingToolNode for conveyor offset '%s'!", key) |
124 | end |
125 | i = i + 1 |
126 | end |
127 | end |
318 | function ConveyorBelt:onMovingToolChanged(movingTool, speed, dt) |
319 | local spec = self.spec_conveyorBelt |
320 | if spec.offsets ~= nil then |
321 | local offset = spec.movingToolToOffset[movingTool] |
322 | |
323 | if offset ~= nil then |
324 | local state = Cylindered.getMovingToolState(self, movingTool) |
325 | if state ~= offset.lastState then |
326 | local updateDelay = false |
327 | |
328 | for _, entry in pairs(offset.effects) do |
329 | local effectState = state |
330 | if entry.inverted then |
331 | effectState = 1 - effectState |
332 | end |
333 | |
334 | entry.effect:setOffset(MathUtil.lerp(entry.minValue, entry.maxValue, effectState)) |
335 | updateDelay = true |
336 | end |
337 | |
338 | if updateDelay then |
339 | spec.currentDelay = 0 |
340 | for _, effect in pairs(spec.effects) do |
341 | if effect.planeFadeTime ~= nil then |
342 | spec.currentDelay = spec.currentDelay + effect.planeFadeTime - effect.offset |
343 | end |
344 | end |
345 | end |
346 | |
347 | offset.lastState = state |
348 | end |
349 | end |
350 | end |
351 | end |
131 | function ConveyorBelt:onPostLoad(savegame) |
132 | local spec = self.spec_conveyorBelt |
133 | |
134 | -- we need to check movingTool in post load to avoid order dependencies |
135 | if spec.offsets ~= nil then |
136 | if self.getMovingToolByNode ~= nil then |
137 | spec.movingToolToOffset = {} |
138 | for i=#spec.offsets, 1, -1 do |
139 | local offset = spec.offsets[i] |
140 | local movingTool = self:getMovingToolByNode(offset.movingToolNode) |
141 | if movingTool ~= nil then |
142 | offset.movingTool = movingTool |
143 | spec.movingToolToOffset[movingTool] = offset |
144 | ConveyorBelt.onMovingToolChanged(self, movingTool, 0, 0) |
145 | else |
146 | g_logManager:xmlWarning(self.configFileName, "No movingTool node '%s' defined for conveyor offset '%d'!", getName(offset.movingToolNode), i) |
147 | table.remove(spec.offsets, i) |
148 | end |
149 | end |
150 | |
151 | if #spec.offsets == 0 then |
152 | spec.offsets = nil |
153 | spec.movingToolToOffset = nil |
154 | end |
155 | else |
156 | g_logManager:xmlError(self.configFileName, "'Cylindered' specialization is required to use conveyorBelt offsets!") |
157 | spec.offsets = nil |
158 | end |
159 | end |
160 | end |
175 | function ConveyorBelt:onUpdateTick(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
176 | if self.isClient then |
177 | local spec = self.spec_conveyorBelt |
178 | |
179 | local isBeltActive = self:getDischargeState() ~= Dischargeable.DISCHARGE_STATE_OFF |
180 | if isBeltActive then |
181 | local fillLevel = self:getFillUnitFillLevel(spec.fillUnitIndex) |
182 | if fillLevel > 0.0001 then |
183 | local movedFactor = dt / spec.currentDelay |
184 | spec.morphStartPos = MathUtil.clamp(spec.morphStartPos + movedFactor, 0, 1) |
185 | spec.morphEndPos = MathUtil.clamp(spec.morphEndPos + movedFactor, 0, 1) |
186 | |
187 | -- we calculate the empty factor based on visual effect mesh and filllevel to get a smooth transition |
188 | local fillFactor = fillLevel/self:getFillUnitCapacity(spec.fillUnitIndex) |
189 | local visualFactor = spec.morphEndPos-spec.morphStartPos |
190 | |
191 | spec.emptyFactor = 1 |
192 | if visualFactor > fillFactor then |
193 | spec.emptyFactor = MathUtil.clamp(fillFactor/visualFactor, 0, 1) |
194 | else |
195 | local offset = fillFactor - visualFactor |
196 | spec.offset = offset |
197 | spec.morphStartPos = MathUtil.clamp(spec.morphStartPos - (offset/((1-spec.morphStartPos)*spec.currentDelay))*dt , 0, 1) |
198 | end |
199 | |
200 | spec.isEffectDirty = true |
201 | end |
202 | end |
203 | |
204 | if spec.isEffectDirty then |
205 | for _, effect in pairs(spec.effects) do |
206 | if effect.setMorphPosition ~= nil then |
207 | local effectStart = effect.startDelay/spec.currentDelay |
208 | local effectEnd = (effect.startDelay+effect.planeFadeTime-effect.offset)/spec.currentDelay |
209 | local offsetFactor = effect.offset/effect.planeFadeTime |
210 | |
211 | local startMorphFactor = (spec.morphStartPos-effectStart)/(effectEnd-effectStart) |
212 | local startMorph = MathUtil.clamp(offsetFactor + startMorphFactor*(1-offsetFactor), offsetFactor, 1) |
213 | |
214 | local endMorphFactor = (spec.morphEndPos-effectStart)/(effectEnd-effectStart) |
215 | local endMorph = MathUtil.clamp(offsetFactor + endMorphFactor*(1-offsetFactor), offsetFactor, 1) |
216 | |
217 | --renderText(0.6, 0.8-i*0.015, 0.012, string.format("%d: effectStart %.4f effectEnd %.4f -> startMorph %.4f endMorph %.4f | offset %.4f | %.4f %.4f", i, effectStart, effectEnd, startMorph, endMorph, effect.offset/effect.planeFadeTime, (spec.morphStartPos-effectStart)/(effectEnd-effectStart), (spec.morphEndPos-effectStart)/(effectEnd-effectStart))) |
218 | effect:setMorphPosition(startMorph, endMorph) |
219 | end |
220 | end |
221 | spec.isEffectDirty = false |
222 | end |
223 | |
224 | spec.scrollUpdateTime = math.max(spec.scrollUpdateTime - dt, 0) |
225 | local doScrollUpdate = spec.scrollUpdateTime > 0 |
226 | if doScrollUpdate ~= spec.lastScrollUpdate then |
227 | if doScrollUpdate then |
228 | g_animationManager:startAnimations(spec.animationNodes) |
229 | else |
230 | g_animationManager:stopAnimations(spec.animationNodes) |
231 | end |
232 | |
233 | for _, effect in pairs(spec.effects) do |
234 | if effect.setScrollUpdate ~= nil then |
235 | effect:setScrollUpdate(doScrollUpdate) |
236 | end |
237 | end |
238 | |
239 | spec.lastScrollUpdate = doScrollUpdate |
240 | end |
241 | end |
242 | end |