Coverage Report

Created: 2026-01-10 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/src/OgreScriptTranslator.cpp
Line
Count
Source
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
(Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
15
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
18
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
THE SOFTWARE.
26
-----------------------------------------------------------------------------
27
*/
28
29
#include "OgreStableHeaders.h"
30
#include "OgreBuiltinScriptTranslators.h"
31
#include "OgreGpuProgramManager.h"
32
#include "OgreHighLevelGpuProgramManager.h"
33
#include "OgreParticleSystemRenderer.h"
34
#include "OgreParticleEmitter.h"
35
#include "OgreParticleAffector.h"
36
#include "OgreCompositor.h"
37
#include "OgreCompositorManager.h"
38
#include "OgreCompositionTargetPass.h"
39
#include "OgreCompositionPass.h"
40
#include "OgreExternalTextureSourceManager.h"
41
#include "OgreLodStrategyManager.h"
42
#include "OgreDistanceLodStrategy.h"
43
#include "OgreParticleSystem.h"
44
#include "OgreHighLevelGpuProgram.h"
45
#include "OgreGpuProgramUsage.h"
46
47
namespace Ogre{
48
    static void applyTextureAliases(ScriptCompiler *compiler, const Material* mat, const NameValuePairList& aliasList)
49
0
    {
50
0
        for (auto t : mat->getTechniques())
51
0
        {
52
0
            for (auto p : t->getPasses())
53
0
            {
54
0
                for (auto tus : p->getTextureUnitStates())
55
0
                {
56
0
                    auto aliasIt = aliasList.find(tus->getName());
57
0
                    if (aliasIt == aliasList.end())
58
0
                        continue;
59
60
0
                    ProcessResourceNameScriptCompilerEvent evt(ProcessResourceNameScriptCompilerEvent::TEXTURE, aliasIt->second);
61
0
                    compiler->_fireEvent(&evt, 0);
62
63
0
                    if (tus->getNumFrames() > 1)
64
0
                        tus->setAnimatedTextureName(evt.mName, tus->getNumFrames(),
65
0
                                                    tus->getAnimationDuration());
66
0
                    else
67
0
                        tus->setTextureName(evt.mName, tus->getTextureType());
68
0
                }
69
0
            }
70
0
        }
71
0
    }
72
73
    template <typename T>
74
    bool getValue(const AbstractNodePtr &node, T& result);
75
    template<> bool getValue(const AbstractNodePtr &node, float& result)
76
0
    {
77
0
        return StringConverter::parse(node->getString(), result);
78
0
    }
79
    template<> bool getValue(const AbstractNodePtr &node, double& result)
80
0
    {
81
0
        return StringConverter::parse(node->getString(), result);
82
0
    }
83
    template<> bool getValue(const AbstractNodePtr &node, bool& result)
84
0
    {
85
0
        return ScriptTranslator::getBoolean(node, &result);
86
0
    }
87
    template<> bool getValue(const AbstractNodePtr &node, uint32& result)
88
0
    {
89
0
        return StringConverter::parse(node->getString(), result);
90
0
    }
91
    template<> bool getValue(const AbstractNodePtr &node, int32& result)
92
0
    {
93
0
        return StringConverter::parse(node->getString(), result);
94
0
    }
95
    template<> bool getValue(const AbstractNodePtr &node, String& result)
96
0
    {
97
0
        return ScriptTranslator::getString(node, &result);
98
0
    }
99
100
    template<> bool getValue(const AbstractNodePtr& node, CompareFunction& result)
101
0
    {
102
0
        return ScriptTranslator::getCompareFunction(node, &result);
103
0
    }
104
105
    template<> bool getValue(const AbstractNodePtr& node, StencilOperation& result)
106
0
    {
107
0
        return ScriptTranslator::getStencilOp(node, &result);
108
0
    }
109
110
    template<> bool getValue(const AbstractNodePtr& node, IlluminationStage& result)
111
0
    {
112
0
        if(node->type != ANT_ATOM)
113
0
            return false;
114
115
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
116
0
        {
117
0
        case ID_AMBIENT:
118
0
            result = IS_AMBIENT;
119
0
            return true;
120
0
        case ID_PER_LIGHT:
121
0
            result = IS_PER_LIGHT;
122
0
            return true;
123
0
        case ID_DECAL:
124
0
            result = IS_DECAL;
125
0
            return true;
126
0
        default:
127
0
            return false;
128
0
        }
129
0
    }
130
131
    template<> bool getValue(const AbstractNodePtr& node, SceneBlendType& result)
132
0
    {
133
0
        if(node->type != ANT_ATOM)
134
0
            return false;
135
136
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
137
0
        {
138
0
        case ID_ADD:
139
0
            result = SBT_ADD;
140
0
            break;
141
0
        case ID_MODULATE:
142
0
            result = SBT_MODULATE;
143
0
            break;
144
0
        case ID_COLOUR_BLEND:
145
0
            result = SBT_TRANSPARENT_COLOUR;
146
0
            break;
147
0
        case ID_ALPHA_BLEND:
148
0
            result = SBT_TRANSPARENT_ALPHA;
149
0
            break;
150
0
        default:
151
0
            return false;
152
0
        }
153
0
        return true;
154
0
    }
155
156
    template<> bool getValue(const AbstractNodePtr& node, SceneBlendOperation& result)
157
0
    {
158
0
        if(node->type != ANT_ATOM)
159
0
            return false;
160
161
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
162
0
        {
163
0
        case ID_ADD:
164
0
            result = SBO_ADD;
165
0
            break;
166
0
        case ID_SUBTRACT:
167
0
            result = SBO_SUBTRACT;
168
0
            break;
169
0
        case ID_REVERSE_SUBTRACT:
170
0
            result = SBO_REVERSE_SUBTRACT;
171
0
            break;
172
0
        case ID_MIN:
173
0
            result = SBO_MIN;
174
0
            break;
175
0
        case ID_MAX:
176
0
            result = SBO_MAX;
177
0
            break;
178
0
        default:
179
0
            return false;
180
0
        }
181
0
        return true;
182
0
    }
183
184
    template<> bool getValue(const AbstractNodePtr& node, CullingMode& result)
185
0
    {
186
0
        if(node->type != ANT_ATOM)
187
0
            return false;
188
189
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
190
0
        {
191
0
        case ID_CLOCKWISE:
192
0
            result = CULL_CLOCKWISE;
193
0
            break;
194
0
        case ID_ANTICLOCKWISE:
195
0
            result = CULL_ANTICLOCKWISE;
196
0
            break;
197
0
        case ID_NONE:
198
0
            result = CULL_NONE;
199
0
            break;
200
0
        default:
201
0
            return false;
202
0
        }
203
0
        return true;
204
0
    }
205
206
    template<> bool getValue(const AbstractNodePtr& node, ManualCullingMode& result)
207
0
    {
208
0
        if(node->type != ANT_ATOM)
209
0
            return false;
210
211
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
212
0
        {
213
0
        case ID_FRONT:
214
0
            result = MANUAL_CULL_FRONT;
215
0
            break;
216
0
        case ID_BACK:
217
0
            result = MANUAL_CULL_BACK;
218
0
            break;
219
0
        case ID_NONE:
220
0
            result = MANUAL_CULL_NONE;
221
0
            break;
222
0
        default:
223
0
            return false;
224
0
        }
225
0
        return true;
226
0
    }
227
228
    template<> bool getValue(const AbstractNodePtr& node, ShadeOptions& result)
229
0
    {
230
0
        if(node->type != ANT_ATOM)
231
0
            return false;
232
233
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
234
0
        {
235
0
        case ID_FLAT:
236
0
            result = SO_FLAT;
237
0
            break;
238
0
        case ID_GOURAUD:
239
0
            result = SO_GOURAUD;
240
0
            break;
241
0
        case ID_PHONG:
242
0
            result = SO_PHONG;
243
0
            break;
244
0
        default:
245
0
            return false;
246
0
        }
247
0
        return true;
248
0
    }
249
250
    template<> bool getValue(const AbstractNodePtr& node, PolygonMode& result)
251
0
    {
252
0
        if(node->type != ANT_ATOM)
253
0
            return false;
254
255
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
256
0
        {
257
0
        case ID_SOLID:
258
0
            result = PM_SOLID;
259
0
            break;
260
0
        case ID_POINTS:
261
0
            result = PM_POINTS;
262
0
            break;
263
0
        case ID_WIREFRAME:
264
0
            result = PM_WIREFRAME;
265
0
            break;
266
0
        default:
267
0
            return false;
268
0
        }
269
0
        return true;
270
0
    }
271
272
    template<> bool getValue(const AbstractNodePtr& node, LayerBlendOperation& result)
273
0
    {
274
0
        if(node->type != ANT_ATOM)
275
0
            return false;
276
277
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
278
0
        {
279
0
        case ID_REPLACE:
280
0
            result = LBO_REPLACE;
281
0
            break;
282
0
        case ID_ADD:
283
0
            result = LBO_ADD;
284
0
            break;
285
0
        case ID_MODULATE:
286
0
            result = LBO_MODULATE;
287
0
            break;
288
0
        case ID_ALPHA_BLEND:
289
0
            result = LBO_ALPHA_BLEND;
290
0
            break;
291
0
        default:
292
0
            return false;
293
0
        }
294
0
        return true;
295
0
    }
296
297
    template<> bool getValue(const AbstractNodePtr& node, LayerBlendOperationEx& op)
298
0
    {
299
0
        if(node->type != ANT_ATOM)
300
0
            return false;
301
302
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
303
0
        {
304
0
        case ID_SOURCE1:
305
0
            op = LBX_SOURCE1;
306
0
            break;
307
0
        case ID_SOURCE2:
308
0
            op = LBX_SOURCE2;
309
0
            break;
310
0
        case ID_MODULATE:
311
0
            op = LBX_MODULATE;
312
0
            break;
313
0
        case ID_MODULATE_X2:
314
0
            op = LBX_MODULATE_X2;
315
0
            break;
316
0
        case ID_MODULATE_X4:
317
0
            op = LBX_MODULATE_X4;
318
0
            break;
319
0
        case ID_ADD:
320
0
            op = LBX_ADD;
321
0
            break;
322
0
        case ID_ADD_SIGNED:
323
0
            op = LBX_ADD_SIGNED;
324
0
            break;
325
0
        case ID_ADD_SMOOTH:
326
0
            op = LBX_ADD_SMOOTH;
327
0
            break;
328
0
        case ID_SUBTRACT:
329
0
            op = LBX_SUBTRACT;
330
0
            break;
331
0
        case ID_BLEND_DIFFUSE_ALPHA:
332
0
            op = LBX_BLEND_DIFFUSE_ALPHA;
333
0
            break;
334
0
        case ID_BLEND_TEXTURE_ALPHA:
335
0
            op = LBX_BLEND_TEXTURE_ALPHA;
336
0
            break;
337
0
        case ID_BLEND_CURRENT_ALPHA:
338
0
            op = LBX_BLEND_CURRENT_ALPHA;
339
0
            break;
340
0
        case ID_BLEND_MANUAL:
341
0
            op = LBX_BLEND_MANUAL;
342
0
            break;
343
0
        case ID_DOT_PRODUCT:
344
0
            op = LBX_DOTPRODUCT;
345
0
            break;
346
0
        case ID_BLEND_DIFFUSE_COLOUR:
347
0
            op = LBX_BLEND_DIFFUSE_COLOUR;
348
0
            break;
349
0
        default:
350
0
            return false;
351
0
        }
352
0
        return true;
353
0
    }
354
355
    template<> bool getValue(const AbstractNodePtr& node, LayerBlendSource& source1)
356
0
    {
357
0
        if(node->type != ANT_ATOM)
358
0
            return false;
359
360
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
361
0
        {
362
0
        case ID_SRC_CURRENT:
363
0
            source1 = LBS_CURRENT;
364
0
            break;
365
0
        case ID_SRC_TEXTURE:
366
0
            source1 = LBS_TEXTURE;
367
0
            break;
368
0
        case ID_SRC_DIFFUSE:
369
0
            source1 = LBS_DIFFUSE;
370
0
            break;
371
0
        case ID_SRC_SPECULAR:
372
0
            source1 = LBS_SPECULAR;
373
0
            break;
374
0
        case ID_SRC_MANUAL:
375
0
            source1 = LBS_MANUAL;
376
0
            break;
377
0
        default:
378
0
            return false;
379
0
        }
380
0
        return true;
381
0
    }
382
383
    template<> bool getValue(const AbstractNodePtr& node, CompositionTargetPass::InputMode& result)
384
0
    {
385
0
        if(node->type != ANT_ATOM)
386
0
            return false;
387
388
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
389
0
        {
390
0
        case ID_NONE:
391
0
            result = CompositionTargetPass::IM_NONE;
392
0
            break;
393
0
        case ID_PREVIOUS:
394
0
            result = CompositionTargetPass::IM_PREVIOUS;
395
0
            break;
396
0
        default:
397
0
            return false;
398
0
        }
399
0
        return true;
400
0
    }
401
402
    template<> bool getValue(const AbstractNodePtr& node, FilterOptions& tmip)
403
0
    {
404
0
        if(node->type != ANT_ATOM)
405
0
            return false;
406
407
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
408
0
        {
409
0
        case ID_NONE:
410
0
            tmip = FO_NONE;
411
0
            break;
412
0
        case ID_POINT:
413
0
            tmip = FO_POINT;
414
0
            break;
415
0
        case ID_LINEAR:
416
0
            tmip = FO_LINEAR;
417
0
            break;
418
0
        case ID_ANISOTROPIC:
419
0
            tmip = FO_ANISOTROPIC;
420
0
            break;
421
0
        default:
422
0
            return false;
423
0
        }
424
0
        return true;
425
0
    }
426
427
    template<> bool getValue(const AbstractNodePtr& node, TextureAddressingMode& result)
428
0
    {
429
0
        if(node->type != ANT_ATOM)
430
0
            return false;
431
432
0
        switch (static_cast<AtomAbstractNode*>(node.get())->id)
433
0
        {
434
0
        case ID_WRAP:
435
0
            result = TextureUnitState::TAM_WRAP;
436
0
            break;
437
0
        case ID_CLAMP:
438
0
            result = TextureUnitState::TAM_CLAMP;
439
0
            break;
440
0
        case ID_MIRROR:
441
0
            result = TextureUnitState::TAM_MIRROR;
442
0
            break;
443
0
        case ID_BORDER:
444
0
            result = TextureUnitState::TAM_BORDER;
445
0
            break;
446
0
        default:
447
0
            return false;
448
0
        }
449
0
        return true;
450
0
    }
451
452
    template <typename T>
453
    static bool getValue(PropertyAbstractNode* prop, ScriptCompiler *compiler, T& val)
454
0
    {
455
0
        if (prop->values.size() > 1)
456
0
        {
457
0
            compiler->addError(*prop, prop->name + " must have at most 1 argument",
458
0
                               ScriptCompiler::CE_FEWERPARAMETERSEXPECTED);
459
0
        }
460
0
        else
461
0
        {
462
0
            if (getValue(prop->values.front(), val))
463
0
                return true;
464
0
            else
465
0
                compiler->addError(*prop, prop->values.front()->getValue() + " is not a valid value for " + prop->name);
466
0
        }
467
468
0
        return false;
469
0
    }
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<bool>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, bool&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<unsigned int>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, unsigned int&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<Ogre::SceneBlendOperation>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, Ogre::SceneBlendOperation&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<Ogre::CompareFunction>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, Ogre::CompareFunction&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<float>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, float&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<Ogre::IlluminationStage>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, Ogre::IlluminationStage&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<Ogre::CullingMode>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, Ogre::CullingMode&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<Ogre::ManualCullingMode>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, Ogre::ManualCullingMode&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<Ogre::ShadeOptions>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, Ogre::ShadeOptions&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<Ogre::PolygonMode>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, Ogre::PolygonMode&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<Ogre::LayerBlendOperation>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, Ogre::LayerBlendOperation&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<Ogre::CompositionTargetPass::InputMode>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, Ogre::CompositionTargetPass::InputMode&)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::getValue<Ogre::StencilOperation>(Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*, Ogre::StencilOperation&)
470
471
    template <typename T>
472
    static bool _getVector(AbstractNodeList::const_iterator i, AbstractNodeList::const_iterator end,
473
                          std::vector<T>& vals, size_t count)
474
0
    {
475
0
        vals.reserve(count);
476
0
        size_t n = 0;
477
0
        while (n < count)
478
0
        {
479
0
            if (i != end)
480
0
            {
481
0
                T v;
482
0
                if (!getValue(*i++, v))
483
0
                    return false;
484
0
                vals.push_back(v);
485
0
            }
486
0
            ++n;
487
0
        }
488
489
0
        vals.resize(count);
490
0
        return true;
491
0
    }
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::_getVector<int>(std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::vector<int, std::__1::allocator<int> >&, unsigned long)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::_getVector<float>(std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::vector<float, std::__1::allocator<float> >&, unsigned long)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::_getVector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, unsigned long)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::_getVector<bool>(std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::vector<bool, std::__1::allocator<bool> >&, unsigned long)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::_getVector<double>(std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::vector<double, std::__1::allocator<double> >&, unsigned long)
Unexecuted instantiation: OgreScriptTranslator.cpp:bool Ogre::_getVector<unsigned int>(std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> >&, unsigned long)
492
493
    static GpuProgramType getProgramType(int id)
494
0
    {
495
0
        switch(id)
496
0
        {
497
0
        default:
498
0
            assert(false);
499
0
            OGRE_FALLTHROUGH;
500
0
        case ID_VERTEX_PROGRAM:
501
0
        case ID_VERTEX_PROGRAM_REF:
502
0
            return GPT_VERTEX_PROGRAM;
503
0
        case ID_FRAGMENT_PROGRAM:
504
0
        case ID_FRAGMENT_PROGRAM_REF:
505
0
            return GPT_FRAGMENT_PROGRAM;
506
0
        case ID_GEOMETRY_PROGRAM:
507
0
        case ID_GEOMETRY_PROGRAM_REF:
508
0
            return GPT_GEOMETRY_PROGRAM;
509
0
        case ID_TESSELLATION_DOMAIN_PROGRAM:
510
0
        case ID_TESSELLATION_DOMAIN_PROGRAM_REF:
511
0
            return GPT_DOMAIN_PROGRAM;
512
0
        case ID_TESSELLATION_HULL_PROGRAM:
513
0
        case ID_TESSELLATION_HULL_PROGRAM_REF:
514
0
            return GPT_HULL_PROGRAM;
515
0
        case ID_COMPUTE_PROGRAM:
516
0
        case ID_COMPUTE_PROGRAM_REF:
517
0
            return GPT_COMPUTE_PROGRAM;
518
0
        case ID_MESH_PROGRAM:
519
0
        case ID_MESH_PROGRAM_REF:
520
0
            return GPT_MESH_PROGRAM;
521
0
        case ID_TASK_PROGRAM:
522
0
        case ID_TASK_PROGRAM_REF:
523
0
            return GPT_TASK_PROGRAM;
524
0
        }
525
0
    }
526
527
    void ScriptTranslator::processNode(ScriptCompiler *compiler, const AbstractNodePtr &node)
528
0
    {
529
0
        if(node->type != ANT_OBJECT)
530
0
            return;
531
532
        // Abstract objects are completely skipped
533
0
        if((static_cast<ObjectAbstractNode*>(node.get()))->abstract)
534
0
            return;
535
536
        // Retrieve the translator to use
537
0
        ScriptTranslator *translator =
538
0
            ScriptCompilerManager::getSingleton().getTranslator(node);
539
540
0
        if(translator)
541
0
            translator->translate(compiler, node);
542
0
        else
543
0
            compiler->addError(ScriptCompiler::CE_UNEXPECTEDTOKEN, node->file, node->line,
544
0
                               "token \"" + static_cast<ObjectAbstractNode*>(node.get())->cls + "\" is not recognized");
545
0
    }
546
    //-------------------------------------------------------------------------
547
    AbstractNodeList::const_iterator ScriptTranslator::getNodeAt(const AbstractNodeList &nodes, size_t index)
548
0
    {
549
0
        if(index >= nodes.size())
550
0
            return nodes.end();
551
552
0
        return std::next(nodes.begin(), index);
553
0
    }
554
    //-------------------------------------------------------------------------
555
    bool ScriptTranslator::getBoolean(const AbstractNodePtr &node, bool *result)
556
0
    {
557
0
        if (node->type != ANT_ATOM)
558
0
            return false;
559
0
        AtomAbstractNode *atom = (AtomAbstractNode*)node.get();
560
0
     if (atom->id == 1 || atom->id == 2)
561
0
    {
562
0
      *result = atom->id == 1 ? true : false;
563
0
      return true;
564
0
    }
565
        //     return false;
566
0
    return false;
567
0
    }
568
    //-------------------------------------------------------------------------
569
    bool ScriptTranslator::getString(const AbstractNodePtr &node, String *result)
570
0
    {
571
0
        if(node->type != ANT_ATOM)
572
0
            return false;
573
0
        AtomAbstractNode *atom = (AtomAbstractNode*)node.get();
574
0
        *result = atom->value;
575
0
        return true;
576
0
    }
577
    //-------------------------------------------------------------------------
578
    bool ScriptTranslator::getFloat(const Ogre::AbstractNodePtr &node, float *result)
579
0
    {
580
0
        return StringConverter::parse(node->getString(), *result);
581
0
    }
582
    //-------------------------------------------------------------------------
583
    bool ScriptTranslator::getDouble(const Ogre::AbstractNodePtr &node, double *result)
584
0
    {
585
0
        return StringConverter::parse(node->getString(), *result);
586
0
    }
587
    //-------------------------------------------------------------------------
588
    bool ScriptTranslator::getInt(const Ogre::AbstractNodePtr &node, int *result)
589
0
    {
590
0
        return StringConverter::parse(node->getString(), *result);
591
0
    }
592
    //-------------------------------------------------------------------------
593
    bool ScriptTranslator::getUInt(const Ogre::AbstractNodePtr &node, uint *result)
594
0
    {
595
0
        return StringConverter::parse(node->getString(), *result);
596
0
    }
597
    //-------------------------------------------------------------------------
598
    bool ScriptTranslator::getColour(AbstractNodeList::const_iterator i, AbstractNodeList::const_iterator end, ColourValue *result, int maxEntries)
599
0
    {
600
0
        int n = 0;
601
0
        while(i != end && n < maxEntries)
602
0
        {
603
0
            float v = 0;
604
0
            if(getFloat(*i, &v))
605
0
            {
606
0
                switch(n)
607
0
                {
608
0
                case 0:
609
0
                    result->r = v;
610
0
                    break;
611
0
                case 1:
612
0
                    result->g = v;
613
0
                    break;
614
0
                case 2:
615
0
                    result->b = v;
616
0
                    break;
617
0
                case 3:
618
0
                    result->a = v;
619
0
                    break;
620
0
                }
621
0
            }
622
0
            else
623
0
            {
624
0
                return false;
625
0
            }
626
0
            ++n;
627
0
            ++i;
628
0
        }
629
        // return error if we found less than rgb before end, unless constrained
630
0
        return (n >= 3 || n == maxEntries);
631
0
    }
632
    //-------------------------------------------------------------------------
633
    bool ScriptTranslator::getSceneBlendFactor(const Ogre::AbstractNodePtr &node, Ogre::SceneBlendFactor *sbf)
634
0
    {
635
0
        if(node->type != ANT_ATOM)
636
0
            return false;
637
0
        AtomAbstractNode *atom = (AtomAbstractNode*)node.get();
638
0
        switch(atom->id)
639
0
        {
640
0
        case ID_ONE:
641
0
            *sbf = SBF_ONE;
642
0
            break;
643
0
        case ID_ZERO:
644
0
            *sbf = SBF_ZERO;
645
0
            break;
646
0
        case ID_DEST_COLOUR:
647
0
            *sbf = SBF_DEST_COLOUR;
648
0
            break;
649
0
        case ID_DEST_ALPHA:
650
0
            *sbf = SBF_DEST_ALPHA;
651
0
            break;
652
0
        case ID_SRC_ALPHA:
653
0
            *sbf = SBF_SOURCE_ALPHA;
654
0
            break;
655
0
        case ID_SRC_COLOUR:
656
0
            *sbf = SBF_SOURCE_COLOUR;
657
0
            break;
658
0
        case ID_ONE_MINUS_DEST_COLOUR:
659
0
            *sbf = SBF_ONE_MINUS_DEST_COLOUR;
660
0
            break;
661
0
        case ID_ONE_MINUS_SRC_COLOUR:
662
0
            *sbf = SBF_ONE_MINUS_SOURCE_COLOUR;
663
0
            break;
664
0
        case ID_ONE_MINUS_DEST_ALPHA:
665
0
            *sbf = SBF_ONE_MINUS_DEST_ALPHA;
666
0
            break;
667
0
        case ID_ONE_MINUS_SRC_ALPHA:
668
0
            *sbf = SBF_ONE_MINUS_SOURCE_ALPHA;
669
0
            break;
670
0
        default:
671
0
            return false;
672
0
        }
673
0
        return true;
674
0
    }
675
    //-------------------------------------------------------------------------
676
    bool ScriptTranslator::getCompareFunction(const AbstractNodePtr &node, CompareFunction *func)
677
0
    {
678
0
        if(node->type != ANT_ATOM)
679
0
            return false;
680
0
        AtomAbstractNode *atom = (AtomAbstractNode*)node.get();
681
0
        switch(atom->id)
682
0
        {
683
0
        case ID_ALWAYS_FAIL:
684
0
            *func = CMPF_ALWAYS_FAIL;
685
0
            break;
686
0
        case ID_ALWAYS_PASS:
687
0
            *func = CMPF_ALWAYS_PASS;
688
0
            break;
689
0
        case ID_LESS:
690
0
            *func = CMPF_LESS;
691
0
            break;
692
0
        case ID_LESS_EQUAL:
693
0
            *func = CMPF_LESS_EQUAL;
694
0
            break;
695
0
        case ID_EQUAL:
696
0
            *func = CMPF_EQUAL;
697
0
            break;
698
0
        case ID_NOT_EQUAL:
699
0
            *func = CMPF_NOT_EQUAL;
700
0
            break;
701
0
        case ID_GREATER_EQUAL:
702
0
            *func = CMPF_GREATER_EQUAL;
703
0
            break;
704
0
        case ID_GREATER:
705
0
            *func = CMPF_GREATER;
706
0
            break;
707
0
        default:
708
0
            return false;
709
0
        }
710
0
        return true;
711
0
    }
712
    //-------------------------------------------------------------------------
713
    bool ScriptTranslator::getMatrix4(AbstractNodeList::const_iterator i, AbstractNodeList::const_iterator end, Matrix4 *m)
714
0
    {
715
0
        int n = 0;
716
0
        while (i != end && n < 16)
717
0
        {
718
0
            Real r = 0;
719
0
            if (!getReal(*i, &r))
720
0
                return false;
721
722
0
            (*m)[n/4][n%4] = r;
723
0
            ++i;
724
0
            ++n;
725
0
        }
726
0
        return n == 16;
727
0
    }
728
    //-------------------------------------------------------------------------
729
    bool ScriptTranslator::getInts(AbstractNodeList::const_iterator i, AbstractNodeList::const_iterator end, int *vals, int count)
730
0
    {
731
0
        bool success = true;
732
0
        int n = 0;
733
0
        while (n < count)
734
0
        {
735
0
            if (i != end)
736
0
            {
737
0
                int v = 0;
738
0
                if (getInt(*i, &v))
739
0
                    vals[n] = v;
740
0
                else
741
0
                    break;
742
0
                ++i;
743
0
            }
744
0
            else
745
0
                vals[n] = 0;
746
0
            ++n;
747
0
        }
748
749
0
        if (n < count)
750
0
            success = false;
751
752
0
        return success;
753
0
    }
754
    bool ScriptTranslator::getVector(AbstractNodeList::const_iterator i, AbstractNodeList::const_iterator end, std::vector<int>& vals, size_t count)
755
0
    {
756
0
        return _getVector(i, end, vals, count);
757
0
    }
758
    //----------------------------------------------------------------------------
759
    bool ScriptTranslator::getFloats(AbstractNodeList::const_iterator i, AbstractNodeList::const_iterator end, float *vals, int count)
760
0
    {
761
0
        bool success = true;
762
0
        int n = 0;
763
0
        while (n < count)
764
0
        {
765
0
            if (i != end)
766
0
            {
767
0
                float v = 0;
768
0
                if (getFloat(*i, &v))
769
0
                    vals[n] = v;
770
0
                else
771
0
                    break;
772
0
                ++i;
773
0
            }
774
0
            else
775
0
                vals[n] = 0;
776
0
            ++n;
777
0
        }
778
779
0
        if (n < count)
780
0
            success = false;
781
782
0
        return success;
783
0
    }
784
    bool ScriptTranslator::getVector(AbstractNodeList::const_iterator i, AbstractNodeList::const_iterator end, std::vector<float>& vals, size_t count)
785
0
    {
786
0
        return _getVector(i, end, vals, count);
787
0
    }
788
    //----------------------------------------------------------------------------
789
    bool ScriptTranslator::getDoubles(AbstractNodeList::const_iterator i, AbstractNodeList::const_iterator end, double *vals, int count)
790
0
    {
791
0
        bool success = true;
792
0
        int n = 0;
793
0
        while (n < count)
794
0
        {
795
0
            if (i != end)
796
0
            {
797
0
                double v = 0;
798
0
                if (getDouble(*i, &v))
799
0
                    vals[n] = v;
800
0
                else
801
0
                    break;
802
0
                ++i;
803
0
            }
804
0
            else
805
0
                vals[n] = 0;
806
0
            ++n;
807
0
        }
808
809
0
        if (n < count)
810
0
            success = false;
811
812
0
        return success;
813
0
    }
814
    //----------------------------------------------------------------------------
815
    bool ScriptTranslator::getUInts(AbstractNodeList::const_iterator i, AbstractNodeList::const_iterator end, uint *vals, int count)
816
0
    {
817
0
        bool success = true;
818
0
        int n = 0;
819
0
        while (n < count)
820
0
        {
821
0
            if (i != end)
822
0
            {
823
0
                uint v = 0;
824
0
                if (getUInt(*i, &v))
825
0
                    vals[n] = v;
826
0
                else
827
0
                    break;
828
0
                ++i;
829
0
            }
830
0
            else
831
0
                vals[n] = 0;
832
0
            ++n;
833
0
        }
834
835
0
        if (n < count)
836
0
            success = false;
837
838
0
        return success;
839
0
    }
840
    //----------------------------------------------------------------------------
841
    bool ScriptTranslator::getBooleans(AbstractNodeList::const_iterator i, AbstractNodeList::const_iterator end, uint *vals, int count)
842
0
    {
843
0
        bool success = true;
844
0
        int n = 0;
845
0
        while (n < count)
846
0
        {
847
0
            if (i != end)
848
0
            {
849
0
                bool v = false;
850
0
                if (getBoolean(*i, &v))
851
0
                    vals[n] = (v != 0);
852
0
                else
853
0
                    break;
854
0
                ++i;
855
0
            }
856
0
            else
857
0
                vals[n] = false;
858
0
            ++n;
859
0
        }
860
861
0
        if (n < count)
862
0
            success = false;
863
864
0
        return success;
865
0
    }
866
    //-------------------------------------------------------------------------
867
    bool ScriptTranslator::getStencilOp(const Ogre::AbstractNodePtr &node, Ogre::StencilOperation *op)
868
0
    {
869
0
        if(node->type != ANT_ATOM)
870
0
            return false;
871
0
        AtomAbstractNode *atom = (AtomAbstractNode*)node.get();
872
0
        switch(atom->id)
873
0
        {
874
0
        case ID_KEEP:
875
0
            *op = SOP_KEEP;
876
0
            break;
877
0
        case ID_ZERO:
878
0
            *op = SOP_ZERO;
879
0
            break;
880
0
        case ID_REPLACE:
881
0
            *op = SOP_REPLACE;
882
0
            break;
883
0
        case ID_INCREMENT:
884
0
            *op = SOP_INCREMENT;
885
0
            break;
886
0
        case ID_DECREMENT:
887
0
            *op = SOP_DECREMENT;
888
0
            break;
889
0
        case ID_INCREMENT_WRAP:
890
0
            *op = SOP_INCREMENT_WRAP;
891
0
            break;
892
0
        case ID_DECREMENT_WRAP:
893
0
            *op = SOP_DECREMENT_WRAP;
894
0
            break;
895
0
        case ID_INVERT:
896
0
            *op = SOP_INVERT;
897
0
            break;
898
0
        default:
899
0
            return false;
900
0
        }
901
0
        return true;
902
0
    }
903
    //---------------------------------------------------------------------
904
    bool ScriptTranslator::getConstantType(AbstractNodeList::const_iterator i, GpuConstantType *op)
905
0
    {
906
0
        const String& val = (*i)->getString();
907
0
        if(val.empty())
908
0
            return false;
909
910
0
        if (val.find("float") != String::npos)
911
0
        {
912
0
            int count = 1;
913
0
            if (val.size() == 6)
914
0
                count = StringConverter::parseInt(val.substr(5));
915
0
            else if (val.size() > 6)
916
0
                return false;
917
918
0
            if (count > 4 || count == 0)
919
0
                return false;
920
921
0
            *op = (GpuConstantType)(GCT_FLOAT1 + count - 1);
922
0
        }
923
0
        else if (val.find("double") != String::npos)
924
0
        {
925
0
            int count = 1;
926
0
            if (val.size() == 7)
927
0
                count = StringConverter::parseInt(val.substr(6));
928
0
            else if (val.size() > 7)
929
0
                return false;
930
931
0
            if (count > 4 || count == 0)
932
0
                return false;
933
934
0
            *op = (GpuConstantType)(GCT_DOUBLE1 + count - 1);
935
0
        }
936
0
        else if (val.find("uint") != String::npos)
937
0
        {
938
0
            int count = 1;
939
0
            if (val.size() == 5)
940
0
                count = StringConverter::parseInt(val.substr(4));
941
0
            else if (val.size() > 5)
942
0
                return false;
943
944
0
            if (count > 4 || count == 0)
945
0
                return false;
946
947
0
            *op = (GpuConstantType)(GCT_UINT1 + count - 1);
948
0
        }
949
0
        else if (val.find("int") != String::npos)
950
0
        {
951
0
            int count = 1;
952
0
            if (val.size() == 4)
953
0
                count = StringConverter::parseInt(val.substr(3));
954
0
            else if (val.size() > 4)
955
0
                return false;
956
957
0
            if (count > 4 || count == 0)
958
0
                return false;
959
960
0
            *op = (GpuConstantType)(GCT_INT1 + count - 1);
961
0
        }
962
0
        else if (val.find("bool") != String::npos)
963
0
        {
964
0
            int count = 1;
965
0
            if (val.size() == 5)
966
0
                count = StringConverter::parseInt(val.substr(4));
967
0
            else if (val.size() > 5)
968
0
                return false;
969
970
0
            if (count > 4 || count == 0)
971
0
                return false;
972
973
0
            *op = (GpuConstantType)(GCT_BOOL1 + count - 1);
974
0
        }
975
0
        else if(val.find("matrix") != String::npos)
976
0
        {
977
0
            int count1, count2;
978
979
0
            if (val.size() == 9)
980
0
            {
981
0
                count1 = StringConverter::parseInt(val.substr(6, 1));
982
0
                count2 = StringConverter::parseInt(val.substr(8, 1));
983
0
            }
984
0
            else
985
0
                return false;
986
987
0
            if (count1 > 4 || count1 < 2 || count2 > 4 || count2 < 2)
988
0
                return false;
989
990
0
            switch(count1)
991
0
            {
992
0
            case 2:
993
0
                *op = (GpuConstantType)(GCT_MATRIX_2X2 + count2 - 2);
994
0
                break;
995
0
            case 3:
996
0
                *op = (GpuConstantType)(GCT_MATRIX_3X2 + count2 - 2);
997
0
                break;
998
0
            case 4:
999
0
                *op = (GpuConstantType)(GCT_MATRIX_4X2 + count2 - 2);
1000
0
                break;
1001
0
            }
1002
1003
0
        }
1004
0
        else
1005
0
        {
1006
0
            return false;
1007
0
        }
1008
1009
0
        return true;
1010
0
    }
1011
1012
    /**************************************************************************
1013
     * MaterialTranslator
1014
     *************************************************************************/
1015
    MaterialTranslator::MaterialTranslator()
1016
0
    {
1017
0
    }
1018
    //-------------------------------------------------------------------------
1019
    void MaterialTranslator::translate(ScriptCompiler *compiler, const AbstractNodePtr &node)
1020
0
    {
1021
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
1022
0
        if(obj->name.empty())
1023
0
        {
1024
0
            compiler->addError(ScriptCompiler::CE_OBJECTNAMEEXPECTED, obj->file, obj->line);
1025
0
            return;
1026
0
        }
1027
1028
0
        Material* mMaterial = 0;
1029
1030
        // Create a material with the given name
1031
0
        CreateMaterialScriptCompilerEvent evt(node->file, obj->name, compiler->getResourceGroup());
1032
0
        bool processed = compiler->_fireEvent(&evt, (void*)&mMaterial);
1033
1034
0
        if(!processed)
1035
0
        {
1036
0
            mMaterial = MaterialManager::getSingleton().create(obj->name, compiler->getResourceGroup()).get();
1037
0
        }
1038
1039
0
        if(!mMaterial)
1040
0
        {
1041
0
            compiler->addError(ScriptCompiler::CE_OBJECTALLOCATIONERROR, obj->file, obj->line, obj->name);
1042
0
            return;
1043
0
        }
1044
1045
0
        mMaterial->removeAllTechniques();
1046
0
        obj->context = mMaterial;
1047
0
        mMaterial->_notifyOrigin(obj->file);
1048
1049
0
        bool bval;
1050
0
        String sval;
1051
1052
0
        for(auto & i : obj->children)
1053
0
        {
1054
0
            if(i->type == ANT_PROPERTY)
1055
0
            {
1056
0
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
1057
0
                switch(prop->id)
1058
0
                {
1059
0
                case ID_LOD_VALUES:
1060
0
                    {
1061
0
                        Material::LodValueList lods;
1062
0
                        for(const auto& j : prop->values)
1063
0
                        {
1064
0
                            Real v = 0;
1065
0
                            if(getReal(j, &v))
1066
0
                                lods.push_back(v);
1067
0
                            else
1068
0
                                compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
1069
0
                                                   "lod_values expects only numbers as arguments");
1070
0
                        }
1071
0
                        mMaterial->setLodLevels(lods);
1072
0
                    }
1073
0
                    break;
1074
0
                case ID_LOD_DISTANCES:
1075
0
                    {
1076
                        // Deprecated! Only for backwards compatibility.
1077
                        // Set strategy hard-coded to 'distance' strategy, since that was the only one available back then,
1078
                        // when using this material keyword was still current.
1079
0
                        LodStrategy *strategy = DistanceLodSphereStrategy::getSingletonPtr();
1080
0
                        mMaterial->setLodStrategy(strategy);
1081
1082
0
                        compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file,
1083
0
                                           prop->line,
1084
0
                                           "lod_distances. Use lod_values.");
1085
                        // Read in LOD distances
1086
0
                        Material::LodValueList lods;
1087
0
                        for(auto& j : prop->values)
1088
0
                        {
1089
0
                            Real v = 0;
1090
0
                            if(getReal(j, &v))
1091
0
                                lods.push_back(v);
1092
0
                            else
1093
0
                                compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
1094
0
                                                   "lod_values expects only numbers as arguments");
1095
0
                        }
1096
0
                        mMaterial->setLodLevels(lods);
1097
0
                    }
1098
0
                    break;
1099
0
                case ID_LOD_STRATEGY:
1100
0
                    if(getValue(prop, compiler, sval))
1101
0
                    {
1102
0
                            if (sval == "Distance" || sval == "PixelCount")
1103
0
                                compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file, prop->line,
1104
0
                                                   sval + ". use distance_box or pixel_count");
1105
1106
0
                            LodStrategy* strategy = LodStrategyManager::getSingleton().getStrategy(sval);
1107
0
                            if (strategy)
1108
0
                                mMaterial->setLodStrategy(strategy);
1109
0
                            else
1110
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line, sval);
1111
0
                    }
1112
0
                    break;
1113
0
                case ID_RECEIVE_SHADOWS:
1114
0
                    if(getValue(prop, compiler, bval))
1115
0
                        mMaterial->setReceiveShadows(bval);
1116
0
                    break;
1117
0
                case ID_TRANSPARENCY_CASTS_SHADOWS:
1118
0
                    if(getValue(prop, compiler, bval))
1119
0
                        mMaterial->setTransparencyCastsShadows(bval);
1120
0
                    break;
1121
0
                case ID_SET_TEXTURE_ALIAS:
1122
0
                    if(prop->values.size() != 2)
1123
0
                    {
1124
0
                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1125
0
                                            "set_texture_alias must have 2 string arguments");
1126
0
                    }
1127
0
                    else
1128
0
                    {
1129
0
                        compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file, prop->line,
1130
0
                                            "set_texture_alias. Use 'set $variable value'");
1131
1132
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1);
1133
0
                        String name, value;
1134
0
                        if(getString(*i0, &name) && getString(*i1, &value))
1135
0
                            mTextureAliases.insert(std::make_pair(name, value));
1136
0
                    }
1137
0
                    break;
1138
0
                default:
1139
0
                    compiler->addError(ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
1140
0
                                       "token \"" + prop->name + "\" is not recognized");
1141
0
                }
1142
0
            }
1143
0
            else if(i->type == ANT_OBJECT)
1144
0
            {
1145
0
                processNode(compiler, i);
1146
0
            }
1147
0
        }
1148
1149
0
        applyTextureAliases(compiler, mMaterial, mTextureAliases);
1150
0
        mTextureAliases.clear();
1151
0
    }
1152
1153
    /**************************************************************************
1154
     * TechniqueTranslator
1155
     *************************************************************************/
1156
    TechniqueTranslator::TechniqueTranslator()
1157
0
        :mTechnique(0)
1158
0
    {
1159
0
    }
1160
    //-------------------------------------------------------------------------
1161
    void TechniqueTranslator::translate(ScriptCompiler *compiler, const AbstractNodePtr &node)
1162
0
    {
1163
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
1164
1165
        // Create the technique from the material
1166
0
        Ogre::Material *material = Ogre::any_cast<Ogre::Material*>(obj->parent->context);
1167
0
        mTechnique = material->createTechnique();
1168
0
        obj->context = mTechnique;
1169
1170
        // Get the name of the technique
1171
0
        if(!obj->name.empty())
1172
0
            mTechnique->setName(obj->name);
1173
1174
0
        uint32 uival;
1175
0
        String sval;
1176
1177
        // Set the properties for the material
1178
0
        for(auto & i : obj->children)
1179
0
        {
1180
0
            if(i->type == ANT_PROPERTY)
1181
0
            {
1182
0
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
1183
0
                switch(prop->id)
1184
0
                {
1185
0
                case ID_SCHEME:
1186
0
                    if(getValue(prop, compiler, sval))
1187
0
                        mTechnique->setSchemeName(sval);
1188
0
                    break;
1189
0
                case ID_LOD_INDEX:
1190
0
                    if(getValue(prop, compiler, uival))
1191
0
                        mTechnique->setLodIndex(static_cast<uint16>(uival));
1192
0
                    break;
1193
0
                case ID_SHADOW_CASTER_MATERIAL:
1194
0
                    if(getValue(prop, compiler, sval))
1195
0
                    {
1196
0
                        ProcessResourceNameScriptCompilerEvent evt(ProcessResourceNameScriptCompilerEvent::MATERIAL, sval);
1197
0
                        compiler->_fireEvent(&evt, 0);
1198
0
                        mTechnique->setShadowCasterMaterial(evt.mName); // Use the processed name
1199
0
                    }
1200
0
                    break;
1201
0
                case ID_SHADOW_RECEIVER_MATERIAL:
1202
0
                    if(getValue(prop, compiler, sval))
1203
0
                    {
1204
0
                        ProcessResourceNameScriptCompilerEvent evt(ProcessResourceNameScriptCompilerEvent::MATERIAL, sval);
1205
0
                        compiler->_fireEvent(&evt, 0);
1206
0
                        mTechnique->setShadowReceiverMaterial(evt.mName); // Use the processed name
1207
0
                    }
1208
0
                    break;
1209
0
                case ID_GPU_VENDOR_RULE:
1210
0
                    if(prop->values.size() < 2)
1211
0
                    {
1212
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line,
1213
0
                                           "gpu_vendor_rule must have 2 arguments");
1214
0
                    }
1215
0
                    else if(prop->values.size() > 2)
1216
0
                    {
1217
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1218
0
                                           "gpu_vendor_rule must have 2 arguments");
1219
0
                    }
1220
0
                    else
1221
0
                    {
1222
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0);
1223
0
                        AbstractNodeList::const_iterator i1 = getNodeAt(prop->values, 1);
1224
1225
0
                        Technique::GPUVendorRule rule;
1226
0
                        if ((*i0)->type == ANT_ATOM)
1227
0
                        {
1228
0
                            AtomAbstractNode *atom0 = (AtomAbstractNode*)(*i0).get();
1229
0
                            if (atom0->id == ID_INCLUDE)
1230
0
                            {
1231
0
                                rule.includeOrExclude = Technique::INCLUDE;
1232
0
                            }
1233
0
                            else if (atom0->id == ID_EXCLUDE)
1234
0
                            {
1235
0
                                rule.includeOrExclude = Technique::EXCLUDE;
1236
0
                            }
1237
0
                            else
1238
0
                            {
1239
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1240
0
                                                   "gpu_vendor_rule cannot accept \"" + (*i0)->getValue() + "\" as first argument");
1241
0
                            }
1242
1243
0
                            String vendor;
1244
0
                            if(!getString(*i1, &vendor))
1245
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1246
0
                                                   "gpu_vendor_rule cannot accept \"" + (*i1)->getValue() + "\" as second argument");
1247
1248
0
                            rule.vendor = RenderSystemCapabilities::vendorFromString(vendor);
1249
1250
0
                            if (rule.vendor != GPU_UNKNOWN)
1251
0
                            {
1252
0
                                mTechnique->addGPUVendorRule(rule);
1253
0
                            }
1254
0
                        }
1255
0
                        else
1256
0
                        {
1257
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1258
0
                                               "gpu_vendor_rule cannot accept \"" + (*i0)->getValue() + "\" as first argument");
1259
0
                        }
1260
1261
0
                    }
1262
0
                    break;
1263
0
                case ID_GPU_DEVICE_RULE:
1264
0
                    if(prop->values.size() < 2)
1265
0
                    {
1266
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line,
1267
0
                                           "gpu_device_rule must have at least 2 arguments");
1268
0
                    }
1269
0
                    else if(prop->values.size() > 3)
1270
0
                    {
1271
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1272
0
                                           "gpu_device_rule must have at most 3 arguments");
1273
0
                    }
1274
0
                    else
1275
0
                    {
1276
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0);
1277
0
                        AbstractNodeList::const_iterator i1 = getNodeAt(prop->values, 1);
1278
1279
0
                        Technique::GPUDeviceNameRule rule;
1280
0
                        if ((*i0)->type == ANT_ATOM)
1281
0
                        {
1282
0
                            AtomAbstractNode *atom0 = (AtomAbstractNode*)(*i0).get();
1283
0
                            if (atom0->id == ID_INCLUDE)
1284
0
                            {
1285
0
                                rule.includeOrExclude = Technique::INCLUDE;
1286
0
                            }
1287
0
                            else if (atom0->id == ID_EXCLUDE)
1288
0
                            {
1289
0
                                rule.includeOrExclude = Technique::EXCLUDE;
1290
0
                            }
1291
0
                            else
1292
0
                            {
1293
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1294
0
                                                   "gpu_device_rule cannot accept \"" + (*i0)->getValue() + "\" as first argument");
1295
0
                            }
1296
1297
0
                            if(!getString(*i1, &rule.devicePattern))
1298
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1299
0
                                                   "gpu_device_rule cannot accept \"" + (*i1)->getValue() + "\" as second argument");
1300
1301
0
                            if (prop->values.size() == 3)
1302
0
                            {
1303
0
                                AbstractNodeList::const_iterator i2 = getNodeAt(prop->values, 2);
1304
0
                                if (!getBoolean(*i2, &rule.caseSensitive))
1305
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1306
0
                                                       "gpu_device_rule third argument must be \"true\", \"false\", \"yes\", \"no\", \"on\", or \"off\"");
1307
0
                            }
1308
1309
0
                            mTechnique->addGPUDeviceNameRule(rule);
1310
0
                        }
1311
0
                        else
1312
0
                        {
1313
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1314
0
                                               "gpu_device_rule cannot accept \"" + (*i0)->getValue() + "\" as first argument");
1315
0
                        }
1316
1317
0
                    }
1318
0
                    break;
1319
0
                default:
1320
0
                    compiler->addError(ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
1321
0
                                       "token \"" + prop->name + "\" is not recognized");
1322
0
                }
1323
0
            }
1324
0
            else if(i->type == ANT_OBJECT)
1325
0
            {
1326
0
                processNode(compiler, i);
1327
0
            }
1328
0
        }
1329
0
    }
1330
1331
    /**************************************************************************
1332
     * PassTranslator
1333
     *************************************************************************/
1334
    PassTranslator::PassTranslator()
1335
0
        :mPass(0)
1336
0
    {
1337
0
    }
1338
    //-------------------------------------------------------------------------
1339
    void PassTranslator::translate(ScriptCompiler *compiler, const AbstractNodePtr &node)
1340
0
    {
1341
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
1342
1343
0
        Technique *technique = any_cast<Technique*>(obj->parent->context);
1344
0
        mPass = technique->createPass();
1345
0
        obj->context = mPass;
1346
1347
        // Get the name of the technique
1348
0
        if(!obj->name.empty())
1349
0
            mPass->setName(obj->name);
1350
1351
0
        Real fval;
1352
0
        bool bval;
1353
0
        uint32 uival;
1354
1355
        // Set the properties for the material
1356
0
        for(auto & i : obj->children)
1357
0
        {
1358
0
            if(i->type == ANT_PROPERTY)
1359
0
            {
1360
0
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
1361
0
                switch(prop->id)
1362
0
                {
1363
0
                case ID_AMBIENT:
1364
0
                    if(prop->values.empty())
1365
0
                    {
1366
0
                        compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line);
1367
0
                    }
1368
0
                    else if(prop->values.size() > 4)
1369
0
                    {
1370
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1371
0
                                           "ambient must have at most 4 parameters");
1372
0
                    }
1373
0
                    else
1374
0
                    {
1375
0
                        if(prop->values.front()->type == ANT_ATOM &&
1376
0
                           ((AtomAbstractNode*)prop->values.front().get())->id == ID_VERTEXCOLOUR)
1377
0
                        {
1378
0
                            mPass->setVertexColourTracking(mPass->getVertexColourTracking() | TVC_AMBIENT);
1379
0
                        }
1380
0
                        else
1381
0
                        {
1382
0
                            ColourValue val = ColourValue::White;
1383
0
                            if(getColour(prop->values.begin(), prop->values.end(), &val))
1384
0
                                mPass->setAmbient(val);
1385
0
                            else
1386
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1387
0
                                                   "ambient requires 3 or 4 colour arguments, or a \"vertexcolour\" directive");
1388
0
                        }
1389
0
                    }
1390
0
                    break;
1391
0
                case ID_DIFFUSE:
1392
0
                    if(prop->values.empty())
1393
0
                    {
1394
0
                        compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line);
1395
0
                    }
1396
0
                    else if(prop->values.size() > 4)
1397
0
                    {
1398
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1399
0
                                           "diffuse must have at most 4 arguments");
1400
0
                    }
1401
0
                    else
1402
0
                    {
1403
0
                        if(prop->values.front()->type == ANT_ATOM &&
1404
0
                           ((AtomAbstractNode*)prop->values.front().get())->id == ID_VERTEXCOLOUR)
1405
0
                        {
1406
0
                            mPass->setVertexColourTracking(mPass->getVertexColourTracking() | TVC_DIFFUSE);
1407
0
                        }
1408
0
                        else
1409
0
                        {
1410
0
                            ColourValue val = ColourValue::White;
1411
0
                            if(getColour(prop->values.begin(), prop->values.end(), &val))
1412
0
                                mPass->setDiffuse(val);
1413
0
                            else
1414
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1415
0
                                                   "diffuse requires 3 or 4 colour arguments, or a \"vertexcolour\" directive");
1416
0
                        }
1417
0
                    }
1418
0
                    break;
1419
0
                case ID_SPECULAR:
1420
0
                    if(prop->values.empty())
1421
0
                    {
1422
0
                        compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line);
1423
0
                    }
1424
0
                    else if(prop->values.size() > 5)
1425
0
                    {
1426
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1427
0
                                           "specular must have at most 5 arguments");
1428
0
                    }
1429
0
                    else
1430
0
                    {
1431
0
                        if(prop->values.front()->type == ANT_ATOM &&
1432
0
                           ((AtomAbstractNode*)prop->values.front().get())->id == ID_VERTEXCOLOUR)
1433
0
                        {
1434
0
                            mPass->setVertexColourTracking(mPass->getVertexColourTracking() | TVC_SPECULAR);
1435
1436
0
                            if(prop->values.size() >= 2)
1437
0
                            {
1438
0
                                Real val = 0;
1439
0
                                if(getReal(prop->values.back(), &val))
1440
0
                                    mPass->setShininess(val);
1441
0
                                else
1442
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1443
0
                                                       "specular does not support \"" + prop->values.back()->getValue() + "\" as its second argument");
1444
0
                            }
1445
0
                        }
1446
0
                        else
1447
0
                        {
1448
0
                            if(prop->values.size() < 4)
1449
0
                            {
1450
0
                                compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
1451
0
                                                   "specular expects at least 4 arguments");
1452
0
                            }
1453
0
                            else
1454
0
                            {
1455
0
                                ColourValue val;
1456
0
                                if(getColour(prop->values.begin(), prop->values.end(), &val))
1457
0
                                {
1458
0
                                    if(prop->values.size() == 4)
1459
0
                                    {
1460
0
                                        mPass->setShininess(val.a);
1461
0
                                        val.a = 1.0f;
1462
0
                                        mPass->setSpecular(val);
1463
0
                                    }
1464
0
                                    else
1465
0
                                    {
1466
0
                                        mPass->setSpecular(val);
1467
1468
0
                                        Real shininess;
1469
0
                                        if(getReal(*getNodeAt(prop->values, 4), &shininess))
1470
0
                                            mPass->setShininess(shininess);
1471
0
                                        else
1472
0
                                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1473
0
                                                               "specular fourth argument must be a valid number for shininess attribute");
1474
0
                                    }
1475
0
                                }
1476
0
                                else
1477
0
                                {
1478
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1479
0
                                                       "specular must have first 3 arguments be a valid colour");
1480
0
                                }
1481
0
                            }
1482
1483
0
                        }
1484
0
                    }
1485
0
                    break;
1486
0
                case ID_EMISSIVE:
1487
0
                    if(prop->values.empty())
1488
0
                    {
1489
0
                        compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line);
1490
0
                    }
1491
0
                    else if(prop->values.size() > 4)
1492
0
                    {
1493
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1494
0
                                           "emissive must have at most 4 arguments");
1495
0
                    }
1496
0
                    else
1497
0
                    {
1498
0
                        if(prop->values.front()->type == ANT_ATOM &&
1499
0
                           ((AtomAbstractNode*)prop->values.front().get())->id == ID_VERTEXCOLOUR)
1500
0
                        {
1501
0
                            mPass->setVertexColourTracking(mPass->getVertexColourTracking() | TVC_EMISSIVE);
1502
0
                        }
1503
0
                        else
1504
0
                        {
1505
0
                            ColourValue val(0.0f, 0.0f, 0.0f, 1.0f);
1506
0
                            if(getColour(prop->values.begin(), prop->values.end(), &val))
1507
0
                                mPass->setSelfIllumination(val);
1508
0
                            else
1509
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1510
0
                                                   "emissive requires 3 or 4 colour arguments, or a \"vertexcolour\" directive");
1511
0
                        }
1512
0
                    }
1513
0
                    break;
1514
0
                case ID_SCENE_BLEND:
1515
0
                    if(prop->values.empty())
1516
0
                    {
1517
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
1518
0
                    }
1519
0
                    else if(prop->values.size() > 2)
1520
0
                    {
1521
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1522
0
                                           "scene_blend supports at most 2 arguments");
1523
0
                    }
1524
0
                    else if(prop->values.size() == 1)
1525
0
                    {
1526
0
                        SceneBlendType enval;
1527
0
                        if(getValue(prop->values.front(), enval))
1528
0
                        {
1529
0
                            mPass->setSceneBlending(enval);
1530
0
                        }
1531
0
                        else
1532
0
                        {
1533
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1534
0
                                               "scene_blend does not support \"" + prop->values.front()->getValue() + "\" for argument 1");
1535
0
                        }
1536
0
                    }
1537
0
                    else
1538
0
                    {
1539
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1);
1540
0
                        SceneBlendFactor sbf0, sbf1;
1541
0
                        if(getSceneBlendFactor(*i0, &sbf0) && getSceneBlendFactor(*i1, &sbf1))
1542
0
                        {
1543
0
                            mPass->setSceneBlending(sbf0, sbf1);
1544
0
                        }
1545
0
                        else
1546
0
                        {
1547
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1548
0
                                               "scene_blend does not support \"" + (*i0)->getValue() + "\" and \"" + (*i1)->getValue() + "\" as arguments");
1549
0
                        }
1550
0
                    }
1551
0
                    break;
1552
0
                case ID_SEPARATE_SCENE_BLEND:
1553
0
                    if(prop->values.empty())
1554
0
                    {
1555
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
1556
0
                    }
1557
0
                    else if(prop->values.size() == 3)
1558
0
                    {
1559
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1560
0
                                           "separate_scene_blend must have 2 or 4 arguments");
1561
0
                    }
1562
0
                    else if(prop->values.size() > 4)
1563
0
                    {
1564
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1565
0
                                           "separate_scene_blend must have 2 or 4 arguments");
1566
0
                    }
1567
0
                    else if(prop->values.size() == 2)
1568
0
                    {
1569
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1);
1570
0
                        SceneBlendType sbt0, sbt1;
1571
0
                        if (getValue(*i0, sbt0) && getValue(*i1, sbt1))
1572
0
                        {
1573
0
                            mPass->setSeparateSceneBlending(sbt0, sbt1);
1574
0
                        }
1575
0
                        else
1576
0
                        {
1577
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1578
0
                                               "separate_scene_blend does not support \"" + (*i0)->getValue() + "\" as argument 1");
1579
0
                        }
1580
0
                    }
1581
0
                    else
1582
0
                    {
1583
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1),
1584
0
                            i2 = getNodeAt(prop->values, 2), i3 = getNodeAt(prop->values, 3);
1585
0
                        if((*i0)->type == ANT_ATOM && (*i1)->type == ANT_ATOM && (*i2)->type == ANT_ATOM && (*i3)->type == ANT_ATOM)
1586
0
                        {
1587
0
                            SceneBlendFactor sbf0, sbf1, sbf2, sbf3;
1588
0
                            if(getSceneBlendFactor(*i0, &sbf0) && getSceneBlendFactor(*i1, &sbf1) && getSceneBlendFactor(*i2, &sbf2) &&
1589
0
                               getSceneBlendFactor(*i3, &sbf3))
1590
0
                            {
1591
0
                                mPass->setSeparateSceneBlending(sbf0, sbf1, sbf2, sbf3);
1592
0
                            }
1593
0
                            else
1594
0
                            {
1595
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1596
0
                                                   "one of the arguments to separate_scene_blend is not a valid scene blend factor directive");
1597
0
                            }
1598
0
                        }
1599
0
                        else
1600
0
                        {
1601
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1602
0
                                               "one of the arguments to separate_scene_blend is not a valid scene blend factor directive");
1603
0
                        }
1604
0
                    }
1605
0
                    break;
1606
0
                case ID_SCENE_BLEND_OP:
1607
0
                    SceneBlendOperation sop;
1608
0
                    if(getValue(prop, compiler, sop))
1609
0
                        mPass->setSceneBlendingOperation(sop);
1610
0
                    break;
1611
0
                case ID_SEPARATE_SCENE_BLEND_OP:
1612
0
                    if(prop->values.empty())
1613
0
                    {
1614
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
1615
0
                    }
1616
0
                    else if(prop->values.size() != 2)
1617
0
                    {
1618
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1619
0
                                           "separate_scene_blend_op must have 2 arguments");
1620
0
                    }
1621
0
                    else
1622
0
                    {
1623
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1);
1624
0
                        SceneBlendOperation op, alphaOp;
1625
0
                        if(getValue(*i0, op) && getValue(*i1, alphaOp))
1626
0
                        {
1627
0
                            mPass->setSeparateSceneBlendingOperation(op, alphaOp);
1628
0
                        }
1629
0
                        else
1630
0
                        {
1631
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1632
0
                                               prop->values.front()->getValue() + ": unrecognized argument");
1633
0
                        }
1634
0
                    }
1635
0
                    break;
1636
0
                case ID_DEPTH_CHECK:
1637
0
                    if(getValue(prop, compiler, bval))
1638
0
                        mPass->setDepthCheckEnabled(bval);
1639
0
                    break;
1640
0
                case ID_DEPTH_WRITE:
1641
0
                    if(getValue(prop, compiler, bval))
1642
0
                        mPass->setDepthWriteEnabled(bval);
1643
0
                    break;
1644
0
                case ID_DEPTH_BIAS:
1645
0
                    if(prop->values.empty())
1646
0
                    {
1647
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
1648
0
                    }
1649
0
                    else if(prop->values.size() > 2)
1650
0
                    {
1651
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1652
0
                                           "depth_bias must have at most 2 arguments");
1653
0
                    }
1654
0
                    else
1655
0
                    {
1656
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1);
1657
0
                        float val0, val1 = 0.0f;
1658
0
                        if(getFloat(*i0, &val0))
1659
0
                        {
1660
0
                            if(i1 != prop->values.end())
1661
0
                                getFloat(*i1, &val1);
1662
0
                            mPass->setDepthBias(val0, val1);
1663
0
                        }
1664
0
                        else
1665
0
                        {
1666
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1667
0
                                               "depth_bias does not support \"" + (*i0)->getValue() + "\" for argument 1");
1668
0
                        }
1669
0
                    }
1670
0
                    break;
1671
0
                case ID_DEPTH_FUNC:
1672
0
                    CompareFunction dfunc;
1673
0
                    if(getValue(prop, compiler, dfunc))
1674
0
                        mPass->setDepthFunction(dfunc);
1675
0
                    break;
1676
0
                case ID_ITERATION_DEPTH_BIAS:
1677
0
                    if(getValue(prop, compiler, fval))
1678
0
                        mPass->setIterationDepthBias(fval);
1679
0
                    break;
1680
0
                case ID_ALPHA_REJECTION:
1681
0
                    if(prop->values.empty())
1682
0
                    {
1683
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
1684
0
                    }
1685
0
                    else if(prop->values.size() > 2)
1686
0
                    {
1687
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1688
0
                                           "alpha_rejection must have at most 2 arguments");
1689
0
                    }
1690
0
                    else
1691
0
                    {
1692
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1);
1693
0
                        CompareFunction func;
1694
0
                        if(getCompareFunction(*i0, &func))
1695
0
                        {
1696
0
                            if(i1 != prop->values.end())
1697
0
                            {
1698
0
                                uint32 val = 0;
1699
0
                                if(getUInt(*i1, &val))
1700
0
                                    mPass->setAlphaRejectSettings(func, static_cast<unsigned char>(val));
1701
0
                                else
1702
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1703
0
                                                       (*i1)->getValue() + " is not a valid integer");
1704
0
                            }
1705
0
                            else
1706
0
                                mPass->setAlphaRejectFunction(func);
1707
0
                        }
1708
0
                        else
1709
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1710
0
                                               (*i0)->getValue() + " is not a valid CompareFunction");
1711
0
                    }
1712
0
                    break;
1713
0
                case ID_ALPHA_TO_COVERAGE:
1714
0
                    if(getValue(prop, compiler, bval))
1715
0
                        mPass->setAlphaToCoverageEnabled(bval);
1716
0
                    break;
1717
0
                case ID_LIGHT_SCISSOR:
1718
0
                    if(getValue(prop, compiler, bval))
1719
0
                        mPass->setLightScissoringEnabled(bval);
1720
0
                    break;
1721
0
                case ID_LIGHT_CLIP_PLANES:
1722
0
                    if(getValue(prop, compiler, bval))
1723
0
                        mPass->setLightClipPlanesEnabled(bval);
1724
0
                    break;
1725
0
                case ID_TRANSPARENT_SORTING:
1726
0
                    if(prop->values.empty())
1727
0
                    {
1728
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
1729
0
                    }
1730
0
                    else if(prop->values.size() > 1)
1731
0
                    {
1732
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1733
0
                                           "transparent_sorting must have at most 1 argument");
1734
0
                    }
1735
0
                    else
1736
0
                    {
1737
0
                        bool val = true;
1738
0
                        if(getBoolean(prop->values.front(), &val))
1739
0
                        {
1740
0
                            mPass->setTransparentSortingEnabled(val);
1741
0
                            mPass->setTransparentSortingForced(false);
1742
0
                        }
1743
0
                        else
1744
0
                        {
1745
0
                            String val2;
1746
0
                            if (prop->values.front()->getString()=="force")
1747
0
                            {
1748
0
                                mPass->setTransparentSortingEnabled(true);
1749
0
                                mPass->setTransparentSortingForced(true);
1750
0
                            }
1751
0
                            else
1752
0
                            {
1753
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1754
0
                                                   prop->values.front()->getValue() + " must be boolean or force");
1755
0
                            }
1756
0
                        }
1757
0
                    }
1758
0
                    break;
1759
0
                case ID_ILLUMINATION_STAGE:
1760
0
                    IlluminationStage is;
1761
0
                    if(getValue(prop, compiler, is))
1762
0
                        mPass->setIlluminationStage(is);
1763
0
                    break;
1764
0
                case ID_CULL_HARDWARE:
1765
0
                    CullingMode cmode;
1766
0
                    if(getValue(prop, compiler, cmode))
1767
0
                        mPass->setCullingMode(cmode);
1768
0
                    break;
1769
0
                case ID_CULL_SOFTWARE:
1770
0
                    ManualCullingMode mmode;
1771
0
                    if(getValue(prop, compiler, mmode))
1772
0
                        mPass->setManualCullingMode(mmode);
1773
0
                    compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file, prop->line,
1774
0
                                       prop->name + ". Only used by the BSP scene manager.");
1775
0
                    break;
1776
0
                case ID_LIGHTING:
1777
0
                    if(getValue(prop, compiler, bval))
1778
0
                        mPass->setLightingEnabled(bval);
1779
0
                    break;
1780
0
                case ID_SHADING:
1781
0
                    ShadeOptions smode;
1782
0
                    if(getValue(prop, compiler, smode))
1783
0
                        mPass->setShadingMode(smode);
1784
0
                    break;
1785
0
                case ID_POLYGON_MODE:
1786
0
                    PolygonMode pmode;
1787
0
                    if(getValue(prop, compiler, pmode))
1788
0
                        mPass->setPolygonMode(pmode);
1789
0
                    break;
1790
0
                case ID_POLYGON_MODE_OVERRIDEABLE:
1791
0
                    if(getValue(prop, compiler, bval))
1792
0
                        mPass->setPolygonModeOverrideable(bval);
1793
0
                    break;
1794
0
                case ID_FOG_OVERRIDE:
1795
0
                    if(prop->values.empty())
1796
0
                    {
1797
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
1798
0
                    }
1799
0
                    else if(prop->values.size() > 8)
1800
0
                    {
1801
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1802
0
                                           "fog_override must have at most 8 arguments");
1803
0
                    }
1804
0
                    else
1805
0
                    {
1806
0
                        AbstractNodeList::const_iterator i1 = getNodeAt(prop->values, 1), i2 = getNodeAt(prop->values, 2);
1807
0
                        bool val = false;
1808
0
                        if(getBoolean(prop->values.front(), &val))
1809
0
                        {
1810
0
                            FogMode mode = FOG_NONE;
1811
0
                            ColourValue clr = ColourValue::White;
1812
0
                            Real dens = 0.001, start = 0.0f, end = 1.0f;
1813
1814
0
                            if(i1 != prop->values.end())
1815
0
                            {
1816
0
                                if((*i1)->type == ANT_ATOM)
1817
0
                                {
1818
0
                                    AtomAbstractNode *atom = (AtomAbstractNode*)(*i1).get();
1819
0
                                    switch(atom->id)
1820
0
                                    {
1821
0
                                    case ID_NONE:
1822
0
                                        mode = FOG_NONE;
1823
0
                                        break;
1824
0
                                    case ID_LINEAR:
1825
0
                                        mode = FOG_LINEAR;
1826
0
                                        break;
1827
0
                                    case ID_EXP:
1828
0
                                        mode = FOG_EXP;
1829
0
                                        break;
1830
0
                                    case ID_EXP2:
1831
0
                                        mode = FOG_EXP2;
1832
0
                                        break;
1833
0
                                    default:
1834
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1835
0
                                                           (*i1)->getValue() + " is not a valid FogMode");
1836
0
                                        break;
1837
0
                                    }
1838
0
                                }
1839
0
                                else
1840
0
                                {
1841
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1842
0
                                                       (*i1)->getValue() + " is not a valid FogMode");
1843
0
                                    break;
1844
0
                                }
1845
0
                            }
1846
1847
0
                            if(i2 != prop->values.end())
1848
0
                            {
1849
0
                                if(!getColour(i2, prop->values.end(), &clr, 3))
1850
0
                                {
1851
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1852
0
                                                       (*i2)->getValue() + " is not a valid colour");
1853
0
                                    break;
1854
0
                                }
1855
1856
0
                                i2 = getNodeAt(prop->values, 5);
1857
0
                            }
1858
1859
0
                            if(i2 != prop->values.end())
1860
0
                            {
1861
0
                                if(!getReal(*i2, &dens))
1862
0
                                {
1863
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1864
0
                                                       (*i2)->getValue() + " is not a valid number");
1865
0
                                    break;
1866
0
                                }
1867
0
                                ++i2;
1868
0
                            }
1869
1870
0
                            if(i2 != prop->values.end())
1871
0
                            {
1872
0
                                if(!getReal(*i2, &start))
1873
0
                                {
1874
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1875
0
                                                       (*i2)->getValue() + " is not a valid number");
1876
0
                                    return;
1877
0
                                }
1878
0
                                ++i2;
1879
0
                            }
1880
1881
0
                            if(i2 != prop->values.end())
1882
0
                            {
1883
0
                                if(!getReal(*i2, &end))
1884
0
                                {
1885
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1886
0
                                                       (*i2)->getValue() + " is not a valid number");
1887
0
                                    return;
1888
0
                                }
1889
0
                                ++i2;
1890
0
                            }
1891
1892
0
                            mPass->setFog(val, mode, clr, dens, start, end);
1893
0
                        }
1894
0
                        else
1895
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1896
0
                                               prop->values.front()->getValue() + " is not a valid boolean");
1897
0
                    }
1898
0
                    break;
1899
0
                case ID_COLOUR_WRITE:
1900
0
                    if(prop->values.empty())
1901
0
                    {
1902
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
1903
0
                    }
1904
0
                    else if(prop->values.size() == 1)
1905
0
                    {
1906
0
                        if(getValue(prop, compiler, bval))
1907
0
                            mPass->setColourWriteEnabled(bval);
1908
0
                    }
1909
0
                    else if(prop->values.size() != 4)
1910
0
                    {
1911
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
1912
0
                                           "colour_write must have exactly 1 or 4 arguments");
1913
0
                    }
1914
0
                    else
1915
0
                    {
1916
0
                        bool colourMask[] = {false ,false ,false, false};
1917
1918
0
                        uint8 channelIndex = 0;
1919
0
                        for(const AbstractNodePtr& abstractNode : prop->values)
1920
0
                        {
1921
0
                            if(!getBoolean(abstractNode, &colourMask[channelIndex++]))
1922
0
                            {
1923
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1924
0
                                                   abstractNode->getValue() + " is not a valid boolean");
1925
0
                                break;
1926
0
                            }
1927
0
                        }
1928
1929
0
                        mPass->setColourWriteEnabled(colourMask[0], colourMask[1], colourMask[2], colourMask[3]);
1930
0
                    }
1931
0
                    break;
1932
0
                case ID_MAX_LIGHTS:
1933
0
                    if(getValue(prop, compiler, uival))
1934
0
                        mPass->setMaxSimultaneousLights(Math::uint16Cast(uival));
1935
0
                    break;
1936
0
                case ID_START_LIGHT:
1937
0
                    if(getValue(prop, compiler, uival))
1938
0
                        mPass->setStartLight(static_cast<uint16>(uival));
1939
0
                    break;
1940
0
                case ID_LIGHT_MASK:
1941
0
                    if(getValue(prop, compiler, uival))
1942
0
                        mPass->setLightMask(static_cast<uint16>(uival));
1943
0
                    break;
1944
0
                case ID_ITERATION:
1945
0
                    if(prop->values.empty())
1946
0
                    {
1947
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
1948
0
                    }
1949
0
                    else
1950
0
                    {
1951
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0);
1952
0
                        if((*i0)->type == ANT_ATOM)
1953
0
                        {
1954
0
                            AtomAbstractNode *atom = (AtomAbstractNode*)(*i0).get();
1955
0
                            if(atom->id == ID_ONCE)
1956
0
                            {
1957
0
                                mPass->setIteratePerLight(false);
1958
0
                            }
1959
0
                            else if(atom->id == ID_ONCE_PER_LIGHT)
1960
0
                            {
1961
0
                                AbstractNodeList::const_iterator i1 = getNodeAt(prop->values, 1);
1962
0
                                if(i1 != prop->values.end() && (*i1)->type == ANT_ATOM)
1963
0
                                {
1964
0
                                    atom = (AtomAbstractNode*)(*i1).get();
1965
0
                                    switch(atom->id)
1966
0
                                    {
1967
0
                                    case ID_POINT:
1968
0
                                        mPass->setIteratePerLight(true);
1969
0
                                        break;
1970
0
                                    case ID_DIRECTIONAL:
1971
0
                                        mPass->setIteratePerLight(true, true, Light::LT_DIRECTIONAL);
1972
0
                                        break;
1973
0
                                    case ID_SPOT:
1974
0
                                        mPass->setIteratePerLight(true, true, Light::LT_SPOTLIGHT);
1975
0
                                        break;
1976
0
                                    default:
1977
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
1978
0
                                                           prop->values.front()->getValue() + " is not a valid light type (point, directional, or spot)");
1979
0
                                    }
1980
0
                                }
1981
0
                                else
1982
0
                                {
1983
0
                                    mPass->setIteratePerLight(true, false);
1984
0
                                }
1985
1986
0
                            }
1987
0
                            else if(getValue(*i0, uival))
1988
0
                            {
1989
0
                                mPass->setPassIterationCount(uival);
1990
1991
0
                                AbstractNodeList::const_iterator i1 = getNodeAt(prop->values, 1);
1992
0
                                if(i1 != prop->values.end() && (*i1)->type == ANT_ATOM)
1993
0
                                {
1994
0
                                    atom = (AtomAbstractNode*)(*i1).get();
1995
0
                                    if(atom->id == ID_PER_LIGHT)
1996
0
                                    {
1997
0
                                        AbstractNodeList::const_iterator i2 = getNodeAt(prop->values, 2);
1998
0
                                        if(i2 != prop->values.end() && (*i2)->type == ANT_ATOM)
1999
0
                                        {
2000
0
                                            atom = (AtomAbstractNode*)(*i2).get();
2001
0
                                            switch(atom->id)
2002
0
                                            {
2003
0
                                            case ID_POINT:
2004
0
                                                mPass->setIteratePerLight(true);
2005
0
                                                break;
2006
0
                                            case ID_DIRECTIONAL:
2007
0
                                                mPass->setIteratePerLight(true, true, Light::LT_DIRECTIONAL);
2008
0
                                                break;
2009
0
                                            case ID_SPOT:
2010
0
                                                mPass->setIteratePerLight(true, true, Light::LT_SPOTLIGHT);
2011
0
                                                break;
2012
0
                                            default:
2013
0
                                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2014
0
                                                                   (*i2)->getValue() + " is not a valid light type (point, directional, or spot)");
2015
0
                                            }
2016
0
                                        }
2017
0
                                        else
2018
0
                                        {
2019
0
                                            mPass->setIteratePerLight(true, false);
2020
0
                                        }
2021
0
                                    }
2022
0
                                    else if(atom->id == ID_PER_N_LIGHTS)
2023
0
                                    {
2024
0
                                        AbstractNodeList::const_iterator i2 = getNodeAt(prop->values, 2);
2025
0
                                        if(i2 != prop->values.end() && (*i2)->type == ANT_ATOM)
2026
0
                                        {
2027
0
                                            if(getValue(*i2, uival))
2028
0
                                            {
2029
0
                                                mPass->setLightCountPerIteration(static_cast<unsigned short>(uival));
2030
2031
0
                                                AbstractNodeList::const_iterator i3 = getNodeAt(prop->values, 3);
2032
0
                                                if(i3 != prop->values.end() && (*i3)->type == ANT_ATOM)
2033
0
                                                {
2034
0
                                                    atom = (AtomAbstractNode*)(*i3).get();
2035
0
                                                    switch(atom->id)
2036
0
                                                    {
2037
0
                                                    case ID_POINT:
2038
0
                                                        mPass->setIteratePerLight(true);
2039
0
                                                        break;
2040
0
                                                    case ID_DIRECTIONAL:
2041
0
                                                        mPass->setIteratePerLight(true, true, Light::LT_DIRECTIONAL);
2042
0
                                                        break;
2043
0
                                                    case ID_SPOT:
2044
0
                                                        mPass->setIteratePerLight(true, true, Light::LT_SPOTLIGHT);
2045
0
                                                        break;
2046
0
                                                    default:
2047
0
                                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2048
0
                                                                           (*i3)->getValue() + " is not a valid light type (point, directional, or spot)");
2049
0
                                                    }
2050
0
                                                }
2051
0
                                                else
2052
0
                                                {
2053
0
                                                    mPass->setIteratePerLight(true, false);
2054
0
                                                }
2055
0
                                            }
2056
0
                                            else
2057
0
                                            {
2058
0
                                                compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
2059
0
                                                                   (*i2)->getValue() + " is not a valid number");
2060
0
                                            }
2061
0
                                        }
2062
0
                                        else
2063
0
                                        {
2064
0
                                            compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
2065
0
                                                               prop->values.front()->getValue() + " is not a valid number");
2066
0
                                        }
2067
0
                                    }
2068
0
                                }
2069
0
                            }
2070
0
                            else
2071
0
                            {
2072
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
2073
0
                            }
2074
0
                        }
2075
0
                        else
2076
0
                        {
2077
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
2078
0
                        }
2079
0
                    }
2080
0
                    break;
2081
0
                case ID_LINE_WIDTH:
2082
0
                    if(getValue(prop, compiler, fval))
2083
0
                        mPass->setLineWidth(fval);
2084
0
                    break;
2085
0
                case ID_POINT_SIZE:
2086
0
                    if(getValue(prop, compiler, fval))
2087
0
                        mPass->setPointSize(fval);
2088
0
                    break;
2089
0
                case ID_POINT_SPRITES:
2090
0
                    if(getValue(prop, compiler, bval))
2091
0
                        mPass->setPointSpritesEnabled(bval);
2092
0
                    break;
2093
0
                case ID_POINT_SIZE_ATTENUATION:
2094
0
                    if(prop->values.empty())
2095
0
                    {
2096
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
2097
0
                    }
2098
0
                    else if(prop->values.size() > 4)
2099
0
                    {
2100
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
2101
0
                                           "point_size_attenuation must have at most 4 arguments");
2102
0
                    }
2103
0
                    else
2104
0
                    {
2105
0
                        bool val = false;
2106
0
                        if(getBoolean(prop->values.front(), &val))
2107
0
                        {
2108
0
                            if(val)
2109
0
                            {
2110
0
                                AbstractNodeList::const_iterator i1 = getNodeAt(prop->values, 1), i2 = getNodeAt(prop->values, 2),
2111
0
                                    i3 = getNodeAt(prop->values, 3);
2112
2113
0
                                if (prop->values.size() > 1)
2114
0
                                {
2115
2116
0
                                    Real constant = 0.0f, linear = 1.0f, quadratic = 0.0f;
2117
2118
0
                                    if(i1 == prop->values.end() || !getValue(*i1, constant))
2119
0
                                    {
2120
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2121
0
                                                           (*i1)->getValue() + " is not a valid number");
2122
0
                                    }
2123
2124
0
                                    if(i2 == prop->values.end() || !getValue(*i2, linear))
2125
0
                                    {
2126
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2127
0
                                                           (*i2)->getValue() + " is not a valid number");
2128
0
                                    }
2129
2130
0
                                    if(i3 == prop->values.end() && !getValue(*i3, quadratic))
2131
0
                                    {
2132
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2133
0
                                                           (*i3)->getValue() + " is not a valid number");
2134
0
                                    }
2135
2136
0
                                    mPass->setPointAttenuation(true, constant, linear, quadratic);
2137
0
                                }
2138
0
                                else
2139
0
                                {
2140
0
                                    mPass->setPointAttenuation(true);
2141
0
                                }
2142
0
                            }
2143
0
                            else
2144
0
                            {
2145
0
                                mPass->setPointAttenuation(false);
2146
0
                            }
2147
0
                        }
2148
0
                        else
2149
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2150
0
                                               prop->values.front()->getValue() + " is not a valid boolean");
2151
0
                    }
2152
0
                    break;
2153
0
                case ID_POINT_SIZE_MIN:
2154
0
                    if(getValue(prop, compiler, fval))
2155
0
                        mPass->setPointMinSize(fval);
2156
0
                    break;
2157
0
                case ID_POINT_SIZE_MAX:
2158
0
                    if(getValue(prop, compiler, fval))
2159
0
                        mPass->setPointMaxSize(fval);
2160
0
                    break;
2161
0
                default:
2162
0
                    compiler->addError(ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
2163
0
                                       "token \"" + prop->name + "\" is not recognized");
2164
0
                }
2165
0
            }
2166
0
            else if(i->type == ANT_OBJECT)
2167
0
            {
2168
0
                ObjectAbstractNode *child = static_cast<ObjectAbstractNode*>(i.get());
2169
0
                switch(child->id)
2170
0
                {
2171
0
                case ID_FRAGMENT_PROGRAM_REF:
2172
0
                case ID_VERTEX_PROGRAM_REF:
2173
0
                case ID_GEOMETRY_PROGRAM_REF:
2174
0
                case ID_TESSELLATION_HULL_PROGRAM_REF:
2175
0
                case ID_TESSELLATION_DOMAIN_PROGRAM_REF:
2176
0
                case ID_COMPUTE_PROGRAM_REF:
2177
0
                case ID_MESH_PROGRAM_REF:
2178
0
                case ID_TASK_PROGRAM_REF:
2179
0
                    translateProgramRef(getProgramType(child->id), compiler, child);
2180
0
                    break;
2181
0
                case ID_SHADOW_CASTER_VERTEX_PROGRAM_REF:
2182
0
                    translateShadowCasterProgramRef(GPT_VERTEX_PROGRAM, compiler, child);
2183
0
                    break;
2184
0
                case ID_SHADOW_CASTER_FRAGMENT_PROGRAM_REF:
2185
0
                    translateShadowCasterProgramRef(GPT_FRAGMENT_PROGRAM, compiler, child);
2186
0
                    break;
2187
0
                case ID_SHADOW_RECEIVER_VERTEX_PROGRAM_REF:
2188
0
                    translateShadowReceiverProgramRef(GPT_VERTEX_PROGRAM, compiler, child);
2189
0
                    break;
2190
0
                case ID_SHADOW_RECEIVER_FRAGMENT_PROGRAM_REF:
2191
0
                    translateShadowReceiverProgramRef(GPT_FRAGMENT_PROGRAM, compiler, child);
2192
0
                    break;
2193
0
                default:
2194
0
                    processNode(compiler, i);
2195
0
                    break;
2196
0
                case ID_FRAGMENT_PROGRAM:
2197
0
                case ID_VERTEX_PROGRAM:
2198
0
                case ID_GEOMETRY_PROGRAM:
2199
0
                case ID_TESSELLATION_HULL_PROGRAM:
2200
0
                case ID_TESSELLATION_DOMAIN_PROGRAM:
2201
0
                case ID_COMPUTE_PROGRAM:
2202
0
                case ID_MESH_PROGRAM:
2203
0
                case ID_TASK_PROGRAM:
2204
0
                {
2205
                    // auto assign inline defined programs
2206
0
                    processNode(compiler, i);
2207
0
                    GpuProgramType type = getProgramType(child->id);
2208
0
                    mPass->setGpuProgram(type, GpuProgramUsage::_getProgramByName(child->name, mPass->getResourceGroup(), type));
2209
0
                }
2210
0
                }
2211
0
            }
2212
0
        }
2213
0
    }
2214
2215
    static GpuProgramPtr getProgram(ScriptCompiler* compiler, ObjectAbstractNode* node)
2216
0
    {
2217
0
        if(node->name.empty())
2218
0
        {
2219
0
            compiler->addError(ScriptCompiler::CE_OBJECTNAMEEXPECTED, node->file, node->line);
2220
0
            return nullptr;
2221
0
        }
2222
2223
0
        ProcessResourceNameScriptCompilerEvent evt(ProcessResourceNameScriptCompilerEvent::GPU_PROGRAM, node->name);
2224
0
        compiler->_fireEvent(&evt, 0);
2225
2226
0
        auto& mgr = GpuProgramManager::getSingleton();
2227
0
        if (auto ret = mgr.getByName(evt.mName, compiler->getResourceGroup()))
2228
0
            return ret;
2229
2230
        // recheck with auto resource group
2231
0
        if (auto ret = mgr.getByName(evt.mName, RGN_AUTODETECT))
2232
0
            return ret;
2233
2234
0
        compiler->addError(ScriptCompiler::CE_REFERENCETOANONEXISTINGOBJECT, node->file, node->line,
2235
0
                           evt.mName);
2236
0
        return nullptr;
2237
0
    }
2238
2239
    //-------------------------------------------------------------------------
2240
    void PassTranslator::translateProgramRef(GpuProgramType type, ScriptCompiler *compiler, ObjectAbstractNode *node)
2241
0
    {
2242
0
        auto program = getProgram(compiler, node);
2243
0
        if(!program) return;
2244
0
        auto pass = any_cast<Pass*>(node->parent->context);
2245
2246
0
        pass->setGpuProgram(type, program);
2247
0
        if(program->isSupported())
2248
0
        {
2249
0
            GpuProgramParametersSharedPtr params = pass->getGpuProgramParameters(type);
2250
0
            GpuProgramTranslator::translateProgramParameters(compiler, params, node);
2251
0
        }
2252
0
    }
2253
    //-------------------------------------------------------------------------
2254
    void PassTranslator::translateShadowCasterProgramRef(GpuProgramType type, ScriptCompiler *compiler, ObjectAbstractNode *node)
2255
0
    {
2256
0
        auto program = getProgram(compiler, node);
2257
0
        if(!program) return;
2258
0
        auto pass = any_cast<Pass*>(node->parent->context);
2259
2260
0
        compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, node->file, node->line,
2261
0
                           node->cls + ". Use shadow_caster_material instead");
2262
2263
0
        auto caster_mat = pass->getParent()->getShadowCasterMaterial();
2264
0
        if(!caster_mat)
2265
0
        {
2266
0
            auto src_mat = pass->getParent()->getParent();
2267
            // only first pass of this will be used. The caster material is technique specific.
2268
0
            caster_mat = src_mat->clone(
2269
0
                StringUtil::format("%s/%p/CasterFallback", src_mat->getName().c_str(), pass->getParent()));
2270
0
            pass->getParent()->setShadowCasterMaterial(caster_mat);
2271
0
        }
2272
0
        auto caster_pass = caster_mat->getTechnique(0)->getPass(0);
2273
2274
0
        caster_pass->setGpuProgram(type, program);
2275
0
        if(program->isSupported())
2276
0
        {
2277
0
            GpuProgramParametersSharedPtr params = caster_pass->getGpuProgramParameters(type);
2278
0
            GpuProgramTranslator::translateProgramParameters(compiler, params, node);
2279
0
        }
2280
0
    }
2281
    //-------------------------------------------------------------------------
2282
    void PassTranslator::translateShadowReceiverProgramRef(GpuProgramType type,ScriptCompiler *compiler, ObjectAbstractNode *node)
2283
0
    {
2284
0
        auto program = getProgram(compiler, node);
2285
0
        if(!program) return;
2286
0
        auto pass = any_cast<Pass*>(node->parent->context);
2287
2288
0
        compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, node->file, node->line,
2289
0
                           node->cls + ". Use shadow_receiver_material instead");
2290
2291
0
        auto receiver_mat = pass->getParent()->getShadowReceiverMaterial();
2292
0
        if(!receiver_mat)
2293
0
        {
2294
0
            auto src_mat = pass->getParent()->getParent();
2295
            // only first pass of this will be used
2296
0
            receiver_mat = src_mat->clone(src_mat->getName()+"/ReceiverFallback");
2297
0
            pass->getParent()->setShadowReceiverMaterial(receiver_mat);
2298
0
        }
2299
0
        auto receiver_pass = receiver_mat->getTechnique(0)->getPass(0);
2300
2301
0
        receiver_pass->setGpuProgram(type, program);
2302
0
        if(program->isSupported())
2303
0
        {
2304
0
            GpuProgramParametersSharedPtr params = receiver_pass->getGpuProgramParameters(type);
2305
0
            GpuProgramTranslator::translateProgramParameters(compiler, params, node);
2306
0
        }
2307
0
    }
2308
    /**************************************************************************
2309
     * TextureUnitTranslator
2310
     *************************************************************************/
2311
    TextureUnitTranslator::TextureUnitTranslator()
2312
0
        :mUnit(0)
2313
0
    {
2314
0
    }
2315
    //-------------------------------------------------------------------------
2316
    void SamplerTranslator::translateSamplerParam(ScriptCompiler* compiler, const SamplerPtr& sampler, PropertyAbstractNode* prop)
2317
0
    {
2318
0
        bool bval;
2319
0
        Real fval;
2320
0
        uint32 uival;
2321
2322
0
        switch(prop->id)
2323
0
        {
2324
0
        case ID_TEX_ADDRESS_MODE:
2325
0
            {
2326
0
                if(prop->values.empty())
2327
0
                {
2328
0
                    compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
2329
0
                }
2330
0
                else
2331
0
                {
2332
0
                    AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0),
2333
0
                        i1 = getNodeAt(prop->values, 1),
2334
0
                        i2 = getNodeAt(prop->values, 2);
2335
0
                    Sampler::UVWAddressingMode mode;
2336
2337
0
                    if(!getValue(*i0, mode.u))
2338
0
                    {
2339
0
                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2340
0
                                           (*i0)->getValue() + " not supported as first argument (must be \"wrap\", \"clamp\", \"mirror\", or \"border\")");
2341
0
                        return;
2342
0
                    }
2343
0
                    mode.v = mode.u;
2344
0
                    mode.w = mode.u;
2345
2346
0
                    if(i1 != prop->values.end())
2347
0
                    {
2348
0
                        if(!getValue(*i1, mode.v))
2349
0
                        {
2350
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2351
0
                                               (*i1)->getValue() + " not supported as second argument (must be \"wrap\", \"clamp\", \"mirror\", or \"border\")");
2352
0
                        }
2353
0
                    }
2354
2355
0
                    if(i2 != prop->values.end())
2356
0
                    {
2357
0
                        if(!getValue(*i2, mode.w))
2358
0
                        {
2359
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2360
0
                                               (*i2)->getValue() + " not supported as third argument (must be \"wrap\", \"clamp\", \"mirror\", or \"border\")");
2361
0
                        }
2362
0
                    }
2363
2364
0
                    sampler->setAddressingMode(mode);
2365
0
                }
2366
0
            }
2367
0
            break;
2368
0
        case ID_TEX_BORDER_COLOUR:
2369
0
            if(prop->values.empty())
2370
0
            {
2371
0
                compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line);
2372
0
            }
2373
0
            else
2374
0
            {
2375
0
                ColourValue val;
2376
0
                if(getColour(prop->values.begin(), prop->values.end(), &val))
2377
0
                    sampler->setBorderColour(val);
2378
0
                else
2379
0
                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2380
0
                                       "tex_border_colour only accepts a colour argument");
2381
0
            }
2382
0
            break;
2383
0
        case ID_FILTERING:
2384
0
            if(prop->values.empty())
2385
0
            {
2386
0
                compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
2387
0
            }
2388
0
            else if(prop->values.size() == 1)
2389
0
            {
2390
0
                if(prop->values.front()->type == ANT_ATOM)
2391
0
                {
2392
0
                    AtomAbstractNode *atom = (AtomAbstractNode*)prop->values.front().get();
2393
0
                    switch(atom->id)
2394
0
                    {
2395
0
                    case ID_NONE:
2396
0
                        sampler->setFiltering(TFO_NONE);
2397
0
                        break;
2398
0
                    case ID_BILINEAR:
2399
0
                        sampler->setFiltering(TFO_BILINEAR);
2400
0
                        break;
2401
0
                    case ID_TRILINEAR:
2402
0
                        sampler->setFiltering(TFO_TRILINEAR);
2403
0
                        break;
2404
0
                    case ID_ANISOTROPIC:
2405
0
                        sampler->setFiltering(TFO_ANISOTROPIC);
2406
0
                        break;
2407
0
                    default:
2408
0
                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2409
0
                                           prop->values.front()->getValue() + " not supported as first argument (must be \"none\", \"bilinear\", \"trilinear\", or \"anisotropic\")");
2410
0
                    }
2411
0
                }
2412
0
                else
2413
0
                {
2414
0
                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2415
0
                                       prop->values.front()->getValue() + " not supported as first argument (must be \"none\", \"bilinear\", \"trilinear\", or \"anisotropic\")");
2416
0
                }
2417
0
            }
2418
0
            else if(prop->values.size() == 3)
2419
0
            {
2420
0
                AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0),
2421
0
                    i1 = getNodeAt(prop->values, 1),
2422
0
                    i2 = getNodeAt(prop->values, 2);
2423
0
                FilterOptions tmin, tmax, tmip;
2424
0
                if (getValue(*i0, tmin) && getValue(*i1, tmax) && getValue(*i2, tmip))
2425
0
                {
2426
0
                    sampler->setFiltering(tmin, tmax, tmip);
2427
0
                }
2428
0
                else
2429
0
                {
2430
0
                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
2431
0
                }
2432
0
            }
2433
0
            else
2434
0
            {
2435
0
                compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
2436
0
                                   "filtering must have either 1 or 3 arguments");
2437
0
            }
2438
0
            break;
2439
0
        case ID_CMPTEST:
2440
0
            if(getValue(prop, compiler, bval))
2441
0
                sampler->setCompareEnabled(bval);
2442
0
            break;
2443
0
        case ID_CMPFUNC:
2444
0
            compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file,
2445
0
                prop->line,
2446
0
                "compare_func. Use comp_func.");
2447
0
            OGRE_FALLTHROUGH;
2448
0
        case ID_COMP_FUNC:
2449
0
            CompareFunction func;
2450
0
            if(getValue(prop, compiler, func))
2451
0
                sampler->setCompareFunction(func);
2452
0
            break;
2453
0
        case ID_MAX_ANISOTROPY:
2454
0
            if(getValue(prop, compiler, uival))
2455
0
                sampler->setAnisotropy(uival);
2456
0
            break;
2457
0
        case ID_MIPMAP_BIAS:
2458
0
            if(getValue(prop, compiler, fval))
2459
0
                sampler->setMipmapBias(fval);
2460
0
            break;
2461
0
        }
2462
0
    }
2463
    void SamplerTranslator::translate(ScriptCompiler *compiler, const Ogre::AbstractNodePtr &node)
2464
0
    {
2465
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
2466
2467
0
        if(obj->name.empty())
2468
0
        {
2469
0
            compiler->addError(ScriptCompiler::CE_OBJECTNAMEEXPECTED, obj->file, obj->line);
2470
0
            return;
2471
0
        }
2472
2473
0
        SamplerPtr sampler = TextureManager::getSingleton().createSampler(obj->name);
2474
2475
        // Set the properties for the material
2476
0
        for(auto & i : obj->children)
2477
0
        {
2478
0
            if(i->type == ANT_PROPERTY)
2479
0
            {
2480
0
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
2481
0
                switch(prop->id)
2482
0
                {
2483
0
                case ID_TEX_ADDRESS_MODE:
2484
0
                case ID_TEX_BORDER_COLOUR:
2485
0
                case ID_FILTERING:
2486
0
                case ID_CMPTEST:
2487
0
                case ID_COMP_FUNC:
2488
0
                case ID_MAX_ANISOTROPY:
2489
0
                case ID_MIPMAP_BIAS:
2490
0
                    translateSamplerParam(compiler, sampler, prop);
2491
0
                    break;
2492
0
                default:
2493
0
                    compiler->addError(ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
2494
0
                                       "token \"" + prop->name + "\" is not recognized");
2495
0
                }
2496
0
            }
2497
0
            else if(i->type == ANT_OBJECT)
2498
0
            {
2499
0
                processNode(compiler, i);
2500
0
            }
2501
0
        }
2502
0
    }
2503
2504
    void TextureUnitTranslator::translate(ScriptCompiler *compiler, const Ogre::AbstractNodePtr &node)
2505
0
    {
2506
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
2507
2508
0
        Pass *pass = any_cast<Pass*>(obj->parent->context);
2509
0
        mUnit = pass->createTextureUnitState();
2510
0
        obj->context = mUnit;
2511
2512
        // Get the name of the technique
2513
0
        if(!obj->name.empty())
2514
0
            mUnit->setName(obj->name);
2515
2516
0
        Real fval;
2517
0
        uint32 uival;
2518
0
        String sval;
2519
2520
        // Set the properties for the material
2521
0
        for(auto & i : obj->children)
2522
0
        {
2523
0
            if(i->type == ANT_PROPERTY)
2524
0
            {
2525
0
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
2526
0
                switch(prop->id)
2527
0
                {
2528
0
                case ID_TEX_ADDRESS_MODE:
2529
0
                case ID_TEX_BORDER_COLOUR:
2530
0
                case ID_FILTERING:
2531
0
                case ID_CMPTEST:
2532
0
                case ID_CMPFUNC:
2533
0
                case ID_COMP_FUNC:
2534
0
                case ID_MAX_ANISOTROPY:
2535
0
                case ID_MIPMAP_BIAS:
2536
0
                    SamplerTranslator::translateSamplerParam(compiler, mUnit->_getLocalSampler(), prop);
2537
0
                    break;
2538
0
                case ID_SAMPLER_REF:
2539
0
                    if(getValue(prop, compiler, sval))
2540
0
                    {
2541
0
                        auto sampler = TextureManager::getSingleton().getSampler(sval);
2542
0
                        if(sampler)
2543
0
                            mUnit->setSampler(sampler);
2544
0
                        else
2545
0
                            compiler->addError(ScriptCompiler::CE_REFERENCETOANONEXISTINGOBJECT,
2546
0
                                               prop->file, prop->line, sval);
2547
0
                    }
2548
0
                    break;
2549
0
                case ID_UNORDERED_ACCESS_MIP:
2550
0
                    if(getValue(prop, compiler, uival))
2551
0
                        mUnit->setUnorderedAccessMipLevel(uival);
2552
0
                    break;
2553
0
                case ID_TEXTURE_ALIAS:
2554
0
                    compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file, prop->line,
2555
0
                        "texture_alias. Use 'texture $variable'");
2556
0
                    if(getValue(prop, compiler, sval))
2557
0
                        mUnit->setName(sval);
2558
0
                    break;
2559
0
                case ID_TEXTURE:
2560
0
                    if(prop->values.empty())
2561
0
                    {
2562
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
2563
0
                    }
2564
0
                    else if(prop->values.size() > 5)
2565
0
                    {
2566
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
2567
0
                                           "texture must have at most 5 arguments");
2568
0
                    }
2569
0
                    else
2570
0
                    {
2571
0
                        AbstractNodeList::const_iterator j = prop->values.begin();
2572
0
                        String val;
2573
0
                        if(getString(*j, &val))
2574
0
                        {
2575
0
                            TextureType texType = TEX_TYPE_2D;
2576
0
                            bool isAlpha = false;
2577
0
                            bool sRGBRead = false;
2578
0
                            PixelFormat format = PF_UNKNOWN;
2579
0
                            int mipmaps = TextureManager::getSingleton().getDefaultNumMipmaps(); // MIP_DEFAULT
2580
2581
0
                            ++j;
2582
0
                            while(j != prop->values.end())
2583
0
                            {
2584
0
                                if((*j)->type == ANT_ATOM)
2585
0
                                {
2586
0
                                    AtomAbstractNode *atom = (AtomAbstractNode*)(*j).get();
2587
0
                                    switch(atom->id)
2588
0
                                    {
2589
0
                                    case ID_1D:
2590
0
                                        texType = TEX_TYPE_1D;
2591
0
                                        break;
2592
0
                                    case ID_2D:
2593
0
                                        texType = TEX_TYPE_2D;
2594
0
                                        break;
2595
0
                                    case ID_3D:
2596
0
                                        texType = TEX_TYPE_3D;
2597
0
                                        break;
2598
0
                                    case ID_CUBIC:
2599
0
                                        texType = TEX_TYPE_CUBE_MAP;
2600
0
                                        break;
2601
0
                                    case ID_2DARRAY:
2602
0
                                        texType = TEX_TYPE_2D_ARRAY;
2603
0
                                        break;
2604
0
                                    case ID_UNLIMITED:
2605
0
                                        mipmaps = MIP_UNLIMITED;
2606
0
                                        break;
2607
0
                                    case ID_ALPHA:
2608
0
                                        isAlpha = true;
2609
0
                                        break;
2610
0
                                    case ID_GAMMA:
2611
0
                                        sRGBRead = true;
2612
0
                                        break;
2613
0
                                    default:
2614
0
                                        if(!StringConverter::parse(atom->value, mipmaps))
2615
0
                                        {
2616
0
                                            format = PixelUtil::getFormatFromName(atom->value, true);
2617
2618
0
                                            if (format == PF_UNKNOWN)
2619
0
                                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS,
2620
0
                                                                   prop->file, prop->line, atom->value);
2621
0
                                        }
2622
0
                                    }
2623
0
                                }
2624
0
                                else
2625
0
                                {
2626
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2627
0
                                                       (*j)->getValue() + " is not a supported argument to the texture property");
2628
0
                                }
2629
0
                                ++j;
2630
0
                            }
2631
2632
0
                            ProcessResourceNameScriptCompilerEvent evt(ProcessResourceNameScriptCompilerEvent::TEXTURE, val);
2633
0
                            compiler->_fireEvent(&evt, 0);
2634
2635
0
                            if(isAlpha)
2636
0
                            {
2637
                                // format = PF_A8; should only be done, if src is luminance, which we dont know here
2638
0
                                compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file,
2639
0
                                                   prop->line, "alpha. Use PF_A8 instead");
2640
0
                            }
2641
2642
0
                            if(const auto& tex = TextureManager::getSingleton().getByName(evt.mName, mUnit->getParent()->getResourceGroup()))
2643
0
                            {
2644
                                // the texture is shared with another texture unit, report any discrepancies
2645
0
                                if (tex->getDesiredFormat() != format || tex->getNumMipmaps() != uint(mipmaps) ||
2646
0
                                    tex->isHardwareGammaEnabled() != sRGBRead || tex->getTextureType() != texType)
2647
0
                                {
2648
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2649
0
                                                       "overriding previous declarations of texture '" + evt.mName +
2650
0
                                                           "' with different parameters");
2651
0
                                }
2652
0
                            }
2653
2654
0
                            mUnit->setTextureName(evt.mName, texType);
2655
0
                            mUnit->setDesiredFormat(format);
2656
0
                            OGRE_IGNORE_DEPRECATED_BEGIN
2657
0
                            mUnit->setIsAlpha(isAlpha);
2658
0
                            OGRE_IGNORE_DEPRECATED_END
2659
0
                            mUnit->setNumMipmaps(mipmaps);
2660
0
                            mUnit->setHardwareGammaEnabled(sRGBRead);
2661
0
                        }
2662
0
                        else
2663
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2664
0
                                               (*j)->getValue() + " is not a valid texture name");
2665
0
                    }
2666
0
                    break;
2667
0
                case ID_ANIM_TEXTURE:
2668
0
                    if(prop->values.size() < 3)
2669
0
                    {
2670
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
2671
0
                    }
2672
0
                    else
2673
0
                    {
2674
0
                        AbstractNodeList::const_iterator i1 = getNodeAt(prop->values, 1);
2675
0
                        uint32 nframes = 0;
2676
0
                        if(getValue(*i1, nframes))
2677
0
                        {
2678
                            // Short form
2679
0
                            AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i2 = getNodeAt(prop->values, 2);
2680
0
                            String val0;
2681
0
                            Real val2;
2682
0
                            if(getValue(*i0, val0) && getValue(*i2, val2))
2683
0
                            {
2684
0
                                ProcessResourceNameScriptCompilerEvent evt(ProcessResourceNameScriptCompilerEvent::TEXTURE, val0);
2685
0
                                compiler->_fireEvent(&evt, 0);
2686
2687
0
                                mUnit->setAnimatedTextureName(evt.mName, nframes, val2);
2688
0
                            }
2689
0
                            else
2690
0
                            {
2691
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2692
0
                                                   "anim_texture short form requires a texture name, number of frames, and animation duration");
2693
0
                            }
2694
0
                        }
2695
0
                        else
2696
0
                        {
2697
                            // Long form has n number of frames
2698
0
                            Real duration = 0;
2699
0
                            AbstractNodeList::const_iterator in = getNodeAt(prop->values, static_cast<int>(prop->values.size()) - 1);
2700
0
                            if(getReal(*in, &duration))
2701
0
                            {
2702
0
                                std::vector<String> names;
2703
2704
0
                                AbstractNodeList::iterator j = prop->values.begin();
2705
0
                                while(j != in)
2706
0
                                {
2707
0
                                    if((*j)->type == ANT_ATOM)
2708
0
                                    {
2709
0
                                        String name = ((AtomAbstractNode*)(*j).get())->value;
2710
                                        // Run the name through the listener
2711
0
                                        if(compiler->getListener())
2712
0
                                        {
2713
0
                                            ProcessResourceNameScriptCompilerEvent evt(ProcessResourceNameScriptCompilerEvent::TEXTURE, name);
2714
0
                                            compiler->_fireEvent(&evt, 0);
2715
0
                                            names.push_back(evt.mName);
2716
0
                                        }
2717
0
                                        else
2718
0
                                        {
2719
0
                                            names.push_back(name);
2720
0
                                        }
2721
0
                                    }
2722
0
                                    else
2723
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2724
0
                                                           (*j)->getValue() + " is not supported as a texture name");
2725
0
                                    ++j;
2726
0
                                }
2727
2728
0
                                mUnit->setAnimatedTextureName(names, duration);
2729
0
                            }
2730
0
                            else
2731
0
                            {
2732
0
                                compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
2733
0
                                                   (*in)->getValue() + " is not supported for the duration argument");
2734
0
                            }
2735
0
                        }
2736
0
                    }
2737
0
                    break;
2738
0
                case ID_CUBIC_TEXTURE:
2739
0
                    if(prop->values.empty())
2740
0
                    {
2741
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
2742
0
                    }
2743
0
                    else if(prop->values.size() == 2)
2744
0
                    {
2745
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0),
2746
0
                            i1 = getNodeAt(prop->values, 1);
2747
0
                        if((*i0)->type == ANT_ATOM && (*i1)->type == ANT_ATOM)
2748
0
                        {
2749
0
                            AtomAbstractNode *atom0 = (AtomAbstractNode*)(*i0).get();
2750
2751
0
                            ProcessResourceNameScriptCompilerEvent evt(ProcessResourceNameScriptCompilerEvent::TEXTURE, atom0->value);
2752
0
                            compiler->_fireEvent(&evt, 0);
2753
2754
0
                            mUnit->setTextureName(evt.mName, TEX_TYPE_CUBE_MAP);
2755
2756
0
                            compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file, prop->line,
2757
0
                                                   "'cubic_texture ..'. Use 'texture .. cubic' instead.");
2758
0
                        }
2759
0
                        else
2760
0
                        {
2761
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
2762
0
                        }
2763
0
                    }
2764
0
                    else if(prop->values.size() == 7)
2765
0
                    {
2766
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0),
2767
0
                            i1 = getNodeAt(prop->values, 1),
2768
0
                            i2 = getNodeAt(prop->values, 2),
2769
0
                            i3 = getNodeAt(prop->values, 3),
2770
0
                            i4 = getNodeAt(prop->values, 4),
2771
0
                            i5 = getNodeAt(prop->values, 5),
2772
0
                            i6 = getNodeAt(prop->values, 6);
2773
0
                        if((*i0)->type == ANT_ATOM && (*i1)->type == ANT_ATOM && (*i2)->type == ANT_ATOM && (*i3)->type == ANT_ATOM &&
2774
0
                           (*i4)->type == ANT_ATOM && (*i5)->type == ANT_ATOM && (*i6)->type == ANT_ATOM)
2775
0
                        {
2776
0
                            AtomAbstractNode *atom0 = (AtomAbstractNode*)(*i0).get(), *atom1 = (AtomAbstractNode*)(*i1).get(),
2777
0
                                *atom2 = (AtomAbstractNode*)(*i2).get(), *atom3 = (AtomAbstractNode*)(*i3).get(),
2778
0
                                *atom4 = (AtomAbstractNode*)(*i4).get(), *atom5 = (AtomAbstractNode*)(*i5).get(),
2779
0
                                *atom6 = (AtomAbstractNode*)(*i6).get();
2780
0
                            std::vector<String> names(6);
2781
                            // backward compatible order
2782
0
                            names[4] = atom0->value;
2783
0
                            names[5] = atom1->value;
2784
0
                            names[1] = atom2->value;
2785
0
                            names[0] = atom3->value;
2786
0
                            names[2] = atom4->value;
2787
0
                            names[3] = atom5->value;
2788
2789
0
                            if(compiler->getListener())
2790
0
                            {
2791
                                // Run each name through the listener
2792
0
                                for(int j = 0; j < 6; ++j)
2793
0
                                {
2794
0
                                    ProcessResourceNameScriptCompilerEvent evt(ProcessResourceNameScriptCompilerEvent::TEXTURE, names[j]);
2795
0
                                    compiler->_fireEvent(&evt, 0);
2796
0
                                    names[j] = evt.mName;
2797
0
                                }
2798
0
                            }
2799
2800
0
                            if(atom6->id != ID_COMBINED_UVW)
2801
0
                            {
2802
0
                                compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file, prop->line,
2803
0
                                                   "separateUV is no longer supported.");
2804
0
                            }
2805
0
                            mUnit->setLayerArrayNames(TEX_TYPE_CUBE_MAP, names);
2806
0
                        }
2807
2808
0
                    }
2809
0
                    else
2810
0
                    {
2811
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
2812
0
                                           "cubic_texture must have at most 7 arguments");
2813
0
                    }
2814
0
                    break;
2815
0
                case ID_TEX_COORD_SET:
2816
0
                    if(getValue(prop, compiler, uival))
2817
0
                        mUnit->setTextureCoordSet(uival);
2818
0
                    break;
2819
2820
0
                case ID_COLOUR_OP:
2821
0
                    LayerBlendOperation cop;
2822
0
                    if(getValue(prop, compiler, cop))
2823
0
                        mUnit->setColourOperation(cop);
2824
0
                    break;
2825
0
                case ID_COLOUR_OP_EX:
2826
0
                    if(prop->values.size() < 3)
2827
0
                    {
2828
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line,
2829
0
                                           "colour_op_ex must have at least 3 arguments");
2830
0
                    }
2831
0
                    else if(prop->values.size() > 10)
2832
0
                    {
2833
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
2834
0
                                           "colour_op_ex must have at most 10 arguments");
2835
0
                    }
2836
0
                    else
2837
0
                    {
2838
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0),
2839
0
                            i1 = getNodeAt(prop->values, 1),
2840
0
                            i2 = getNodeAt(prop->values, 2);
2841
0
                        LayerBlendOperationEx op;
2842
0
                        LayerBlendSource source1, source2;
2843
0
                        if (getValue(*i0, op) && getValue(*i1, source1) && getValue(*i2, source2))
2844
0
                        {
2845
0
                            ColourValue arg1 = ColourValue::White, arg2 = ColourValue::White;
2846
0
                            Real manualBlend = 0.0f;
2847
2848
0
                            if(op == LBX_BLEND_MANUAL)
2849
0
                            {
2850
0
                                AbstractNodeList::const_iterator i3 = getNodeAt(prop->values, 3);
2851
0
                                if(i3 != prop->values.end())
2852
0
                                {
2853
0
                                    if(!getReal(*i3, &manualBlend))
2854
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2855
0
                                                           (*i3)->getValue() + " is not a valid number argument");
2856
0
                                }
2857
0
                                else
2858
0
                                {
2859
0
                                    compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
2860
0
                                                       "fourth argument expected when blend_manual is used");
2861
0
                                }
2862
0
                            }
2863
2864
0
                            AbstractNodeList::const_iterator j = getNodeAt(prop->values, 3);
2865
0
                            if(op == LBX_BLEND_MANUAL)
2866
0
                                ++j;
2867
0
                            if(source1 == LBS_MANUAL)
2868
0
                            {
2869
0
                                if(j != prop->values.end())
2870
0
                                {
2871
0
                                    if(!getColour(j, prop->values.end(), &arg1, 3))
2872
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2873
0
                                                           "valid colour expected when src_manual is used");
2874
0
                                }
2875
0
                                else
2876
0
                                {
2877
0
                                    compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
2878
0
                                                       "valid colour expected when src_manual is used");
2879
0
                                }
2880
0
                            }
2881
0
                            if(source2 == LBS_MANUAL)
2882
0
                            {
2883
0
                                if(j != prop->values.end())
2884
0
                                {
2885
0
                                    if(!getColour(j, prop->values.end(), &arg2, 3))
2886
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2887
0
                                                           "valid colour expected when src_manual is used");
2888
0
                                }
2889
0
                                else
2890
0
                                {
2891
0
                                    compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
2892
0
                                                       "valid colour expected when src_manual is used");
2893
0
                                }
2894
0
                            }
2895
2896
0
                            mUnit->setColourOperationEx(op, source1, source2, arg1, arg2, manualBlend);
2897
0
                        }
2898
0
                        else
2899
0
                        {
2900
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
2901
0
                        }
2902
0
                    }
2903
0
                    break;
2904
0
                case ID_COLOUR_OP_MULTIPASS_FALLBACK:
2905
0
                    if(prop->values.empty())
2906
0
                    {
2907
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
2908
0
                    }
2909
0
                    else if(prop->values.size() > 2)
2910
0
                    {
2911
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
2912
0
                                           "colour_op_multiplass_fallback must have at most 2 arguments");
2913
0
                    }
2914
0
                    else if(prop->values.size() == 1)
2915
0
                    {
2916
0
                        if(prop->values.front()->type == ANT_ATOM)
2917
0
                        {
2918
0
                            AtomAbstractNode *atom = (AtomAbstractNode*)prop->values.front().get();
2919
0
                            switch(atom->id)
2920
0
                            {
2921
0
                            case ID_ADD:
2922
0
                                mUnit->setColourOpMultipassFallback(SBF_ONE, SBF_ONE);
2923
0
                                break;
2924
0
                            case ID_MODULATE:
2925
0
                                mUnit->setColourOpMultipassFallback(SBF_DEST_COLOUR, SBF_ZERO);
2926
0
                                break;
2927
0
                            case ID_COLOUR_BLEND:
2928
0
                                mUnit->setColourOpMultipassFallback(SBF_SOURCE_COLOUR, SBF_ONE_MINUS_SOURCE_COLOUR);
2929
0
                                break;
2930
0
                            case ID_ALPHA_BLEND:
2931
0
                                mUnit->setColourOpMultipassFallback(SBF_SOURCE_ALPHA, SBF_ONE_MINUS_SOURCE_ALPHA);
2932
0
                                break;
2933
0
                            case ID_REPLACE:
2934
0
                                mUnit->setColourOpMultipassFallback(SBF_ONE, SBF_ZERO);
2935
0
                                break;
2936
0
                            default:
2937
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2938
0
                                                   "argument must be a valid scene blend type (add, modulate, colour_blend, alpha_blend, or replace)");
2939
0
                            }
2940
0
                        }
2941
0
                        else
2942
0
                        {
2943
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2944
0
                                               "argument must be a valid scene blend type (add, modulate, colour_blend, alpha_blend, or replace)");
2945
0
                        }
2946
0
                    }
2947
0
                    else
2948
0
                    {
2949
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1);
2950
0
                        SceneBlendFactor sbf0, sbf1;
2951
0
                        if(getSceneBlendFactor(*i0, &sbf0) && getSceneBlendFactor(*i1, &sbf1))
2952
0
                            mUnit->setColourOpMultipassFallback(sbf0, sbf1);
2953
0
                        else
2954
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2955
0
                                               "arguments must be valid scene blend factors");
2956
0
                    }
2957
0
                    break;
2958
0
                case ID_ALPHA_OP_EX:
2959
0
                    if(prop->values.size() < 3)
2960
0
                    {
2961
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line,
2962
0
                                           "alpha_op_ex must have at least 3 arguments");
2963
0
                    }
2964
0
                    else if(prop->values.size() > 6)
2965
0
                    {
2966
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
2967
0
                                           "alpha_op_ex must have at most 6 arguments");
2968
0
                    }
2969
0
                    else
2970
0
                    {
2971
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0),
2972
0
                            i1 = getNodeAt(prop->values, 1),
2973
0
                            i2 = getNodeAt(prop->values, 2);
2974
0
                        LayerBlendOperationEx op;
2975
0
                        LayerBlendSource source1, source2;
2976
0
                        if (getValue(*i0, op) && getValue(*i1, source1) && getValue(*i2, source2))
2977
0
                        {
2978
0
                            Real arg1 = 0.0f, arg2 = 0.0f;
2979
0
                            Real manualBlend = 0.0f;
2980
2981
0
                            if(op == LBX_BLEND_MANUAL)
2982
0
                            {
2983
0
                                AbstractNodeList::const_iterator i3 = getNodeAt(prop->values, 3);
2984
0
                                if(i3 != prop->values.end())
2985
0
                                {
2986
0
                                    if(!getReal(*i3, &manualBlend))
2987
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
2988
0
                                                           "valid number expected when blend_manual is used");
2989
0
                                }
2990
0
                                else
2991
0
                                {
2992
0
                                    compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
2993
0
                                                       "valid number expected when blend_manual is used");
2994
0
                                }
2995
0
                            }
2996
2997
0
                            AbstractNodeList::const_iterator j = getNodeAt(prop->values, 3);
2998
0
                            if(op == LBX_BLEND_MANUAL)
2999
0
                                ++j;
3000
0
                            if(source1 == LBS_MANUAL)
3001
0
                            {
3002
0
                                if(j != prop->values.end())
3003
0
                                {
3004
0
                                    if(!getReal(*j, &arg1))
3005
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3006
0
                                                           "valid colour expected when src_manual is used");
3007
0
                                    else
3008
0
                                        ++j;
3009
0
                                }
3010
0
                                else
3011
0
                                {
3012
0
                                    compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
3013
0
                                                       "valid colour expected when src_manual is used");
3014
0
                                }
3015
0
                            }
3016
0
                            if(source2 == LBS_MANUAL)
3017
0
                            {
3018
0
                                if(j != prop->values.end())
3019
0
                                {
3020
0
                                    if(!getReal(*j, &arg2))
3021
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3022
0
                                                           "valid colour expected when src_manual is used");
3023
0
                                }
3024
0
                                else
3025
0
                                {
3026
0
                                    compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
3027
0
                                                       "valid colour expected when src_manual is used");
3028
0
                                }
3029
0
                            }
3030
3031
0
                            mUnit->setAlphaOperation(op, source1, source2, arg1, arg2, manualBlend);
3032
0
                        }
3033
0
                        else
3034
0
                        {
3035
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
3036
0
                        }
3037
0
                    }
3038
0
                    break;
3039
0
                case ID_ENV_MAP:
3040
0
                    if(prop->values.empty())
3041
0
                    {
3042
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
3043
0
                    }
3044
0
                    else if(prop->values.size() > 1)
3045
0
                    {
3046
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
3047
0
                                           "env_map must have at most 1 argument");
3048
0
                    }
3049
0
                    else
3050
0
                    {
3051
0
                        if(prop->values.front()->type == ANT_ATOM)
3052
0
                        {
3053
0
                            AtomAbstractNode *atom = (AtomAbstractNode*)prop->values.front().get();
3054
0
                            switch(atom->id)
3055
0
                            {
3056
0
                            case ScriptCompiler::ID_OFF:
3057
0
                                mUnit->setEnvironmentMap(false);
3058
0
                                break;
3059
0
                            case ID_SPHERICAL:
3060
0
                                mUnit->setEnvironmentMap(true, TextureUnitState::ENV_CURVED);
3061
0
                                break;
3062
0
                            case ID_PLANAR:
3063
0
                                mUnit->setEnvironmentMap(true, TextureUnitState::ENV_PLANAR);
3064
0
                                break;
3065
0
                            case ID_CUBIC_REFLECTION:
3066
0
                                mUnit->setEnvironmentMap(true, TextureUnitState::ENV_REFLECTION);
3067
0
                                break;
3068
0
                            case ID_CUBIC_NORMAL:
3069
0
                                mUnit->setEnvironmentMap(true, TextureUnitState::ENV_NORMAL);
3070
0
                                break;
3071
0
                            default:
3072
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3073
0
                                                   prop->values.front()->getValue() + " is not a valid argument (must be \"off\", \"spherical\", \"planar\", \"cubic_reflection\", or \"cubic_normal\")");
3074
0
                            }
3075
0
                        }
3076
0
                        else
3077
0
                        {
3078
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3079
0
                                               prop->values.front()->getValue() + " is not a valid argument (must be \"off\", \"spherical\", \"planar\", \"cubic_reflection\", or \"cubic_normal\")");
3080
0
                        }
3081
0
                    }
3082
0
                    break;
3083
0
                case ID_SCROLL:
3084
0
                    if(prop->values.empty())
3085
0
                    {
3086
0
                        compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line);
3087
0
                    }
3088
0
                    else if(prop->values.size() > 2)
3089
0
                    {
3090
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
3091
0
                                           "scroll must have at most 2 arguments");
3092
0
                    }
3093
0
                    else
3094
0
                    {
3095
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1);
3096
0
                        Real x, y;
3097
0
                        if(getReal(*i0, &x) && getReal(*i1, &y))
3098
0
                            mUnit->setTextureScroll(x, y);
3099
0
                        else
3100
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3101
0
                                               (*i0)->getValue() + " and/or " + (*i1)->getValue() + " is invalid; both must be numbers");
3102
0
                    }
3103
0
                    break;
3104
0
                case ID_SCROLL_ANIM:
3105
0
                    if(prop->values.empty())
3106
0
                    {
3107
0
                        compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line);
3108
0
                    }
3109
0
                    else if(prop->values.size() > 2)
3110
0
                    {
3111
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
3112
0
                                           "scroll_anim must have at most 2 arguments");
3113
0
                    }
3114
0
                    else
3115
0
                    {
3116
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1);
3117
0
                        Real x, y;
3118
0
                        if(getReal(*i0, &x) && getReal(*i1, &y))
3119
0
                            mUnit->setScrollAnimation(x, y);
3120
0
                        else
3121
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3122
0
                                               (*i0)->getValue() + " and/or " + (*i1)->getValue() + " is invalid; both must be numbers");
3123
0
                    }
3124
0
                    break;
3125
0
                case ID_ROTATE:
3126
0
                    if(getValue(prop, compiler, fval))
3127
0
                        mUnit->setTextureRotate(Degree(fval));
3128
0
                    break;
3129
0
                case ID_ROTATE_ANIM:
3130
0
                    if(getValue(prop, compiler, fval))
3131
0
                        mUnit->setRotateAnimation(fval);
3132
0
                    break;
3133
0
                case ID_SCALE:
3134
0
                    if(prop->values.empty())
3135
0
                    {
3136
0
                        compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line);
3137
0
                    }
3138
0
                    else if(prop->values.size() > 2)
3139
0
                    {
3140
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
3141
0
                                           "scale must have at most 2 arguments");
3142
0
                    }
3143
0
                    else
3144
0
                    {
3145
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1);
3146
0
                        Real x, y;
3147
0
                        if(getReal(*i0, &x) && getReal(*i1, &y))
3148
0
                            mUnit->setTextureScale(x, y);
3149
0
                        else
3150
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3151
0
                                               "first and second arguments must both be valid number values (received " + (*i0)->getValue() + ", " + (*i1)->getValue() + ")");
3152
0
                    }
3153
0
                    break;
3154
0
                case ID_WAVE_XFORM:
3155
0
                    if(prop->values.empty())
3156
0
                    {
3157
0
                        compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line);
3158
0
                    }
3159
0
                    else if(prop->values.size() > 6)
3160
0
                    {
3161
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
3162
0
                                           "wave_xform must have at most 6 arguments");
3163
0
                    }
3164
0
                    else
3165
0
                    {
3166
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1),
3167
0
                            i2 = getNodeAt(prop->values, 2), i3 = getNodeAt(prop->values, 3),
3168
0
                            i4 = getNodeAt(prop->values, 4), i5 = getNodeAt(prop->values, 5);
3169
0
                        if((*i0)->type == ANT_ATOM && (*i1)->type == ANT_ATOM && (*i2)->type == ANT_ATOM &&
3170
0
                           (*i3)->type == ANT_ATOM && (*i4)->type == ANT_ATOM && (*i5)->type == ANT_ATOM)
3171
0
                        {
3172
0
                            AtomAbstractNode *atom0 = (AtomAbstractNode*)(*i0).get(), *atom1 = (AtomAbstractNode*)(*i1).get();
3173
0
                            TextureUnitState::TextureTransformType type = TextureUnitState::TT_ROTATE;
3174
0
                            WaveformType wave = WFT_SINE;
3175
0
                            Real base = 0.0f, freq = 0.0f, phase = 0.0f, amp = 0.0f;
3176
3177
0
                            switch(atom0->id)
3178
0
                            {
3179
0
                            case ID_SCROLL_X:
3180
0
                                type = TextureUnitState::TT_TRANSLATE_U;
3181
0
                                break;
3182
0
                            case ID_SCROLL_Y:
3183
0
                                type = TextureUnitState::TT_TRANSLATE_V;
3184
0
                                break;
3185
0
                            case ID_SCALE_X:
3186
0
                                type = TextureUnitState::TT_SCALE_U;
3187
0
                                break;
3188
0
                            case ID_SCALE_Y:
3189
0
                                type = TextureUnitState::TT_SCALE_V;
3190
0
                                break;
3191
0
                            case ID_ROTATE:
3192
0
                                type = TextureUnitState::TT_ROTATE;
3193
0
                                break;
3194
0
                            default:
3195
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3196
0
                                                   atom0->value + " is not a valid transform type (must be \"scroll_x\", \"scroll_y\", \"scale_x\", \"scale_y\", or \"rotate\")");
3197
0
                            }
3198
3199
0
                            switch(atom1->id)
3200
0
                            {
3201
0
                            case ID_SINE:
3202
0
                                wave = WFT_SINE;
3203
0
                                break;
3204
0
                            case ID_TRIANGLE:
3205
0
                                wave = WFT_TRIANGLE;
3206
0
                                break;
3207
0
                            case ID_SQUARE:
3208
0
                                wave = WFT_SQUARE;
3209
0
                                break;
3210
0
                            case ID_SAWTOOTH:
3211
0
                                wave = WFT_SAWTOOTH;
3212
0
                                break;
3213
0
                            case ID_INVERSE_SAWTOOTH:
3214
0
                                wave = WFT_INVERSE_SAWTOOTH;
3215
0
                                break;
3216
0
                            default:
3217
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3218
0
                                                   atom1->value + " is not a valid waveform type (must be \"sine\", \"triangle\", \"square\", \"sawtooth\", or \"inverse_sawtooth\")");
3219
0
                            }
3220
3221
0
                            if(!getReal(*i2, &base) || !getReal(*i3, &freq) || !getReal(*i4, &phase) || !getReal(*i5, &amp))
3222
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3223
0
                                                   "arguments 3, 4, 5, and 6 must be valid numbers; received " + (*i2)->getValue() + ", " + (*i3)->getValue() + ", " + (*i4)->getValue() + ", " + (*i5)->getValue());
3224
3225
0
                            mUnit->setTransformAnimation(type, wave, base, freq, phase, amp);
3226
0
                        }
3227
0
                        else
3228
0
                        {
3229
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
3230
0
                        }
3231
0
                    }
3232
0
                    break;
3233
0
                case ID_TRANSFORM:
3234
0
                    {
3235
0
                        Matrix4 m;
3236
0
                        if(getMatrix4(prop->values.begin(), prop->values.end(), &m))
3237
0
                            mUnit->setTextureTransform(m);
3238
0
                        else
3239
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
3240
0
                    }
3241
0
                    break;
3242
0
                case ID_CONTENT_TYPE:
3243
0
                    if(prop->values.empty())
3244
0
                    {
3245
0
                        compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line);
3246
0
                    }
3247
0
                    else if(prop->values.size() > 4)
3248
0
                    {
3249
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
3250
0
                                           "content_type must have at most 4 arguments");
3251
0
                    }
3252
0
                    else
3253
0
                    {
3254
0
                        if(prop->values.front()->type == ANT_ATOM)
3255
0
                        {
3256
0
                            AtomAbstractNode *atom = (AtomAbstractNode*)prop->values.front().get();
3257
0
                            switch(atom->id)
3258
0
                            {
3259
0
                            case ID_NAMED:
3260
0
                                mUnit->setContentType(TextureUnitState::CONTENT_NAMED);
3261
0
                                break;
3262
0
                            case ID_SHADOW:
3263
0
                                mUnit->setContentType(TextureUnitState::CONTENT_SHADOW);
3264
0
                                break;
3265
0
                            case ID_COMPOSITOR:
3266
0
                                mUnit->setContentType(TextureUnitState::CONTENT_COMPOSITOR);
3267
0
                                if (prop->values.size() >= 3)
3268
0
                                {
3269
0
                                    String compositorName;
3270
0
                                    getString(*getNodeAt(prop->values, 1), &compositorName);
3271
0
                                    String textureName;
3272
0
                                    getString(*getNodeAt(prop->values, 2), &textureName);
3273
3274
0
                                    if (prop->values.size() == 4)
3275
0
                                    {
3276
0
                                        uint32 mrtIndex;
3277
0
                                        getUInt(*getNodeAt(prop->values, 3), (uint32*)&mrtIndex);
3278
0
                                        mUnit->setCompositorReference(compositorName, textureName, mrtIndex);
3279
0
                                    }
3280
0
                                    else
3281
0
                                    {
3282
0
                                        mUnit->setCompositorReference(compositorName, textureName);
3283
0
                                    }
3284
0
                                }
3285
0
                                else
3286
0
                                {
3287
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3288
0
                                                       "content_type compositor must have an additional 2 or 3 parameters");
3289
0
                                }
3290
3291
0
                                break;
3292
0
                            default:
3293
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3294
0
                                                   atom->value + " is not a valid content type (must be \"named\" or \"shadow\" or \"compositor\")");
3295
0
                            }
3296
0
                        }
3297
0
                        else
3298
0
                        {
3299
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3300
0
                                               prop->values.front()->getValue() + " is not a valid content type");
3301
0
                        }
3302
0
                    }
3303
0
                    break;
3304
0
                default:
3305
0
                    compiler->addError(ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
3306
0
                                       "token \"" + prop->name + "\" is not recognized");
3307
0
                }
3308
0
            }
3309
0
            else if(i->type == ANT_OBJECT)
3310
0
            {
3311
0
                processNode(compiler, i);
3312
0
            }
3313
0
        }
3314
0
    }
3315
3316
    /**************************************************************************
3317
     * TextureSourceTranslator
3318
     **************************************************************************/
3319
    TextureSourceTranslator::TextureSourceTranslator()
3320
0
    {
3321
0
    }
3322
    //-------------------------------------------------------------------------
3323
    void TextureSourceTranslator::translate(Ogre::ScriptCompiler *compiler, const Ogre::AbstractNodePtr &node)
3324
0
    {
3325
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
3326
3327
        // It has to have one value identifying the texture source name
3328
0
        if(obj->values.empty())
3329
0
        {
3330
0
            compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, node->file, node->line,
3331
0
                               "texture_source requires a type value");
3332
0
            return;
3333
0
        }
3334
3335
        // Set the value of the source
3336
0
        ExternalTextureSourceManager::getSingleton().setCurrentPlugIn(obj->values.front()->getValue());
3337
3338
0
        if (!ExternalTextureSourceManager::getSingleton().getCurrentPlugIn())
3339
0
        {
3340
0
            compiler->addError(ScriptCompiler::CE_REFERENCETOANONEXISTINGOBJECT, node->file, node->line,
3341
0
                               obj->values.front()->getValue());
3342
0
            return;
3343
0
        }
3344
3345
        // Set up the technique, pass, and texunit levels
3346
0
        TextureUnitState *texunit = any_cast<TextureUnitState*>(obj->parent->context);
3347
0
        Pass *pass = texunit->getParent();
3348
0
        Technique *technique = pass->getParent();
3349
0
        Material *material = technique->getParent();
3350
3351
0
        unsigned short techniqueIndex = 0, passIndex = 0, texUnitIndex = 0;
3352
0
        for(unsigned short i = 0; i < material->getNumTechniques(); i++)
3353
0
        {
3354
0
            if(material->getTechnique(i) == technique)
3355
0
            {
3356
0
                techniqueIndex = i;
3357
0
                break;
3358
0
            }
3359
0
        }
3360
0
        for(unsigned short i = 0; i < technique->getNumPasses(); i++)
3361
0
        {
3362
0
            if(technique->getPass(i) == pass)
3363
0
            {
3364
0
                passIndex = i;
3365
0
                break;
3366
0
            }
3367
0
        }
3368
0
        for(unsigned short i = 0; i < pass->getNumTextureUnitStates(); i++)
3369
0
        {
3370
0
            if(pass->getTextureUnitState(i) == texunit)
3371
0
            {
3372
0
                texUnitIndex = i;
3373
0
                break;
3374
0
            }
3375
0
        }
3376
3377
0
        String tps;
3378
0
        tps = StringConverter::toString(techniqueIndex) + " "
3379
0
            + StringConverter::toString(passIndex) + " "
3380
0
            + StringConverter::toString(texUnitIndex);
3381
3382
0
        ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->setParameter( "set_T_P_S", tps );
3383
3384
0
        for(auto & i : obj->children)
3385
0
        {
3386
0
            if(i->type == ANT_PROPERTY)
3387
0
            {
3388
0
                auto prop = i->getProperty();
3389
                // Glob the property values all together
3390
0
                String str = StringConverter::toString(prop.values);
3391
0
                ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->setParameter(prop.name, str);
3392
0
            }
3393
0
            else if(i->type == ANT_OBJECT)
3394
0
            {
3395
0
                processNode(compiler, i);
3396
0
            }
3397
0
        }
3398
3399
0
        ExternalTextureSourceManager::getSingleton().getCurrentPlugIn()->createDefinedTexture(material->getName(), material->getGroup());
3400
0
    }
3401
3402
    /**************************************************************************
3403
     * GpuProgramTranslator
3404
     *************************************************************************/
3405
    GpuProgramTranslator::GpuProgramTranslator()
3406
0
    {
3407
0
    }
3408
    //-------------------------------------------------------------------------
3409
    void GpuProgramTranslator::translate(ScriptCompiler *compiler, const AbstractNodePtr &node)
3410
0
    {
3411
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
3412
3413
        // Must have a name
3414
0
        if(obj->name.empty())
3415
0
        {
3416
0
            compiler->addError(ScriptCompiler::CE_OBJECTNAMEEXPECTED, obj->file, obj->line,
3417
0
                               "gpu program object must have names");
3418
0
            return;
3419
0
        }
3420
3421
        // Must have a language type
3422
0
        if(obj->values.empty())
3423
0
        {
3424
0
            compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, obj->file, obj->line,
3425
0
                               "gpu program object require language declarations");
3426
0
            return;
3427
0
        }
3428
3429
        // Get the language
3430
0
        String language;
3431
0
        for(const auto& lnode : obj->values)
3432
0
        {
3433
0
            if(!getString(lnode, &language))
3434
0
            {
3435
0
                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, obj->file, obj->line);
3436
0
                return;
3437
0
            }
3438
3439
0
            if (language == "asm")
3440
0
            {
3441
0
                compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, obj->file, obj->line, "asm. Use syntax code.");
3442
0
                break; // always supported
3443
0
            }
3444
0
            if (GpuProgramManager::getSingleton().isLanguageSupported(language))
3445
0
                break;
3446
0
        }
3447
3448
0
        translateGpuProgram(compiler, obj, language);
3449
0
    }
3450
    //-------------------------------------------------------------------------
3451
    void GpuProgramTranslator::translateGpuProgram(ScriptCompiler *compiler, ObjectAbstractNode *obj, String language)
3452
0
    {
3453
0
        String syntax;
3454
0
        std::vector<String> delegates;
3455
0
        std::vector<std::pair<PropertyAbstractNode*, String> > customParameters;
3456
0
        String source, profiles, target;
3457
0
        AbstractNodePtr params;
3458
0
        for(auto & i : obj->children)
3459
0
        {
3460
0
            if(i->type == ANT_PROPERTY)
3461
0
            {
3462
0
                PropertyAbstractNode *prop = (PropertyAbstractNode*)i.get();
3463
0
                if(prop->id == ID_SOURCE)
3464
0
                {
3465
0
                    if(!getValue(prop, compiler, source))
3466
0
                        return;
3467
0
                }
3468
0
                else if(prop->name == "delegate")
3469
0
                {
3470
0
                    String value;
3471
0
                    if(!getValue(prop, compiler, value))
3472
0
                        return;
3473
3474
0
                    ProcessResourceNameScriptCompilerEvent evt(ProcessResourceNameScriptCompilerEvent::GPU_PROGRAM, value);
3475
0
                    compiler->_fireEvent(&evt, 0);
3476
0
                    delegates.push_back(evt.mName);
3477
0
                }
3478
0
                else
3479
0
                {
3480
0
                    StringVector values;
3481
0
                    _getVector(prop->values.begin(), prop->values.end(), values, prop->values.size());
3482
3483
0
                    if(prop->name == "attach")
3484
0
                    {
3485
0
                        compiler->addError(*prop, "attach. Use the #include directive instead",
3486
0
                                           ScriptCompiler::CE_DEPRECATEDSYMBOL);
3487
3488
0
                        for (auto& value : values)
3489
0
                        {
3490
0
                            ProcessResourceNameScriptCompilerEvent evt(ProcessResourceNameScriptCompilerEvent::GPU_PROGRAM, value);
3491
0
                            compiler->_fireEvent(&evt, 0);
3492
0
                            value = evt.mName;
3493
0
                        }
3494
0
                    }
3495
3496
0
                    String value = StringConverter::toString(values);
3497
3498
0
                    if(prop->name == "profiles")
3499
0
                        profiles = value;
3500
0
                    else if(prop->name == "target")
3501
0
                        target = value;
3502
0
                    else if(prop->id == ID_SYNTAX && language == "asm")
3503
0
                        syntax = value;
3504
0
                    else
3505
0
                        customParameters.push_back(std::make_pair(prop, value));
3506
0
                }
3507
0
            }
3508
0
            else if(i->type == ANT_OBJECT)
3509
0
            {
3510
0
                if(((ObjectAbstractNode*)i.get())->id == ID_DEFAULT_PARAMS)
3511
0
                    params = i;
3512
0
                else
3513
0
                    processNode(compiler, i);
3514
0
            }
3515
0
        }
3516
3517
        // Allocate the program
3518
0
        GpuProgramType gpt = getProgramType(obj->id);
3519
0
        GpuProgram *prog = 0;
3520
3521
0
        if(language == "asm")
3522
0
            language = syntax;
3523
0
        CreateGpuProgramScriptCompilerEvent evt(obj->file, obj->name, compiler->getResourceGroup(), source,
3524
0
                                                language, gpt);
3525
0
        bool processed = compiler->_fireEvent(&evt, &prog);
3526
3527
0
        if(!processed)
3528
0
        {
3529
0
            prog = GpuProgramManager::getSingleton().create(obj->name, compiler->getResourceGroup(), gpt, language).get();
3530
3531
0
            if (source.empty() && language != "unified")
3532
0
            {
3533
0
                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, obj->file, obj->line,
3534
0
                                   "No 'source' provided for GPU program");
3535
0
                return;
3536
0
            }
3537
3538
0
            if(prog && !source.empty()) // prog=0 if duplicate definition resolved by "use previous"
3539
0
                prog->setSourceFile(source);
3540
0
        }
3541
3542
0
        if(!prog)
3543
0
        {
3544
0
            compiler->addError(ScriptCompiler::CE_OBJECTALLOCATIONERROR, obj->file, obj->line, obj->name);
3545
0
            return;
3546
0
        }
3547
3548
0
        obj->context = prog;
3549
3550
0
        prog->setMorphAnimationIncluded(false);
3551
0
        prog->setPoseAnimationIncluded(0);
3552
0
        prog->setSkeletalAnimationIncluded(false);
3553
0
        prog->setVertexTextureFetchRequired(false);
3554
0
        prog->_notifyOrigin(obj->file);
3555
3556
        // special case for Cg
3557
0
        if(!profiles.empty())
3558
0
            prog->setParameter("profiles", profiles);
3559
3560
        // special case for HLSL
3561
0
        if(!target.empty())
3562
0
            prog->setParameter("target", target);
3563
3564
        // special case for unified
3565
0
        for(const auto& d : delegates)
3566
0
            prog->setParameter("delegate", d);
3567
3568
        // Set the custom parameters
3569
0
        for(const auto& p : customParameters)
3570
0
        {
3571
0
            if(prog->isSupported() && !prog->setParameter(p.first->name, p.second))
3572
0
            {
3573
0
                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, p.first->file, p.first->line, p.first->name);
3574
0
            }
3575
0
        }
3576
3577
        // Set up default parameters
3578
0
        if(prog->isSupported() && params)
3579
0
        {
3580
0
            GpuProgramParametersSharedPtr ptr = prog->getDefaultParameters();
3581
3582
0
            if(prog->hasCompileError())
3583
0
                return;
3584
3585
0
            GpuProgramTranslator::translateProgramParameters(compiler, ptr, static_cast<ObjectAbstractNode*>(params.get()));
3586
0
        }
3587
0
    }
3588
    //-------------------------------------------------------------------------
3589
    static int parseProgramParameterDimensions(String& declarator, BaseConstantType& type)
3590
0
    {
3591
        // Assume 1 unless otherwise specified
3592
0
        int dimensions = 1;
3593
0
        type = BCT_UNKNOWN;
3594
3595
        // get the type
3596
0
        const char* typeStrings[] = {"float", "int", "uint", "double", "bool"};
3597
0
        BaseConstantType baseTypes[] = {BCT_FLOAT, BCT_INT, BCT_UINT, BCT_DOUBLE, BCT_BOOL};
3598
3599
0
        const char* typeStr = "";
3600
3601
0
        for(int i = 0; i < 5; ++i)
3602
0
        {
3603
0
            if(declarator.find(typeStrings[i]) == 0)
3604
0
            {
3605
0
                type = baseTypes[i];
3606
0
                typeStr = typeStrings[i];
3607
0
                break;
3608
0
            }
3609
0
        }
3610
3611
0
        if(type == BCT_UNKNOWN)
3612
0
            return dimensions;
3613
3614
0
        size_t start = declarator.find_first_not_of(typeStr);
3615
3616
0
        if (start != String::npos)
3617
0
        {
3618
0
            size_t end = declarator.find_first_of('[', start);
3619
3620
            // int1, int2, etc.
3621
0
            if (end != start)
3622
0
            {
3623
0
                dimensions *= StringConverter::parseInt(
3624
0
                    declarator.substr(start, end - start));
3625
0
                start = end;
3626
0
            }
3627
3628
            // C-style array
3629
0
            while (start != String::npos)
3630
0
            {
3631
0
                end = declarator.find_first_of(']', start);
3632
0
                dimensions *= StringConverter::parseInt(
3633
0
                    declarator.substr(start + 1, end - start - 1));
3634
0
                start = declarator.find_first_of('[', end);
3635
0
            }
3636
0
        }
3637
0
        return dimensions;
3638
0
    }
3639
    //-------------------------------------------------------------------------
3640
    template <typename T, typename It>
3641
    static void safeSetConstant(const GpuProgramParametersPtr& params, const String& name, size_t index, It arrayStart,
3642
                                It arrayEnd, size_t count, PropertyAbstractNode* prop, ScriptCompiler* compiler)
3643
0
    {
3644
0
        int roundedCount = (count + 3) / 4; // integer ceil
3645
0
        roundedCount *= 4;
3646
3647
0
        std::vector<T> vals;
3648
0
        if (!_getVector(arrayStart, arrayEnd, vals, roundedCount))
3649
0
        {
3650
0
            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
3651
0
            return;
3652
0
        }
3653
3654
0
        try
3655
0
        {
3656
0
            if (!name.empty())
3657
0
                params->setNamedConstant(name, vals.data(), count, 1);
3658
0
            else
3659
0
                params->setConstant(index, vals.data(), roundedCount / 4);
3660
0
        }
3661
0
        catch (Exception& e)
3662
0
        {
3663
0
            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line, e.getDescription());
3664
0
        }
3665
0
    }
Unexecuted instantiation: OgreScriptTranslator.cpp:void Ogre::safeSetConstant<float, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*> >(Ogre::SharedPtr<Ogre::GpuProgramParameters> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, unsigned long, Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*)
Unexecuted instantiation: OgreScriptTranslator.cpp:void Ogre::safeSetConstant<unsigned int, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*> >(Ogre::SharedPtr<Ogre::GpuProgramParameters> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, unsigned long, Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*)
Unexecuted instantiation: OgreScriptTranslator.cpp:void Ogre::safeSetConstant<int, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*> >(Ogre::SharedPtr<Ogre::GpuProgramParameters> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, unsigned long, Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*)
Unexecuted instantiation: OgreScriptTranslator.cpp:void Ogre::safeSetConstant<double, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*> >(Ogre::SharedPtr<Ogre::GpuProgramParameters> const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, std::__1::__list_const_iterator<Ogre::SharedPtr<Ogre::AbstractNode>, void*>, unsigned long, Ogre::PropertyAbstractNode*, Ogre::ScriptCompiler*)
3666
3667
    void GpuProgramTranslator::translateProgramParameters(ScriptCompiler *compiler, const GpuProgramParametersSharedPtr& params, ObjectAbstractNode *obj)
3668
0
    {
3669
0
        uint32 animParametricsCount = 0;
3670
3671
0
        String value;
3672
0
        bool bval;
3673
0
        for(auto & i : obj->children)
3674
0
        {
3675
0
            if(i->type == ANT_PROPERTY)
3676
0
            {
3677
0
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
3678
0
                switch(prop->id)
3679
0
                {
3680
0
                case ID_USE_LINEAR_COLOURS:
3681
0
                    if(getValue(prop, compiler, bval))
3682
0
                    {
3683
0
                        params->setUseLinearColours(bval);
3684
0
                    }
3685
0
                    break;
3686
0
                case ID_SHARED_PARAMS_REF:
3687
0
                    if(getValue(prop, compiler, value))
3688
0
                    {
3689
0
                        try
3690
0
                        {
3691
0
                            params->addSharedParameters(value);
3692
0
                        }
3693
0
                        catch(Exception& e)
3694
0
                        {
3695
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3696
0
                                               e.getDescription());
3697
0
                        }
3698
0
                    }
3699
0
                    break;
3700
                //TODO Refactor this case.
3701
0
                case ID_PARAM_INDEXED:
3702
0
                case ID_PARAM_NAMED:
3703
0
                    {
3704
0
                        if(prop->values.size() >= 3)
3705
0
                        {
3706
0
                            bool named = (prop->id == ID_PARAM_NAMED);
3707
0
                            AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1),
3708
0
                                k = getNodeAt(prop->values, 2);
3709
3710
0
                            if((*i0)->type != ANT_ATOM || (*i1)->type != ANT_ATOM)
3711
0
                            {
3712
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3713
0
                                                   "name or index and parameter type expected");
3714
0
                                return;
3715
0
                            }
3716
3717
0
                            String name;
3718
0
                            uint32 index = 0;
3719
3720
0
                            AtomAbstractNode *atom0 = (AtomAbstractNode*)(*i0).get(), *atom1 = (AtomAbstractNode*)(*i1).get();
3721
3722
                            // Assign the name/index
3723
0
                            if(named)
3724
0
                                name = atom0->value;
3725
0
                            else if(!getValue(*i0, index))
3726
0
                            {
3727
0
                                compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
3728
0
                                                   atom0->value);
3729
0
                                return;
3730
0
                            }
3731
3732
                            // Determine the type
3733
0
                            if(atom1->value == "matrix4x4")
3734
0
                            {
3735
0
                                Matrix4 m;
3736
0
                                if(getMatrix4(k, prop->values.end(), &m))
3737
0
                                {
3738
0
                                    try
3739
0
                                    {
3740
0
                                        if(named)
3741
0
                                            params->setNamedConstant(name, m);
3742
0
                                        else
3743
0
                                            params->setConstant(index, m);
3744
0
                                    }
3745
0
                                    catch (Exception& e)
3746
0
                                    {
3747
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3748
0
                                                           e.getDescription());
3749
0
                                    }
3750
0
                                }
3751
0
                                else
3752
0
                                {
3753
0
                                    compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
3754
0
                                                       "incorrect matrix4x4 declaration");
3755
0
                                }
3756
0
                            }
3757
0
                            else
3758
0
                            {
3759
0
                                int count;
3760
0
                                BaseConstantType type;
3761
3762
                                // First, clear out any offending auto constants
3763
0
                                if (named)
3764
0
                                    params->clearNamedAutoConstant(name);
3765
0
                                else
3766
0
                                    params->clearAutoConstant(index);
3767
3768
0
                                count = parseProgramParameterDimensions(atom1->value, type);
3769
3770
0
                                if (type == BCT_FLOAT)
3771
0
                                {
3772
0
                                    safeSetConstant<float>(params, name, index, k, prop->values.cend(), count, prop, compiler);
3773
0
                                }
3774
0
                                else if (type == BCT_UINT)
3775
0
                                {
3776
0
                                    safeSetConstant<uint>(params, name, index, k, prop->values.cend(), count, prop, compiler);
3777
0
                                }
3778
0
                                else if (type == BCT_INT)
3779
0
                                {
3780
0
                                    safeSetConstant<int>(params, name, index, k, prop->values.cend(), count, prop, compiler);
3781
0
                                }
3782
0
                                else if (type == BCT_DOUBLE)
3783
0
                                {
3784
0
                                    safeSetConstant<double>(params, name, index, k, prop->values.cend(), count, prop, compiler);
3785
0
                                }
3786
0
                                else if (type == BCT_BOOL)
3787
0
                                {
3788
0
                                    std::vector<bool> tmp;
3789
0
                                    int roundedCount = (count + 3) / 4; // integer ceil
3790
0
                                    roundedCount *= 4;
3791
0
                                    if (_getVector(k, prop->values.end(), tmp, roundedCount))
3792
0
                                    {
3793
0
                                        std::vector<uint> vals(tmp.begin(), tmp.end());
3794
0
                                        try
3795
0
                                        {
3796
0
                                            if (named)
3797
0
                                                params->setNamedConstant(name, vals.data(), count, 1);
3798
0
                                            else
3799
0
                                                params->setConstant(index, vals.data(), roundedCount/4);
3800
0
                                        }
3801
0
                                        catch (Exception& e)
3802
0
                                        {
3803
0
                                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3804
0
                                                               e.getDescription());
3805
0
                                        }
3806
0
                                    }
3807
0
                                    else
3808
0
                                    {
3809
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3810
0
                                                           "incorrect boolean constant declaration");
3811
0
                                    }
3812
3813
0
                                    compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file, prop->line,
3814
0
                                                       "bool. Use uint instead");
3815
0
                                }
3816
0
                                else
3817
0
                                {
3818
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3819
0
                                                       "incorrect type specified; only variants of int, uint, float, double, and bool allowed");
3820
0
                                }
3821
0
                            }
3822
0
                        }
3823
0
                        else
3824
0
                        {
3825
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3826
0
                                               "param_named and param_indexed properties requires at least 3 arguments");
3827
0
                        }
3828
0
                    }
3829
0
                    break;
3830
0
                case ID_PARAM_INDEXED_AUTO:
3831
0
                case ID_PARAM_NAMED_AUTO:
3832
0
                    {
3833
0
                        bool named = (prop->id == ID_PARAM_NAMED_AUTO);
3834
0
                        String name;
3835
3836
0
                        if(prop->values.size() >= 2)
3837
0
                        {
3838
0
                            uint32 index = 0;
3839
0
                            AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0),
3840
0
                                i1 = getNodeAt(prop->values, 1), i2 = getNodeAt(prop->values, 2), i3 = getNodeAt(prop->values, 3);
3841
0
                            if((*i0)->type != ANT_ATOM || (*i1)->type != ANT_ATOM)
3842
0
                            {
3843
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3844
0
                                                   "name or index and auto constant type expected");
3845
0
                                return;
3846
0
                            }
3847
0
                            AtomAbstractNode *atom0 = (AtomAbstractNode*)(*i0).get(), *atom1 = (AtomAbstractNode*)(*i1).get();
3848
3849
0
                            if(named)
3850
0
                                name = atom0->value;
3851
0
                            else if(!getValue(*i0, index))
3852
0
                            {
3853
0
                                compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
3854
0
                                                   "parameter index expected");
3855
0
                                return;
3856
0
                            }
3857
3858
                            // Look up the auto constant
3859
0
                            StringUtil::toLowerCase(atom1->value);
3860
0
                            const GpuProgramParameters::AutoConstantDefinition *def =
3861
0
                                GpuProgramParameters::getAutoConstantDefinition(atom1->value);
3862
0
                            if(def)
3863
0
                            {
3864
0
                                switch(def->dataType)
3865
0
                                {
3866
0
                                case GpuProgramParameters::ACDT_NONE:
3867
0
                                    if (i2 != prop->values.end())
3868
0
                                    {
3869
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file,
3870
0
                                                           prop->line, "unexpected <extraInfo> parameter");
3871
0
                                    }
3872
3873
                                    // Set the auto constant
3874
0
                                    try
3875
0
                                    {
3876
0
                                        if(named)
3877
0
                                            params->setNamedAutoConstant(name, def->acType);
3878
0
                                        else
3879
0
                                            params->setAutoConstant(index, def->acType);
3880
0
                                    }
3881
0
                                    catch(Exception& e)
3882
0
                                    {
3883
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3884
0
                                                           e.getDescription());
3885
0
                                    }
3886
0
                                    break;
3887
0
                                case GpuProgramParameters::ACDT_INT:
3888
0
                                    if(def->acType == GpuProgramParameters::ACT_ANIMATION_PARAMETRIC)
3889
0
                                    {
3890
0
                                        try
3891
0
                                        {
3892
0
                                            if(named)
3893
0
                                                params->setNamedAutoConstant(name, def->acType, animParametricsCount++);
3894
0
                                            else
3895
0
                                                params->setAutoConstant(index, def->acType, animParametricsCount++);
3896
0
                                        }
3897
0
                                        catch(Exception& e)
3898
0
                                        {
3899
0
                                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3900
0
                                                               e.getDescription());
3901
0
                                        }
3902
0
                                    }
3903
0
                                    else
3904
0
                                    {
3905
                                        // Only certain texture projection auto params will assume 0
3906
                                        // Otherwise we will expect that 3rd parameter
3907
0
                                        if(i2 == prop->values.end())
3908
0
                                        {
3909
0
                                            if(def->acType == GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX ||
3910
0
                                               def->acType == GpuProgramParameters::ACT_TEXTURE_WORLDVIEWPROJ_MATRIX ||
3911
0
                                               def->acType == GpuProgramParameters::ACT_SPOTLIGHT_VIEWPROJ_MATRIX ||
3912
0
                                               def->acType == GpuProgramParameters::ACT_SPOTLIGHT_WORLDVIEWPROJ_MATRIX
3913
0
                                            )
3914
0
                                            {
3915
0
                                                try
3916
0
                                                {
3917
0
                                                    if(named)
3918
0
                                                        params->setNamedAutoConstant(name, def->acType, 0);
3919
0
                                                    else
3920
0
                                                        params->setAutoConstant(index, def->acType, 0);
3921
0
                                                }
3922
0
                                                catch (Exception& e)
3923
0
                                                {
3924
0
                                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3925
0
                                                                       e.getDescription());
3926
0
                                                }
3927
0
                                            }
3928
0
                                            else
3929
0
                                            {
3930
0
                                                compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
3931
0
                                                                   "<extraInfo> parameter required by constant definition " + atom1->value);
3932
0
                                            }
3933
0
                                        }
3934
0
                                        else
3935
0
                                        {
3936
0
                                            bool success = false;
3937
0
                                            uint32 extraInfo = 0;
3938
0
                                            if(i3 == prop->values.end())
3939
0
                                            { // Handle only one extra value
3940
0
                                                if(getUInt(*i2, &extraInfo))
3941
0
                                                {
3942
0
                                                    success = true;
3943
0
                                                }
3944
0
                                            }
3945
0
                                            else
3946
0
                                            { // Handle two extra values
3947
0
                                                uint32 extraInfo1 = 0, extraInfo2 = 0;
3948
0
                                                if(getUInt(*i2, &extraInfo1) && getUInt(*i3, &extraInfo2))
3949
0
                                                {
3950
0
                                                    extraInfo = extraInfo1 | (extraInfo2 << 16);
3951
0
                                                    success = true;
3952
0
                                                }
3953
0
                                            }
3954
3955
0
                                            if(success)
3956
0
                                            {
3957
0
                                                try
3958
0
                                                {
3959
0
                                                    if(named)
3960
0
                                                        params->setNamedAutoConstant(name, def->acType, extraInfo);
3961
0
                                                    else
3962
0
                                                        params->setAutoConstant(index, def->acType, extraInfo);
3963
0
                                                }
3964
0
                                                catch (Exception& e)
3965
0
                                                {
3966
0
                                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3967
0
                                                                       e.getDescription());
3968
0
                                                }
3969
0
                                            }
3970
0
                                            else
3971
0
                                            {
3972
0
                                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3973
0
                                                                   "invalid auto constant <extraInfo> parameter");
3974
0
                                            }
3975
0
                                        }
3976
0
                                    }
3977
0
                                    break;
3978
0
                                case GpuProgramParameters::ACDT_REAL:
3979
0
                                    if(def->acType == GpuProgramParameters::ACT_TIME ||
3980
0
                                       def->acType == GpuProgramParameters::ACT_FRAME_TIME)
3981
0
                                    {
3982
0
                                        Real f = 1.0f;
3983
0
                                        if(i2 != prop->values.end())
3984
0
                                            getReal(*i2, &f);
3985
3986
0
                                        try
3987
0
                                        {
3988
0
                                            if(named)
3989
0
                                                params->setNamedAutoConstantReal(name, def->acType, f);
3990
0
                                            else
3991
0
                                                params->setAutoConstantReal(index, def->acType, f);
3992
0
                                        }
3993
0
                                        catch (Exception& e)
3994
0
                                        {
3995
0
                                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
3996
0
                                                               e.getDescription());
3997
0
                                        }
3998
0
                                    }
3999
0
                                    else
4000
0
                                    {
4001
0
                                        if(i2 != prop->values.end())
4002
0
                                        {
4003
0
                                            Real extraInfo = 0.0f;
4004
0
                                            if(getReal(*i2, &extraInfo))
4005
0
                                            {
4006
0
                                                try
4007
0
                                                {
4008
0
                                                    if(named)
4009
0
                                                        params->setNamedAutoConstantReal(name, def->acType, extraInfo);
4010
0
                                                    else
4011
0
                                                        params->setAutoConstantReal(index, def->acType, extraInfo);
4012
0
                                                }
4013
0
                                                catch(Exception& e)
4014
0
                                                {
4015
0
                                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4016
0
                                                                       e.getDescription());
4017
0
                                                }
4018
0
                                            }
4019
0
                                            else
4020
0
                                            {
4021
0
                                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4022
0
                                                                   "incorrect float argument definition in <extraInfo> parameter");
4023
0
                                            }
4024
0
                                        }
4025
0
                                        else
4026
0
                                        {
4027
0
                                            compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
4028
0
                                                               "<extraInfo> parameter required by constant definition " + atom1->value);
4029
0
                                        }
4030
0
                                    }
4031
0
                                    break;
4032
0
                                }
4033
0
                            }
4034
0
                            else
4035
0
                            {
4036
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line, atom1->value);
4037
0
                            }
4038
0
                        }
4039
0
                        else
4040
0
                        {
4041
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4042
0
                        }
4043
0
                    }
4044
0
                    break;
4045
                // case ID_COMPUTE_WORKGROUP_DIMENSIONS:
4046
                //     if (obj->id != ID_COMPUTE_PROGRAM)
4047
                //         break;
4048
                //     if (prop->values.size() == 3)
4049
                //     {
4050
                //         AbstractNodeList::const_iterator first_dimension = getNodeAt(prop->values, 0);
4051
4052
                //         uint *vals = OGRE_ALLOC_T(uint, roundedCount, MEMCATEGORY_SCRIPTING);
4053
                //         if(getUInts(k, prop->values.end(), vals, 3))
4054
                //         {
4055
                //             try
4056
                //             {
4057
                //                 params->setNamedConstant(name, m);
4058
                //             }
4059
                //             catch(...)
4060
                //             {
4061
                //                 compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4062
                //                                    "setting workgroup_dimensions parameter failed");
4063
                //             }
4064
                //         }
4065
                //         else
4066
                //         {
4067
                //             compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
4068
                //                                "incorrect workgroup_dimensions declaration");
4069
                //         }
4070
                //     }
4071
                //     else
4072
                //     {
4073
                //         compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4074
                //                            "workgroup_dimensions property requires 3 arguments");
4075
                //     }
4076
4077
4078
                //     break;
4079
0
                default:
4080
0
                    compiler->addError(ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
4081
0
                                       "token \"" + prop->name + "\" is not recognized");
4082
0
                }
4083
0
            }
4084
0
        }
4085
0
    }
4086
    /**************************************************************************
4087
     * SharedParamsTranslator
4088
     *************************************************************************/
4089
    SharedParamsTranslator::SharedParamsTranslator()
4090
0
    {
4091
0
    }
4092
4093
    //-------------------------------------------------------------------------
4094
    void SharedParamsTranslator::translate(ScriptCompiler *compiler, const AbstractNodePtr &node)
4095
0
    {
4096
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
4097
4098
        // Must have a name
4099
0
        if (obj->name.empty())
4100
0
        {
4101
0
            compiler->addError(ScriptCompiler::CE_OBJECTNAMEEXPECTED, obj->file, obj->line);
4102
0
            return;
4103
0
        }
4104
4105
0
        GpuSharedParameters* sharedParams = 0;
4106
0
        CreateGpuSharedParametersScriptCompilerEvent evt(obj->file, obj->name, compiler->getResourceGroup());
4107
0
        bool processed = compiler->_fireEvent(&evt, (void*)&sharedParams);
4108
4109
0
        if (!processed)
4110
0
        {
4111
0
            sharedParams = GpuProgramManager::getSingleton().createSharedParameters(obj->name).get();
4112
0
        }
4113
4114
0
        if (!sharedParams)
4115
0
        {
4116
0
            compiler->addError(ScriptCompiler::CE_OBJECTALLOCATIONERROR, obj->file, obj->line, obj->name);
4117
0
            return;
4118
0
        }
4119
4120
0
        for (auto & i : obj->children)
4121
0
        {
4122
0
            if (i->type != ANT_PROPERTY)
4123
0
                continue;
4124
4125
0
            PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
4126
0
            if (prop->id != ID_SHARED_PARAM_NAMED && prop->id != ID_PARAM_NAMED)
4127
0
            {
4128
0
                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4129
0
                                   prop->name);
4130
0
                continue;
4131
0
            }
4132
4133
0
            if(prop->id == ID_SHARED_PARAM_NAMED)
4134
0
            {
4135
0
                compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file, prop->line,
4136
0
                                   "shared_param_named is deprecated. Use param_named instead");
4137
0
            }
4138
4139
0
            if (prop->values.size() < 2)
4140
0
            {
4141
0
                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4142
0
                                   prop->name + " - expected 2 or more arguments");
4143
0
                continue;
4144
0
            }
4145
4146
0
            AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1);
4147
4148
0
            String pName;
4149
0
            GpuConstantType constType;
4150
4151
0
            if (!getValue(*i0, pName) || !getConstantType(i1, &constType))
4152
0
            {
4153
0
                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4154
0
                                   "name and parameter type expected");
4155
0
                continue;
4156
0
            }
4157
4158
0
            AbstractNodeList::const_iterator arrayStart = getNodeAt(prop->values, 2), arrayEnd = prop->values.end();
4159
0
            uint32 arraySz = 1;
4160
4161
0
            if (arrayStart != arrayEnd)
4162
0
            {
4163
0
                String value;
4164
0
                getValue(*arrayStart, value);
4165
4166
0
                if (value.front() == '[' && value.back() == ']')
4167
0
                {
4168
0
                    arraySz = StringConverter::parseInt(value.substr(1, value.size() - 2), 0);
4169
0
                    if(!arraySz)
4170
0
                    {
4171
0
                        compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line,
4172
0
                                           "invalid array size");
4173
0
                        continue;
4174
0
                    }
4175
0
                    arrayStart++;
4176
0
                }
4177
0
            }
4178
4179
            // define constant entry
4180
0
            try
4181
0
            {
4182
0
                sharedParams->addConstantDefinition(pName, constType, arraySz);
4183
0
            }
4184
0
            catch(Exception& e)
4185
0
            {
4186
0
                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4187
0
                                   e.getDescription());
4188
0
                continue;
4189
0
            }
4190
4191
            // amount of individual numbers to read
4192
0
            arraySz *= GpuConstantDefinition::getElementSize(constType, false);
4193
4194
0
            switch (GpuConstantDefinition::getBaseType(constType))
4195
0
            {
4196
0
            case BCT_FLOAT:
4197
0
            {
4198
0
                std::vector<float> values;
4199
0
                if(_getVector(arrayStart, arrayEnd, values, arraySz))
4200
0
                    sharedParams->setNamedConstant(pName, &values[0], arraySz);
4201
0
                else
4202
0
                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4203
0
                break;
4204
0
            }
4205
0
            case BCT_INT:
4206
0
            {
4207
0
                std::vector<int> values;
4208
0
                if(_getVector(arrayStart, arrayEnd, values, arraySz))
4209
0
                    sharedParams->setNamedConstant(pName, &values[0], arraySz);
4210
0
                else
4211
0
                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4212
0
                break;
4213
0
            }
4214
0
            case BCT_DOUBLE:
4215
0
            {
4216
0
                std::vector<double> values;
4217
0
                if(_getVector(arrayStart, arrayEnd, values, arraySz))
4218
0
                    sharedParams->setNamedConstant(pName, &values[0], arraySz);
4219
0
                else
4220
0
                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4221
0
                break;
4222
0
            }
4223
0
            case BCT_UINT:
4224
0
            {
4225
0
                std::vector<uint> values;
4226
0
                if(_getVector(arrayStart, arrayEnd, values, arraySz))
4227
0
                {
4228
0
                    sharedParams->setNamedConstant(pName, &values[0], arraySz);
4229
0
                }
4230
0
                else
4231
0
                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4232
0
                break;
4233
0
            }
4234
0
            case BCT_BOOL:
4235
0
            {
4236
0
                compiler->addError(ScriptCompiler::CE_DEPRECATEDSYMBOL, prop->file, prop->line,
4237
0
                                   "bool. Use uint instead");
4238
0
                std::vector<bool> tmp;
4239
0
                if(_getVector(arrayStart, arrayEnd, tmp, arraySz))
4240
0
                {
4241
0
                    std::vector<uint> values(tmp.begin(), tmp.end());
4242
0
                    sharedParams->setNamedConstant(pName, &values[0], arraySz);
4243
0
                }
4244
0
                else
4245
0
                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4246
0
                break;
4247
0
            }
4248
0
            default:
4249
0
                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4250
0
                                   "invalid parameter type");
4251
0
                break;
4252
0
            }
4253
0
        }
4254
0
    }
4255
4256
    /**************************************************************************
4257
     * ParticleSystemTranslator
4258
     *************************************************************************/
4259
    ParticleSystemTranslator::ParticleSystemTranslator()
4260
0
        :mSystem(0)
4261
0
    {
4262
0
    }
4263
4264
    void ParticleSystemTranslator::translate(ScriptCompiler* compiler, const AbstractNodePtr &node)
4265
0
    {
4266
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
4267
        // Find the name
4268
0
        if(obj->name.empty())
4269
0
        {
4270
0
            compiler->addError(ScriptCompiler::CE_OBJECTNAMEEXPECTED, obj->file, obj->line);
4271
0
            return;
4272
0
        }
4273
4274
        // Allocate the particle system
4275
0
        CreateParticleSystemScriptCompilerEvent evt(obj->file, obj->name, compiler->getResourceGroup());
4276
0
        bool processed = compiler->_fireEvent(&evt, (void*)&mSystem);
4277
4278
0
        if(!processed)
4279
0
        {
4280
0
            mSystem = ParticleSystemManager::getSingleton().createTemplate(obj->name, compiler->getResourceGroup());
4281
0
        }
4282
4283
0
        if(!mSystem)
4284
0
        {
4285
0
            compiler->addError(ScriptCompiler::CE_OBJECTALLOCATIONERROR, obj->file, obj->line, obj->name);
4286
0
            return;
4287
0
        }
4288
4289
0
        mSystem->_notifyOrigin(obj->file);
4290
4291
0
        mSystem->removeAllEmitters();
4292
0
        mSystem->removeAllAffectors();
4293
4294
0
        obj->context = mSystem;
4295
4296
0
        for(auto & i : obj->children)
4297
0
        {
4298
0
            if(i->type == ANT_PROPERTY)
4299
0
            {
4300
0
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
4301
0
                if(prop->values.empty())
4302
0
                {
4303
0
                    compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
4304
0
                    return;
4305
0
                }
4306
4307
0
                String value;
4308
0
                if(prop->id == ID_MATERIAL)
4309
0
                {
4310
0
                    if(prop->values.front()->type == ANT_ATOM)
4311
0
                    {
4312
0
                        value = ((AtomAbstractNode*)prop->values.front().get())->value;
4313
4314
0
                        ProcessResourceNameScriptCompilerEvent locEvt(ProcessResourceNameScriptCompilerEvent::MATERIAL, value);
4315
0
                        compiler->_fireEvent(&locEvt, 0);
4316
0
                        value = locEvt.mName;
4317
0
                    }
4318
0
                }
4319
0
                else
4320
0
                {
4321
                    // Glob the values together
4322
0
                    for(auto& v : prop->values)
4323
0
                    {
4324
0
                        if(v->type == ANT_ATOM)
4325
0
                        {
4326
0
                            if(value.empty())
4327
0
                                value = ((AtomAbstractNode*)v.get())->value;
4328
0
                            else
4329
0
                                value = value + " " + ((AtomAbstractNode*)v.get())->value;
4330
0
                        }
4331
0
                        else
4332
0
                        {
4333
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4334
0
                            return;
4335
0
                        }
4336
0
                    }
4337
0
                }
4338
4339
0
                if(!mSystem->setParameter(prop->name, value))
4340
0
                {
4341
0
                    if(auto renderer = mSystem->getRenderer())
4342
0
                    {
4343
0
                        if(!renderer->setParameter(prop->name, value))
4344
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4345
0
                    }
4346
0
                }
4347
0
            }
4348
0
            else
4349
0
            {
4350
0
                processNode(compiler, i);
4351
0
            }
4352
0
        }
4353
0
    }
4354
4355
    /**************************************************************************
4356
     * ParticleEmitterTranslator
4357
     *************************************************************************/
4358
    ParticleEmitterTranslator::ParticleEmitterTranslator()
4359
0
        :mEmitter(0)
4360
0
    {
4361
0
    }
4362
    //-------------------------------------------------------------------------
4363
    void ParticleEmitterTranslator::translate(ScriptCompiler *compiler, const AbstractNodePtr &node)
4364
0
    {
4365
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
4366
4367
        // Must have a type as the first value
4368
0
        if(obj->values.empty())
4369
0
        {
4370
0
            compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, obj->file, obj->line);
4371
0
            return;
4372
0
        }
4373
4374
0
        ParticleSystem *system = any_cast<ParticleSystem*>(obj->parent->context);
4375
4376
0
        try
4377
0
        {
4378
0
            mEmitter = system->addEmitter(obj->values.front()->getString());
4379
0
        }
4380
0
        catch(Exception &e)
4381
0
        {
4382
0
            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, obj->file, obj->line, e.getDescription());
4383
0
            return;
4384
0
        }
4385
4386
0
        for(auto & i : obj->children)
4387
0
        {
4388
0
            if(i->type == ANT_PROPERTY)
4389
0
            {
4390
0
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
4391
0
                String value;
4392
4393
                // Glob the values together
4394
0
                for(const auto& v : prop->values)
4395
0
                {
4396
0
                    if(v->type == ANT_ATOM)
4397
0
                    {
4398
0
                        if(value.empty())
4399
0
                            value = ((AtomAbstractNode*)v.get())->value;
4400
0
                        else
4401
0
                            value = value + " " + ((AtomAbstractNode*)v.get())->value;
4402
0
                    }
4403
0
                    else
4404
0
                    {
4405
0
                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4406
0
                        break;
4407
0
                    }
4408
0
                }
4409
4410
0
                if(!mEmitter->setParameter(prop->name, value))
4411
0
                {
4412
0
                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4413
0
                }
4414
0
            }
4415
0
            else
4416
0
            {
4417
0
                processNode(compiler, i);
4418
0
            }
4419
0
        }
4420
0
    }
4421
4422
    /**************************************************************************
4423
     * ParticleAffectorTranslator
4424
     *************************************************************************/
4425
    ParticleAffectorTranslator::ParticleAffectorTranslator()
4426
0
        :mAffector(0)
4427
0
    {
4428
0
    }
4429
    //-------------------------------------------------------------------------
4430
    void ParticleAffectorTranslator::translate(ScriptCompiler *compiler, const AbstractNodePtr &node)
4431
0
    {
4432
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
4433
4434
        // Must have a type as the first value
4435
0
        if(obj->values.empty())
4436
0
        {
4437
0
            compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, obj->file, obj->line);
4438
0
            return;
4439
0
        }
4440
4441
0
        ParticleSystem *system = any_cast<ParticleSystem*>(obj->parent->context);
4442
0
        try
4443
0
        {
4444
0
            mAffector = system->addAffector(obj->values.front()->getString());
4445
0
        }
4446
0
        catch(Exception &e)
4447
0
        {
4448
0
            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, obj->file, obj->line, e.getDescription());
4449
0
            return;
4450
0
        }
4451
4452
0
        for(auto & i : obj->children)
4453
0
        {
4454
0
            if(i->type == ANT_PROPERTY)
4455
0
            {
4456
0
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
4457
0
                String value;
4458
4459
                // Glob the values together
4460
0
                for (const auto& v : prop->values)
4461
0
                {
4462
0
                    if(v->type == ANT_ATOM)
4463
0
                    {
4464
0
                        if(value.empty())
4465
0
                            value = ((AtomAbstractNode*)v.get())->value;
4466
0
                        else
4467
0
                            value = value + " " + ((AtomAbstractNode*)v.get())->value;
4468
0
                    }
4469
0
                    else
4470
0
                    {
4471
0
                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4472
0
                        break;
4473
0
                    }
4474
0
                }
4475
4476
0
                if(!mAffector->setParameter(prop->name, value))
4477
0
                {
4478
0
                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4479
0
                }
4480
0
            }
4481
0
            else
4482
0
            {
4483
0
                processNode(compiler, i);
4484
0
            }
4485
0
        }
4486
0
    }
4487
4488
    /**************************************************************************
4489
     * CompositorTranslator
4490
     *************************************************************************/
4491
    CompositorTranslator::CompositorTranslator()
4492
0
        :mCompositor(0)
4493
0
    {
4494
0
    }
4495
4496
    void CompositorTranslator::translate(ScriptCompiler *compiler, const AbstractNodePtr &node)
4497
0
    {
4498
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
4499
0
        if(obj->name.empty())
4500
0
        {
4501
0
            compiler->addError(ScriptCompiler::CE_OBJECTNAMEEXPECTED, obj->file, obj->line);
4502
0
            return;
4503
0
        }
4504
4505
        // Create the compositor
4506
0
        CreateCompositorScriptCompilerEvent evt(obj->file, obj->name, compiler->getResourceGroup());
4507
0
        bool processed = compiler->_fireEvent(&evt, (void*)&mCompositor);
4508
4509
0
        if(!processed)
4510
0
        {
4511
0
            mCompositor = CompositorManager::getSingleton().create(obj->name, compiler->getResourceGroup()).get();
4512
0
        }
4513
4514
0
        if(!mCompositor)
4515
0
        {
4516
0
            compiler->addError(ScriptCompiler::CE_OBJECTALLOCATIONERROR, obj->file, obj->line, obj->name);
4517
0
            return;
4518
0
        }
4519
4520
        // Prepare the compositor
4521
0
        mCompositor->removeAllTechniques();
4522
0
        mCompositor->_notifyOrigin(obj->file);
4523
0
        obj->context = mCompositor;
4524
4525
0
        for(auto & i : obj->children)
4526
0
        {
4527
0
            if(i->type == ANT_OBJECT)
4528
0
            {
4529
0
                processNode(compiler, i);
4530
0
            }
4531
0
            else
4532
0
            {
4533
0
                compiler->addError(ScriptCompiler::CE_UNEXPECTEDTOKEN, i->file, i->line,
4534
0
                                   "token not recognized");
4535
0
            }
4536
0
        }
4537
0
    }
4538
4539
    /**************************************************************************
4540
     * CompositionTechniqueTranslator
4541
     *************************************************************************/
4542
    CompositionTechniqueTranslator::CompositionTechniqueTranslator()
4543
0
        :mTechnique(0)
4544
0
    {
4545
0
    }
4546
    //-------------------------------------------------------------------------
4547
    void CompositionTechniqueTranslator::translate(ScriptCompiler *compiler, const AbstractNodePtr &node)
4548
0
    {
4549
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
4550
4551
0
        Compositor *compositor = any_cast<Compositor*>(obj->parent->context);
4552
0
        mTechnique = compositor->createTechnique();
4553
0
        obj->context = mTechnique;
4554
4555
0
        String sval;
4556
0
        uint32 uival;
4557
4558
0
        for(auto & i : obj->children)
4559
0
        {
4560
0
            if(i->type == ANT_OBJECT)
4561
0
            {
4562
0
                processNode(compiler, i);
4563
0
            }
4564
0
            else if(i->type == ANT_PROPERTY)
4565
0
            {
4566
0
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
4567
0
                switch(prop->id)
4568
0
                {
4569
0
                case ID_TEXTURE:
4570
0
                    {
4571
0
                        size_t atomIndex = 1;
4572
4573
0
                        AbstractNodeList::const_iterator it = getNodeAt(prop->values, 0);
4574
4575
0
                        if((*it)->type != ANT_ATOM)
4576
0
                        {
4577
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4578
0
                            return;
4579
0
                        }
4580
                        // Save the first atom, should be name
4581
0
                        AtomAbstractNode *atom0 = (AtomAbstractNode*)(*it).get();
4582
4583
0
                        uint32 width = 0, height = 0;
4584
0
                        uint32 depth = 1;
4585
0
                        float widthFactor = 1.0f, heightFactor = 1.0f;
4586
0
                        bool widthSet = false, heightSet = false, formatSet = false;
4587
0
                        bool pooled = false;
4588
0
                        bool hwGammaWrite = false;
4589
0
                        uint32 fsaa = 1;
4590
0
                        auto type = TEX_TYPE_2D;
4591
0
                        uint16 depthBufferId = RBP_DEFAULT;
4592
0
                        CompositionTechnique::TextureScope scope = CompositionTechnique::TS_LOCAL;
4593
0
                        Ogre::PixelFormatList formats;
4594
4595
0
                        while (atomIndex < prop->values.size())
4596
0
                        {
4597
0
                            it = getNodeAt(prop->values, static_cast<int>(atomIndex++));
4598
0
                            if((*it)->type != ANT_ATOM)
4599
0
                            {
4600
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4601
0
                                return;
4602
0
                            }
4603
0
                            AtomAbstractNode *atom = (AtomAbstractNode*)(*it).get();
4604
4605
0
                            switch(atom->id)
4606
0
                            {
4607
0
                            case ID_TARGET_WIDTH:
4608
0
                                width = 0;
4609
0
                                widthSet = true;
4610
0
                                break;
4611
0
                            case ID_TARGET_HEIGHT:
4612
0
                                height = 0;
4613
0
                                heightSet = true;
4614
0
                                break;
4615
0
                            case ID_TARGET_WIDTH_SCALED:
4616
0
                            case ID_TARGET_HEIGHT_SCALED:
4617
0
                                {
4618
0
                                    bool *pSetFlag;
4619
0
                                    uint32 *pSize;
4620
0
                                    float *pFactor;
4621
4622
0
                                    if (atom->id == ID_TARGET_WIDTH_SCALED)
4623
0
                                    {
4624
0
                                        pSetFlag = &widthSet;
4625
0
                                        pSize = &width;
4626
0
                                        pFactor = &widthFactor;
4627
0
                                    }
4628
0
                                    else
4629
0
                                    {
4630
0
                                        pSetFlag = &heightSet;
4631
0
                                        pSize = &height;
4632
0
                                        pFactor = &heightFactor;
4633
0
                                    }
4634
                                    // advance to next to get scaling
4635
0
                                    it = getNodeAt(prop->values, static_cast<int>(atomIndex++));
4636
0
                                    if(prop->values.end() == it || !getValue(*it, *pFactor))
4637
0
                                    {
4638
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4639
0
                                        return;
4640
0
                                    }
4641
4642
0
                                    *pSize = 0;
4643
0
                                    *pSetFlag = true;
4644
0
                                }
4645
0
                                break;
4646
0
                            case ID_POOLED:
4647
0
                                pooled = true;
4648
0
                                break;
4649
0
                            case ID_CUBIC:
4650
0
                                type = TEX_TYPE_CUBE_MAP;
4651
0
                                break;
4652
0
                            case ID_2DARRAY:
4653
0
                                type = TEX_TYPE_2D_ARRAY;
4654
0
                                break;
4655
0
                            case ID_2DMS:
4656
0
                                type = TEX_TYPE_2D_MULTISAMPLE;
4657
0
                                break;
4658
0
                            case ID_SCOPE_LOCAL:
4659
0
                                scope = CompositionTechnique::TS_LOCAL;
4660
0
                                break;
4661
0
                            case ID_SCOPE_CHAIN:
4662
0
                                scope = CompositionTechnique::TS_CHAIN;
4663
0
                                break;
4664
0
                            case ID_SCOPE_GLOBAL:
4665
0
                                scope = CompositionTechnique::TS_GLOBAL;
4666
0
                                break;
4667
0
                            case ID_GAMMA:
4668
0
                                hwGammaWrite = true;
4669
0
                                break;
4670
0
                            case ID_NO_FSAA:
4671
0
                                fsaa = 0;
4672
0
                                break;
4673
0
                            case ID_FSAA:
4674
                                // advance to next to get the value
4675
0
                                it = getNodeAt(prop->values, atomIndex++);
4676
0
                                if(prop->values.end() == it || !getValue(*it, fsaa))
4677
0
                                {
4678
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4679
0
                                    return;
4680
0
                                }
4681
0
                                break;
4682
0
                            case ID_DEPTH_POOL:
4683
0
                                {
4684
                                    // advance to next to get the ID
4685
0
                                    it = getNodeAt(prop->values, static_cast<int>(atomIndex++));
4686
0
                                    if(prop->values.end() == it || !getValue(*it, uival))
4687
0
                                    {
4688
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4689
0
                                        return;
4690
0
                                    }
4691
0
                                    depthBufferId = Math::uint16Cast(uival);
4692
0
                                }
4693
0
                                break;
4694
0
                            default:
4695
0
                                if (StringConverter::parse(atom->value, uival))
4696
0
                                {
4697
0
                                    if (atomIndex == 2)
4698
0
                                    {
4699
0
                                        width = uival;
4700
0
                                        widthSet = true;
4701
0
                                    }
4702
0
                                    else if (atomIndex == 3)
4703
0
                                    {
4704
0
                                        height = uival;
4705
0
                                        heightSet = true;
4706
0
                                    }
4707
0
                                    else if (atomIndex == 4)
4708
0
                                    {
4709
0
                                        depth = uival;
4710
0
                                    }
4711
0
                                    else
4712
0
                                    {
4713
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
4714
0
                                        return;
4715
0
                                    }
4716
0
                                }
4717
0
                                else
4718
0
                                {
4719
                                    // pixel format?
4720
0
                                    PixelFormat format = PixelUtil::getFormatFromName(atom->value, true);
4721
0
                                    if (format == PF_UNKNOWN)
4722
0
                                    {
4723
0
                                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line, atom->value);
4724
0
                                        return;
4725
0
                                    }
4726
0
                                    formats.push_back(format);
4727
0
                                    formatSet = true;
4728
0
                                }
4729
4730
0
                            }
4731
0
                        }
4732
0
                        if (!widthSet || !heightSet || !formatSet)
4733
0
                        {
4734
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4735
0
                                               "texture definition must specify width, height, and format");
4736
0
                            return;
4737
0
                        }
4738
4739
0
                        if(depth != 1 && type != TEX_TYPE_2D_ARRAY)
4740
0
                        {
4741
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4742
0
                                               "depth only supported for 2d_array textures");
4743
0
                            return;
4744
0
                        }
4745
4746
                        // No errors, create
4747
0
                        try {
4748
0
                            CompositionTechnique::TextureDefinition *def = mTechnique->createTextureDefinition(atom0->value);
4749
0
                            def->width = width;
4750
0
                            def->height = height;
4751
0
                            def->depth = depth;
4752
0
                            def->type = type;
4753
0
                            def->widthFactor = widthFactor;
4754
0
                            def->heightFactor = heightFactor;
4755
0
                            def->formatList = formats;
4756
0
                            def->fsaa = fsaa;
4757
0
                            def->hwGammaWrite = hwGammaWrite;
4758
0
                            def->depthBufferId = depthBufferId;
4759
0
                            def->pooled = pooled;
4760
0
                            def->scope = scope;
4761
0
                        }
4762
0
                        catch (Exception &e)
4763
0
                        {
4764
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line, e.getDescription());
4765
0
                        }
4766
0
                    }
4767
0
                    break;
4768
0
                case ID_TEXTURE_REF:
4769
0
                    if(prop->values.empty())
4770
0
                    {
4771
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
4772
0
                    }
4773
0
                    else if(prop->values.size() != 3)
4774
0
                    {
4775
0
                        compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4776
0
                                           "texture_ref only supports 3 argument");
4777
0
                    }
4778
0
                    else
4779
0
                    {
4780
0
                        String texName, refCompName, refTexName;
4781
4782
0
                        AbstractNodeList::const_iterator it = getNodeAt(prop->values, 0);
4783
0
                        if(!getString(*it, &texName))
4784
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4785
0
                                               "texture_ref must have 3 string arguments");
4786
4787
0
                        it = getNodeAt(prop->values, 1);
4788
0
                        if(!getString(*it, &refCompName))
4789
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4790
0
                                               "texture_ref must have 3 string arguments");
4791
4792
0
                        it = getNodeAt(prop->values, 2);
4793
0
                        if(!getString(*it, &refTexName))
4794
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
4795
0
                                               "texture_ref must have 3 string arguments");
4796
4797
0
                        CompositionTechnique::TextureDefinition* refTexDef =
4798
0
                            mTechnique->createTextureDefinition(texName);
4799
4800
0
                        refTexDef->refCompName = refCompName;
4801
0
                        refTexDef->refTexName = refTexName;
4802
0
                    }
4803
0
                    break;
4804
0
                case ID_SCHEME:
4805
0
                    if(getValue(prop, compiler, sval))
4806
0
                        mTechnique->setSchemeName(sval);
4807
0
                    break;
4808
0
                case ID_COMPOSITOR_LOGIC:
4809
0
                    if(getValue(prop, compiler, sval))
4810
0
                        mTechnique->setCompositorLogicName(sval);
4811
0
                    break;
4812
0
                default:
4813
0
                    compiler->addError(ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
4814
0
                                       "token \"" + prop->name + "\" is not recognized");
4815
0
                }
4816
0
            }
4817
0
        }
4818
0
    }
4819
4820
    /**************************************************************************
4821
     * CompositionTargetPass
4822
     *************************************************************************/
4823
    CompositionTargetPassTranslator::CompositionTargetPassTranslator()
4824
0
        :mTarget(0)
4825
0
    {
4826
0
    }
4827
    //-------------------------------------------------------------------------
4828
    void CompositionTargetPassTranslator::translate(ScriptCompiler *compiler, const AbstractNodePtr &node)
4829
0
    {
4830
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
4831
4832
0
        CompositionTechnique *technique = any_cast<CompositionTechnique*>(obj->parent->context);
4833
0
        if(obj->id == ID_TARGET)
4834
0
        {
4835
0
            mTarget = technique->createTargetPass();
4836
0
            if(obj->name.empty())
4837
0
            {
4838
0
                compiler->addError(ScriptCompiler::CE_OBJECTNAMEEXPECTED, obj->file, obj->line);
4839
0
                return;
4840
0
            }
4841
0
            mTarget->setOutputName(obj->name);
4842
4843
0
            if(!obj->values.empty())
4844
0
            {
4845
0
                int val;
4846
0
                if(getInt(obj->values.front(), &val))
4847
0
                    mTarget->setOutputSlice(val);
4848
0
            }
4849
0
        }
4850
0
        else if(obj->id == ID_TARGET_OUTPUT)
4851
0
        {
4852
0
            mTarget = technique->getOutputTargetPass();
4853
0
            if (!mTarget->getPasses().empty() || mTarget->getInputMode() != CompositionTargetPass::IM_NONE)
4854
0
            {
4855
0
                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, obj->file, obj->line,
4856
0
                                   "target_output can only be used once per technique");
4857
0
            }
4858
0
        }
4859
0
        obj->context = mTarget;
4860
4861
0
        bool bval;
4862
0
        Real fval;
4863
0
        uint32 uival;
4864
0
        String sval;
4865
4866
0
        for(auto & i : obj->children)
4867
0
        {
4868
0
            if(i->type == ANT_OBJECT)
4869
0
            {
4870
0
                processNode(compiler, i);
4871
0
            }
4872
0
            else if(i->type == ANT_PROPERTY)
4873
0
            {
4874
0
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
4875
0
                switch(prop->id)
4876
0
                {
4877
0
                case ID_INPUT:
4878
0
                    CompositionTargetPass::InputMode im;
4879
0
                    if(getValue(prop, compiler, im))
4880
0
                        mTarget->setInputMode(im);
4881
0
                    break;
4882
0
                case ID_ONLY_INITIAL:
4883
0
                    if(getValue(prop, compiler, bval))
4884
0
                        mTarget->setOnlyInitial(bval);
4885
0
                    break;
4886
0
                case ID_VISIBILITY_MASK:
4887
0
                    if(getValue(prop, compiler, uival))
4888
0
                        mTarget->setVisibilityMask(uival);
4889
0
                    break;
4890
0
                case ID_LOD_BIAS:
4891
0
                    if(getValue(prop, compiler, fval))
4892
0
                        mTarget->setLodBias(fval);
4893
0
                    break;
4894
0
                case ID_MATERIAL_SCHEME:
4895
0
                    if(getValue(prop, compiler, sval))
4896
0
                        mTarget->setMaterialScheme(sval);
4897
0
                    break;
4898
0
                case ID_SHADOWS_ENABLED:
4899
0
                    if(getValue(prop, compiler, bval))
4900
0
                        mTarget->setShadowsEnabled(bval);
4901
0
                    break;
4902
0
                default:
4903
0
                    compiler->addError(ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
4904
0
                                       "token \"" + prop->name + "\" is not recognized");
4905
0
                }
4906
0
            }
4907
0
        }
4908
0
    }
4909
4910
    /**************************************************************************
4911
     * CompositionPassTranslator
4912
     *************************************************************************/
4913
    CompositionPassTranslator::CompositionPassTranslator()
4914
0
        :mPass(0)
4915
0
    {
4916
0
    }
4917
4918
    void CompositionPassTranslator::translate(ScriptCompiler *compiler, const AbstractNodePtr &node)
4919
0
    {
4920
0
        ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
4921
4922
        // The name is the type of the pass
4923
0
        if(obj->values.empty() || obj->values.front()->type != ANT_ATOM)
4924
0
        {
4925
0
            compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, obj->file, obj->line, "pass type missing");
4926
0
            return;
4927
0
        }
4928
4929
0
        AtomAbstractNode* atom = static_cast<AtomAbstractNode*>(obj->values.front().get());
4930
4931
0
        CompositionPass::PassType ptype;
4932
0
        switch(atom->id)
4933
0
        {
4934
0
            case ID_CLEAR:
4935
0
                ptype = CompositionPass::PT_CLEAR;
4936
0
                break;
4937
0
            case ID_STENCIL:
4938
0
                ptype = CompositionPass::PT_STENCIL;
4939
0
                break;
4940
0
            case ID_RENDER_QUAD:
4941
0
                ptype = CompositionPass::PT_RENDERQUAD;
4942
0
                break;
4943
0
            case ID_RENDER_SCENE:
4944
0
                ptype = CompositionPass::PT_RENDERSCENE;
4945
0
                break;
4946
0
            case ID_COMPUTE:
4947
0
                ptype = CompositionPass::PT_COMPUTE;
4948
0
                break;
4949
0
            case ID_RENDER_CUSTOM:
4950
0
                ptype = CompositionPass::PT_RENDERCUSTOM;
4951
0
                break;
4952
0
            default:
4953
0
                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, obj->file, obj->line, atom->value);
4954
0
                return;
4955
0
        }
4956
4957
0
        CompositionTargetPass *target = any_cast<CompositionTargetPass*>(obj->parent->context);
4958
0
        mPass = target->createPass(ptype);
4959
0
        obj->context = mPass;
4960
4961
0
        if(mPass->getType() == CompositionPass::PT_RENDERCUSTOM)
4962
0
        {
4963
0
            String customType;
4964
            //This is the ugly one liner for safe access to the second parameter.
4965
0
            if (obj->values.size() < 2 || !getString(*(++(obj->values.begin())), &customType))
4966
0
            {
4967
0
                compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, obj->file, obj->line);
4968
0
                return;
4969
0
            }
4970
0
            mPass->setCustomType(customType);
4971
0
        }
4972
4973
0
        Real fval;
4974
0
        bool bval;
4975
0
        uint32 uival;
4976
0
        String sval;
4977
0
        StencilOperation sop;
4978
4979
0
        for(auto & i : obj->children)
4980
0
        {
4981
0
            if(i->type == ANT_OBJECT)
4982
0
            {
4983
0
                processNode(compiler, i);
4984
0
            }
4985
0
            else if(i->type == ANT_PROPERTY)
4986
0
            {
4987
0
                PropertyAbstractNode *prop = static_cast<PropertyAbstractNode*>(i.get());
4988
0
                switch(prop->id)
4989
0
                {
4990
0
                case ID_CHECK:
4991
0
                    if(getValue(prop, compiler, bval))
4992
0
                        mPass->setStencilCheck(bval);
4993
0
                    break;
4994
0
                case ID_COMP_FUNC:
4995
0
                    CompareFunction func;
4996
0
                    if(getValue(prop, compiler, func))
4997
0
                        mPass->setStencilFunc(func);
4998
0
                    break;
4999
0
                case ID_REF_VALUE:
5000
0
                    if(getValue(prop, compiler, uival))
5001
0
                        mPass->setStencilRefValue(uival);
5002
0
                    break;
5003
0
                case ID_MASK:
5004
0
                    if(getValue(prop, compiler, uival))
5005
0
                        mPass->setStencilMask(uival);
5006
0
                    break;
5007
0
                case ID_FAIL_OP:
5008
0
                    if(getValue(prop, compiler, sop))
5009
0
                        mPass->setStencilFailOp(sop);
5010
0
                    break;
5011
0
                case ID_DEPTH_FAIL_OP:
5012
0
                    if(getValue(prop, compiler, sop))
5013
0
                        mPass->setStencilDepthFailOp(sop);
5014
0
                    break;
5015
0
                case ID_PASS_OP:
5016
0
                    if(getValue(prop, compiler, sop))
5017
0
                        mPass->setStencilPassOp(sop);
5018
0
                    break;
5019
0
                case ID_TWO_SIDED:
5020
0
                    if(getValue(prop, compiler, bval))
5021
0
                        mPass->setStencilTwoSidedOperation(bval);
5022
0
                    break;
5023
0
                case ID_BUFFERS:
5024
0
                    {
5025
0
                        uint32 buffers = 0;
5026
0
                        for(const auto& v : prop->values)
5027
0
                        {
5028
0
                            if(v->type == ANT_ATOM)
5029
0
                            {
5030
0
                                switch(((AtomAbstractNode*)v.get())->id)
5031
0
                                {
5032
0
                                case ID_COLOUR:
5033
0
                                    buffers |= FBT_COLOUR;
5034
0
                                    break;
5035
0
                                case ID_DEPTH:
5036
0
                                    buffers |= FBT_DEPTH;
5037
0
                                    break;
5038
0
                                case ID_STENCIL:
5039
0
                                    buffers |= FBT_STENCIL;
5040
0
                                    break;
5041
0
                                default:
5042
0
                                    compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
5043
0
                                }
5044
0
                            }
5045
0
                            else
5046
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
5047
0
                        }
5048
0
                        mPass->setClearBuffers(buffers);
5049
0
                    }
5050
0
                    break;
5051
0
                case ID_COLOUR_VALUE:
5052
0
                    {
5053
0
                        if(prop->values.empty())
5054
0
                        {
5055
0
                            compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line);
5056
0
                            return;
5057
0
                        }
5058
0
                        ColourValue val;
5059
0
                        if (prop->values.front()->type == ANT_ATOM &&
5060
0
                            ((AtomAbstractNode*)prop->values.front().get())->id == ID_AUTO)
5061
0
                            mPass->setAutomaticColour(true);
5062
0
                        else if(getColour(prop->values.begin(), prop->values.end(), &val))
5063
0
                            mPass->setClearColour(val);
5064
0
                        else
5065
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
5066
0
                    }
5067
0
                    break;
5068
0
                case ID_DEPTH_VALUE:
5069
0
                    if(getValue(prop, compiler, fval))
5070
0
                        mPass->setClearDepth(fval);
5071
0
                    break;
5072
0
                case ID_STENCIL_VALUE:
5073
0
                    if(getValue(prop, compiler, uival))
5074
0
                        mPass->setClearStencil(uival);
5075
0
                    break;
5076
0
                case ID_MATERIAL:
5077
0
                    if(getValue(prop, compiler, sval))
5078
0
                    {
5079
0
                        ProcessResourceNameScriptCompilerEvent evt(ProcessResourceNameScriptCompilerEvent::MATERIAL, sval);
5080
0
                        compiler->_fireEvent(&evt, 0);
5081
0
                        auto mat = MaterialManager::getSingleton().getByName(evt.mName, compiler->getResourceGroup());
5082
0
                        if (mat)
5083
0
                            mPass->setMaterial(mat);
5084
0
                        else
5085
0
                            compiler->addError(ScriptCompiler::CE_REFERENCETOANONEXISTINGOBJECT, prop->file,
5086
0
                                               prop->line, evt.mName);
5087
0
                    }
5088
0
                    break;
5089
0
                case ID_INPUT:
5090
0
                    if(prop->values.size() < 2)
5091
0
                    {
5092
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
5093
0
                        return;
5094
0
                    }
5095
0
                    else if (prop->values.size() > 3)
5096
0
                    {
5097
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line);
5098
0
                        return;
5099
0
                    }
5100
0
                    else
5101
0
                    {
5102
0
                        AbstractNodeList::const_iterator i0 = getNodeAt(prop->values, 0), i1 = getNodeAt(prop->values, 1), i2 = getNodeAt(prop->values, 2);
5103
0
                        uint32 id;
5104
0
                        String name;
5105
0
                        if(getUInt(*i0, &id) && getString(*i1, &name))
5106
0
                        {
5107
0
                            uint32 index = 0;
5108
0
                            if(i2 != prop->values.end())
5109
0
                            {
5110
0
                                if(!getUInt(*i2, &index))
5111
0
                                {
5112
0
                                    compiler->addError(ScriptCompiler::CE_NUMBEREXPECTED, prop->file, prop->line);
5113
0
                                    return;
5114
0
                                }
5115
0
                            }
5116
5117
0
                            mPass->setInput(id, name, index);
5118
0
                        }
5119
0
                        else
5120
0
                        {
5121
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
5122
0
                        }
5123
0
                    }
5124
0
                    break;
5125
0
                case ID_IDENTIFIER:
5126
0
                    if(getValue(prop, compiler, uival))
5127
0
                        mPass->setIdentifier(uival);
5128
0
                    break;
5129
0
                case ID_FIRST_RENDER_QUEUE:
5130
0
                    if(getValue(prop, compiler, uival))
5131
0
                        mPass->setFirstRenderQueue(static_cast<uint8>(uival));
5132
0
                    break;
5133
0
                case ID_LAST_RENDER_QUEUE:
5134
0
                    if(getValue(prop, compiler, uival))
5135
0
                        mPass->setLastRenderQueue(static_cast<uint8>(uival));
5136
0
                    break;
5137
0
                case ID_MATERIAL_SCHEME:
5138
0
                    if(getValue(prop, compiler, sval))
5139
0
                        mPass->setMaterialScheme(sval);
5140
0
                    break;
5141
0
                case ID_THREAD_GROUPS:
5142
0
                {
5143
0
                    std::vector<int> g;
5144
0
                    if(_getVector(prop->values.begin(), prop->values.end(), g, 3))
5145
0
                        mPass->setThreadGroups({g[0], g[1], g[2]});
5146
0
                    break;
5147
0
                }
5148
0
                case ID_QUAD_NORMALS:
5149
0
                    if(prop->values.empty())
5150
0
                    {
5151
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
5152
0
                        return;
5153
0
                    }
5154
0
                    else if (prop->values.size() > 1)
5155
0
                    {
5156
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line);
5157
0
                        return;
5158
0
                    }
5159
0
                    else
5160
0
                    {
5161
0
                        if(prop->values.front()->type == ANT_ATOM)
5162
0
                        {
5163
0
                            atom = static_cast<AtomAbstractNode*>(prop->values.front().get());
5164
0
                            if(atom->id == ID_CAMERA_FAR_CORNERS_VIEW_SPACE)
5165
0
                                mPass->setQuadFarCorners(true, true);
5166
0
                            else if(atom->id == ID_CAMERA_FAR_CORNERS_WORLD_SPACE)
5167
0
                                mPass->setQuadFarCorners(true, false);
5168
0
                            else
5169
0
                                compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
5170
0
                        }
5171
0
                        else
5172
0
                        {
5173
0
                            compiler->addError(ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line);
5174
0
                        }
5175
0
                    }
5176
0
                    break;
5177
0
                case ID_CAMERA:
5178
0
                    if(prop->values.empty())
5179
0
                    {
5180
0
                        compiler->addError(ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
5181
0
                        return;
5182
0
                    }
5183
0
                    else if (prop->values.size() > 2)
5184
0
                    {
5185
0
                        compiler->addError(ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line);
5186
0
                        return;
5187
0
                    }
5188
0
                    else
5189
0
                    {
5190
0
                        if (!getValue(prop->values.front(), sval))
5191
0
                            return;
5192
0
                        mPass->setCameraName(sval);
5193
0
                        if (prop->values.back()->type == ANT_ATOM &&
5194
0
                            static_cast<AtomAbstractNode*>(prop->values.back().get())->id ==
5195
0
                                ID_ALIGN_TO_FACE)
5196
0
                        {
5197
0
                            mPass->setAlignCameraToFace(true);
5198
0
                        }
5199
0
                    }
5200
0
                    break;
5201
0
                default:
5202
0
                    compiler->addError(ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
5203
0
                                       "token \"" + prop->name + "\" is not recognized");
5204
0
                }
5205
0
            }
5206
0
        }
5207
0
    }
5208
5209
    /**************************************************************************
5210
     * BuiltinScriptTranslatorManager
5211
     *************************************************************************/
5212
    BuiltinScriptTranslatorManager::BuiltinScriptTranslatorManager()
5213
0
    {
5214
0
    }
5215
    //-------------------------------------------------------------------------
5216
    ScriptTranslator *BuiltinScriptTranslatorManager::getTranslator(const AbstractNodePtr &node)
5217
0
    {
5218
0
        ScriptTranslator *translator = 0;
5219
5220
0
        if(node->type == ANT_OBJECT)
5221
0
        {
5222
0
            ObjectAbstractNode *obj = static_cast<ObjectAbstractNode*>(node.get());
5223
0
            ObjectAbstractNode *parent = obj->parent ? static_cast<ObjectAbstractNode*>(obj->parent) : 0;
5224
0
            if(obj->id == ID_MATERIAL)
5225
0
                translator = &mMaterialTranslator;
5226
0
            else if(obj->id == ID_TECHNIQUE && parent && parent->id == ID_MATERIAL)
5227
0
                translator = &mTechniqueTranslator;
5228
0
            else if(obj->id == ID_PASS && parent && parent->id == ID_TECHNIQUE)
5229
0
                translator = &mPassTranslator;
5230
0
            else if(obj->id == ID_TEXTURE_UNIT && parent && parent->id == ID_PASS)
5231
0
                translator = &mTextureUnitTranslator;
5232
0
            else if(obj->id == ID_TEXTURE_SOURCE && parent && parent->id == ID_TEXTURE_UNIT)
5233
0
                translator = &mTextureSourceTranslator;
5234
0
            else if(obj->id == ID_FRAGMENT_PROGRAM ||
5235
0
                    obj->id == ID_VERTEX_PROGRAM ||
5236
0
                    obj->id == ID_GEOMETRY_PROGRAM ||
5237
0
                    obj->id == ID_TESSELLATION_HULL_PROGRAM ||
5238
0
                    obj->id == ID_TESSELLATION_DOMAIN_PROGRAM ||
5239
0
                    obj->id == ID_COMPUTE_PROGRAM ||
5240
0
                    obj->id == ID_MESH_PROGRAM ||
5241
0
                    obj->id == ID_TASK_PROGRAM)
5242
0
                translator = &mGpuProgramTranslator;
5243
0
            else if(obj->id == ID_SHARED_PARAMS)
5244
0
                translator = &mSharedParamsTranslator;
5245
0
            else if(obj->id == ID_PARTICLE_SYSTEM)
5246
0
                translator = &mParticleSystemTranslator;
5247
0
            else if(obj->id == ID_EMITTER)
5248
0
                translator = &mParticleEmitterTranslator;
5249
0
            else if(obj->id == ID_AFFECTOR)
5250
0
                translator = &mParticleAffectorTranslator;
5251
0
            else if(obj->id == ID_COMPOSITOR)
5252
0
                translator = &mCompositorTranslator;
5253
0
            else if(obj->id == ID_TECHNIQUE && parent && parent->id == ID_COMPOSITOR)
5254
0
                translator = &mCompositionTechniqueTranslator;
5255
0
            else if((obj->id == ID_TARGET || obj->id == ID_TARGET_OUTPUT) && parent && parent->id == ID_TECHNIQUE)
5256
0
                translator = &mCompositionTargetPassTranslator;
5257
0
            else if(obj->id == ID_PASS && parent && (parent->id == ID_TARGET || parent->id == ID_TARGET_OUTPUT))
5258
0
                translator = &mCompositionPassTranslator;
5259
0
            else if(obj->id == ID_SAMPLER)
5260
0
                translator = &mSamplerTranslator;
5261
0
        }
5262
5263
0
        return translator;
5264
0
    }
5265
}