1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Quick 3D.
7 **
8 ** $QT_BEGIN_LICENSE:GPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 or (at your option) any later version
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
22 ** included in the packaging of this file. Please review the following
23 ** information to ensure the GNU General Public License requirements will
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25 **
26 ** $QT_END_LICENSE$
27 **
28 ****************************************************************************/
29 
30 #ifndef UIPPRESENTATION_H
31 #define UIPPRESENTATION_H
32 
33 #include <QString>
34 #include <QVector>
35 #include <QSet>
36 #include <QHash>
37 #include <QVector2D>
38 #include <QVector3D>
39 #include <QMatrix4x4>
40 #include <QColor>
41 #include <QXmlStreamAttributes>
42 
43 #include <functional>
44 
45 QT_BEGIN_NAMESPACE
46 
47 namespace Q3DS {
48 
49 enum PropertyType {     // value format
50     Unknown = 0,
51     StringList,         // String
52     FloatRange,         // Float
53     LongRange,          // Long
54     Float,              // Float
55     Long,               // Long
56     Float2,             // Float2
57     Vector,             // Float3
58     Scale,              // Float3
59     Rotation,           // Float3
60     Color,              // Float4
61     Boolean,            // Bool
62     Slide,              // String
63     Font,               // String
64     FontSize,           // Float
65     String,             // String
66     MultiLineString,    // String
67     ObjectRef,          // ObjectRef
68     Image,              // String
69     Mesh,               // String
70     Import,             // String
71     Texture,            // String
72     Image2D,            // String
73     Buffer,             // String
74     Guid,               // Long4
75     StringListOrInt,    // StringOrInt
76     Renderable,         // String
77     PathBuffer,         // String
78     Enum,               // depends on name; data model only
79     Matrix4x4           // Matrix4x4
80 };
81 
82 bool convertToPropertyType(const QStringRef &value, Q3DS::PropertyType *type, int *componentCount, const char *desc = nullptr, QXmlStreamReader *reader = nullptr);
83 bool convertToFloat(const QStringRef &value, float *v, const char *desc = nullptr, QXmlStreamReader *reader = nullptr);
84 bool convertToInt(const QStringRef &value, int *v, const char *desc = nullptr, QXmlStreamReader *reader = nullptr);
85 bool convertToInt32(const QStringRef &value, qint32 *v, const char *desc = nullptr, QXmlStreamReader *reader = nullptr);
86 bool convertToBool(const QStringRef &value, bool *v, const char *desc = nullptr, QXmlStreamReader *reader = nullptr);
87 bool convertToVector2D(const QStringRef &value, QVector2D *v, const char *desc = nullptr, QXmlStreamReader *reader = nullptr);
88 bool convertToVector3D(const QStringRef &value, QVector3D *v, const char *desc = nullptr, QXmlStreamReader *reader = nullptr);
89 bool convertToVector4D(const QStringRef &value, QVector4D *v, const char *desc = nullptr, QXmlStreamReader *reader = nullptr);
90 bool convertToMatrix4x4(const QStringRef &value, QMatrix4x4 *v, const char *desc = nullptr, QXmlStreamReader *reader = nullptr);
91 int animatablePropertyTypeToMetaType(Q3DS::PropertyType type);
92 QVariant convertToVariant(const QString &value, Q3DS::PropertyType type);
93 QString convertFromVariant(const QVariant &value);
94 
95 } // namespace Q3DS
96 
97 class PropertyChange
98 {
99 public:
100     PropertyChange() = default;
101 
102     // When the new value is already set via a member or static setter.
103     // Used by animations and any external call to a member setter.
PropertyChange(const QString & name_)104     PropertyChange(const QString &name_)
105         : m_name(name_)
106     { }
107 
108     // Value included.
109     // Used by slides (on-enter property changes) and data input.
110     // High frequency usage should be avoided.
PropertyChange(const QString & name_,const QString & value_)111     PropertyChange(const QString &name_, const QString &value_)
112         : m_name(name_), m_value(value_), m_hasValue(true)
113     { }
114 
115     static PropertyChange fromVariant(const QString &name, const QVariant &value);
116 
117     // name() and value() must be source compatible with QXmlStreamAttribute
name()118     QStringRef name() const { return QStringRef(&m_name); }
value()119     QStringRef value() const { Q_ASSERT(m_hasValue); return QStringRef(&m_value); }
120 
nameStr()121     QString nameStr() const { return m_name; }
valueStr()122     QString valueStr() const { Q_ASSERT(m_hasValue); return m_value; }
123 
124     // A setter can return an invalid change when the new value is the same as
125     // before. Such changes are ignored by the changelist.
isValid()126     bool isValid() const { return !m_name.isEmpty(); }
127 
128     // A change without value can only be used with notifyPropertyChanges, not
129     // with applyPropertyChanges.
hasValue()130     bool hasValue() const { return m_hasValue; }
131 
132 private:
133     QString m_name;
134     QString m_value;
135     bool m_hasValue = false;
136 };
137 
138 Q_DECLARE_TYPEINFO(PropertyChange, Q_MOVABLE_TYPE);
139 
140 class PropertyChangeList
141 {
142 public:
143     typedef const PropertyChange *const_iterator;
144     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
145 
PropertyChangeList()146     PropertyChangeList() { }
147 #ifdef Q_COMPILER_INITIALIZER_LISTS
148     PropertyChangeList(std::initializer_list<PropertyChange> args);
149 #endif
150 
begin()151     const_iterator begin() const Q_DECL_NOTHROW { return m_changes.begin(); }
cbegin()152     const_iterator cbegin() const Q_DECL_NOTHROW { return begin(); }
end()153     const_iterator end() const Q_DECL_NOTHROW { return m_changes.end(); }
cend()154     const_iterator cend() const Q_DECL_NOTHROW { return end(); }
rbegin()155     const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
crbegin()156     const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return rbegin(); }
rend()157     const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
crend()158     const_reverse_iterator crend() const Q_DECL_NOTHROW { return rend(); }
159 
isEmpty()160     bool isEmpty() const { return m_changes.isEmpty(); }
count()161     int count() const { return m_changes.count(); }
clear()162     void clear() { m_changes.clear(); m_keys.clear(); }
163     void append(const PropertyChange &change);
keys()164     QSet<QString> keys() const { return m_keys; }
165 
166     typedef PropertyChange value_type;
167 
168 private:
169     QVector<PropertyChange> m_changes;
170     QSet<QString> m_keys;
171 };
172 
173 class GraphObject
174 {
175 public:
176     enum Type {
177         Asset = 0,
178         // direct subtypes
179         Scene,
180         Slide,
181         Image,
182         DefaultMaterial,
183         ReferencedMaterial,
184         CustomMaterial,
185         Effect,
186         Behavior,
187         // node subtypes
188         Layer = 100,
189         Camera,
190         Light,
191         Model,
192         Group,
193         Text,
194         Component,
195         Alias
196     };
197 
198     static constexpr Type AnyObject = Type::Asset;
199     static constexpr Type FirstNodeType = Type::Layer;
200 
201     enum PropSetFlag {
202         PropSetDefaults = 0x01,
203         PropSetOnMaster = 0x02
204     };
205     Q_DECLARE_FLAGS(PropSetFlags, PropSetFlag)
206 
207     enum State {
208         Enabled,
209         Disabled
210     };
211 
212     GraphObject(Type type);
213     virtual ~GraphObject();
214 
215     // hmm where have I seen this before...
type()216     Type type() const { return m_type; }
217     QString typeName () const;
218 
parent()219     GraphObject *parent() const { return m_parent; }
firstChild()220     GraphObject *firstChild() const { return m_firstChild; }
lastChild()221     GraphObject *lastChild() const { return m_lastChild; }
nextSibling()222     GraphObject *nextSibling() const { return m_nextSibling; }
previousSibling()223     GraphObject *previousSibling() const { return m_previousSibling; }
224     int childCount() const;
225     GraphObject *childAtIndex(int idx) const;
226     void removeChildNode(GraphObject *node);
227     void removeAllChildNodes();
228     void prependChildNode(GraphObject *node);
229     void appendChildNode(GraphObject *node);
230     void insertChildNodeBefore(GraphObject *node, GraphObject *before);
231     void insertChildNodeAfter(GraphObject *node, GraphObject *after);
232     void reparentChildNodesTo(GraphObject *newParent);
233 
234     virtual void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags);
235     virtual void applyPropertyChanges(const PropertyChangeList &changeList);
236 
isNode()237     bool isNode() const { return m_type >= FirstNodeType; }
startTime()238     float startTime() { return m_startTime * 0.001f; }
endTime()239     float endTime() { return m_endTime * 0.001f; }
state()240     State state() const { return m_state; }
241 
242     QString qmlId();
243     virtual void writeQmlHeader(QTextStream &output, int tabLevel) = 0;
244     virtual void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) = 0;
245     virtual void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) = 0;
246     virtual void writeQmlFooter(QTextStream &output, int tabLevel);
247 
248     void destroyGraph();
249 
250     QByteArray m_id;
251     QString m_name;
252     qint32 m_startTime = 0;
253     qint32 m_endTime = 10000;
254 
255 private:
256     Q_DISABLE_COPY(GraphObject)
257     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
258 
259     struct ObjectExtraMetaData
260     {
261         struct Data {
262             QVector<QByteArray> propertyNames;
263             QVector<QVariant> propertyValues;
264         };
265         QScopedPointer<Data> data;
266     } metaData;
267 
extraMetaData()268     ObjectExtraMetaData *extraMetaData() { return &metaData; }
extraMetaData()269     const ObjectExtraMetaData *extraMetaData() const { return &metaData; }
270 
271     GraphObject *m_parent = nullptr;
272     GraphObject *m_firstChild = nullptr;
273     GraphObject *m_lastChild = nullptr;
274     GraphObject *m_nextSibling = nullptr;
275     GraphObject *m_previousSibling = nullptr;
276     Type m_type = AnyObject;
277     State m_state = Enabled;
278 
279     friend class UipPresentation;
280 };
281 
282 class Scene : public GraphObject
283 {
284 public:
285     Scene();
286     ~Scene() override;
287 
288     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
289 
290     bool m_useClearColor = true;
291     QColor m_clearColor = Qt::black;
292 
293     // GraphObject interface
294 public:
295     void writeQmlHeader(QTextStream &output, int tabLevel) override;
296     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
297     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
298     void writeQmlFooter(QTextStream &output, int tabLevel) override;
299 };
300 
301 class AnimationTrack
302 {
303 public:
304     enum AnimationType {
305         NoAnimation = 0,
306         Linear,
307         EaseInOut,
308         Bezier
309     };
310 
311     struct KeyFrame {
312         KeyFrame() = default;
KeyFrameKeyFrame313         KeyFrame(float time_, float value_)
314             : time(time_), value(value_)
315         { }
316 
317         float time = 0; // seconds
318         float value = 0;
319         union {
320             float easeIn;
321             float c2time;
322         };
323         union {
324             float easeOut;
325             float c2value;
326         };
327         float c1time;
328         float c1value;
329     };
330     using KeyFrameList = QVector<KeyFrame>;
331 
332     AnimationTrack() = default;
AnimationTrack(AnimationType type_,GraphObject * target_,const QString & property_)333     AnimationTrack(AnimationType type_, GraphObject *target_, const QString &property_)
334         : m_type(type_), m_target(target_), m_property(property_)
335     { }
336 
337     AnimationType m_type = NoAnimation;
338     GraphObject *m_target = nullptr;
339     QString m_property;
340     bool m_dynamic = false;
341     KeyFrameList m_keyFrames;
342 };
343 
344 Q_DECLARE_TYPEINFO(AnimationTrack::KeyFrame, Q_MOVABLE_TYPE);
345 Q_DECLARE_TYPEINFO(AnimationTrack, Q_MOVABLE_TYPE);
346 
347 inline bool operator==(const AnimationTrack::KeyFrame &a, const AnimationTrack::KeyFrame &b)
348 {
349     return a.time == b.time;
350 }
351 
352 inline bool operator!=(const AnimationTrack::KeyFrame &a, const AnimationTrack::KeyFrame &b)
353 {
354     return !(a == b);
355 }
356 
357 inline bool operator==(const AnimationTrack &a, const AnimationTrack &b)
358 {
359     return a.m_target == b.m_target && a.m_property == b.m_property;
360 }
361 
362 inline bool operator!=(const AnimationTrack &a, const AnimationTrack &b)
363 {
364     return !(a == b);
365 }
366 
367 class Slide : public GraphObject
368 {
369 public:
370     enum PlayMode {
371         StopAtEnd = 0,
372         Looping,
373         PingPong,
374         Ping,
375         PlayThroughTo
376     };
377 
378     enum InitialPlayState {
379         Play = 0,
380         Pause
381     };
382 
383     enum PlayThrough {
384         Next,
385         Previous,
386         Value
387     };
388 
389     using PropertyChanges = QHash<GraphObject *, PropertyChangeList *>;
390     using AnimationTrackList = QVector<AnimationTrack>;
391 
392     Slide();
393     ~Slide() override;
394 
395     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
396     void applyPropertyChanges(const PropertyChangeList &changeList) override;
397 
objects()398     const QSet<GraphObject *> &objects() const { return m_objects; } // NB does not include objects from master
399     void addObject(GraphObject *obj);
400     void removeObject(GraphObject *obj);
401 
propertyChanges()402     const PropertyChanges &propertyChanges() const { return m_propChanges; }
403     void addPropertyChanges(GraphObject *target, PropertyChangeList *changeList); // changeList ownership transferred
404     void removePropertyChanges(GraphObject *target);
405     PropertyChangeList *takePropertyChanges(GraphObject *target);
406 
animations()407     const AnimationTrackList &animations() const { return m_anims; }
408     void addAnimation(const AnimationTrack &track);
409     void removeAnimation(const AnimationTrack &track);
410 
411     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
412 
413     PlayMode m_playMode = StopAtEnd;
414     InitialPlayState m_initialPlayState = Play;
415     PlayThrough m_playThrough = Next;
416     QVariant m_playThroughValue;
417     QSet<GraphObject *> m_objects;
418     PropertyChanges m_propChanges;
419     AnimationTrackList m_anims;
420 
421     // GraphObject interface
422 public:
423     void writeQmlHeader(QTextStream &output, int tabLevel) override;
424     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
425     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
426     void writeQmlFooter(QTextStream &output, int tabLevel) override;
427 };
428 
429 class Image : public GraphObject
430 {
431 public:
432     enum MappingMode {
433         UVMapping = 0,
434         EnvironmentalMapping,
435         LightProbe,
436         IBLOverride
437     };
438 
439     enum TilingMode {
440         Tiled = 0,
441         Mirrored,
442         NoTiling
443     };
444 
445     enum ImagePropertyChanges {
446         SourceChanges = 1 << 0
447     };
448 
449     Image();
450 
451     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
452     void applyPropertyChanges(const PropertyChangeList &changeList) override;
453 
454     bool isDefaultScaleAndRotation();
455 
456     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
457 
458     QString m_sourcePath;
459     float m_scaleU = 1;
460     float m_scaleV = 1;
461     MappingMode m_mappingMode = UVMapping;
462     TilingMode m_tilingHoriz = NoTiling;
463     TilingMode m_tilingVert = NoTiling;
464     float m_rotationUV = 0;
465     float m_positionU = 0;
466     float m_positionV = 0;
467     float m_pivotU = 0;
468     float m_pivotV = 0;
469     QString m_subPresentation;
470 
471     // GraphObject interface
472 public:
473     void writeQmlHeader(QTextStream &output, int tabLevel) override;
474     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
475     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
476 };
477 
478 class Node : public GraphObject
479 {
480 public:
481     enum NodeFlag {
482         Active = 0x01, // eyeball
483         IgnoresParentTransform = 0x02
484     };
485     Q_DECLARE_FLAGS(Flags, NodeFlag)
486 
487     enum RotationOrder {
488         XYZ = 0,
489         YZX,
490         ZXY,
491         XZY,
492         YXZ,
493         ZYX,
494         XYZr,
495         YZXr,
496         ZXYr,
497         XZYr,
498         YXZr,
499         ZYXr
500     };
501 
502     enum Orientation {
503         LeftHanded = 0,
504         RightHanded
505     };
506 
507     enum NodePropertyChanges {
508         TransformChanges = 1 << 0,
509         OpacityChanges = 1 << 1,
510         EyeballChanges = 1 << 2
511     };
512     static const int FIRST_FREE_PROPERTY_CHANGE_BIT = 3;
513 
514     Node(Type type);
515 
516     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
517     void applyPropertyChanges(const PropertyChangeList &changeList) override;
518 
519     Flags m_flags = Active;
520     QVector3D m_rotation;
521     QVector3D m_position;
522     QVector3D m_scale = QVector3D(1, 1, 1);
523     QVector3D m_pivot;
524     float m_localOpacity = 100.0f;
525     qint32 m_skeletonId = -1;
526     RotationOrder m_rotationOrder = YXZ;
527     Orientation m_orientation = LeftHanded;
528 
529     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
530 
531     // GraphObject interface
532 public:
533     void writeQmlHeader(QTextStream &output, int tabLevel) override;
534     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
535     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
536 };
537 
538 class LayerNode : public Node
539 {
540 public:
541     enum Flag {
542         DisableDepthTest = 0x01,
543         DisableDepthPrePass = 0x02,
544         TemporalAA = 0x04,
545         FastIBL = 0x08,
546 
547         // non-uip
548         ExplicitSize = 0x1000
549     };
550     Q_DECLARE_FLAGS(Flags, Flag)
551 
552     enum ProgressiveAA {
553         NoPAA = 0,
554         PAA2x,
555         PAA4x,
556         PAA8x
557     };
558 
559     enum MultisampleAA {
560         NoMSAA = 0,
561         MSAA2x,
562         MSAA4x,
563         SSAA
564     };
565 
566     enum LayerBackground {
567         Transparent = 0,
568         SolidColor,
569         Unspecified
570     };
571 
572     enum BlendType {
573         Normal = 0,
574         Screen,
575         Multiply,
576         Add,
577         Subtract,
578         Overlay,
579         ColorBurn,
580         ColorDodge
581     };
582 
583     enum HorizontalFields {
584         LeftWidth = 0,
585         LeftRight,
586         WidthRight
587     };
588 
589     enum VerticalFields {
590         TopHeight = 0,
591         TopBottom,
592         HeightBottom
593     };
594 
595     enum Units {
596         Percent = 0,
597         Pixels
598     };
599 
600     enum LayerPropertyChanges {
601         AoOrShadowChanges = 1 << Node::FIRST_FREE_PROPERTY_CHANGE_BIT,
602         LayerContentSubTreeChanges = 1 << (Node::FIRST_FREE_PROPERTY_CHANGE_BIT + 1),
603         LayerContentSubTreeLightsChange = 1 << (Node::FIRST_FREE_PROPERTY_CHANGE_BIT + 2),
604         SourcePathChanges = 1 << (Node::FIRST_FREE_PROPERTY_CHANGE_BIT + 3)
605     };
606 
607     LayerNode();
608 
609     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
610     void applyPropertyChanges(const PropertyChangeList &changeList) override;
611 
612     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
613 
614     void outputAAModeAndQuality(QTextStream &output, int tabLevel, const QString &propertyName);
615 
616     QSize m_explicitSize;
617 
618     Flags m_layerFlags = FastIBL;
619     ProgressiveAA m_progressiveAA = NoPAA;
620     MultisampleAA m_multisampleAA = NoMSAA;
621     bool m_antialiasingSet = false;
622     LayerBackground m_layerBackground = Transparent;
623     QColor m_backgroundColor = Qt::black;
624     BlendType m_blendType = Normal;
625 
626     HorizontalFields m_horizontalFields = LeftWidth;
627     float m_left = 0;
628     Units m_leftUnits = Percent;
629     float m_width = 100;
630     Units m_widthUnits = Percent;
631     float m_right = 0;
632     Units m_rightUnits = Percent;
633     VerticalFields m_verticalFields = TopHeight;
634     float m_top = 0;
635     Units m_topUnits = Percent;
636     float m_height = 100;
637     Units m_heightUnits = Percent;
638     float m_bottom = 0;
639     Units m_bottomUnits = Percent;
640 
641     QString m_sourcePath;
642 
643     float m_aoStrength = 0;
644     float m_aoDistance = 5;
645     float m_aoSoftness = 50;
646     float m_aoBias = 0;
647     qint32 m_aoSampleRate = 2;
648     bool m_aoDither = false;
649 
650     QString m_lightProbe_unresolved;
651     float m_probeBright = 100;
652     float m_probeHorizon = -1;
653     float m_probeFov = 180;
654 
655     // GraphObject interface
656 public:
657     void writeQmlHeader(QTextStream &output, int tabLevel) override;
658     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
659     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
660 };
661 
662 class CameraNode : public Node
663 {
664 
665 public:
666     CameraNode();
667 
668     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
669     void applyPropertyChanges(const PropertyChangeList &changeList) override;
670 
671     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
672 
673     bool m_orthographic = false;
674     float m_fov = 60;
675     bool m_fovHorizontal = false;
676     float m_clipNear = 10;
677     float m_clipFar = 5000;
678     bool m_frustumCulling = false;
679     float m_zoom = 1.0;
680 
681     // GraphObject interface
682 public:
683     void writeQmlHeader(QTextStream &output, int tabLevel) override;
684     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
685     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
686 };
687 
688 class LightNode : public Node
689 {
690 public:
691     enum LightType {
692         Directional = 0,
693         Point,
694         Area
695     };
696 
697     LightNode();
698 
699     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
700     void applyPropertyChanges(const PropertyChangeList &changeList) override;
701 
702     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
703 
704     QString m_scope_unresolved;
705     GraphObject *m_scope = nullptr;
706     LightType m_lightType = Directional;
707     QColor m_lightDiffuse = Qt::white;
708     QColor m_lightSpecular = Qt::white;
709     QColor m_lightAmbient = Qt::black;
710     float m_brightness = 100;
711     float m_constantFade = 1;
712     float m_linearFade = 0;
713     float m_expFade = 0;
714     float m_areaWidth = 100;
715     float m_areaHeight = 100;
716     bool m_castShadow = false;
717     float m_shadowFactor = 10;
718     float m_shadowFilter = 35;
719     qint32 m_shadowMapRes = 9;
720     float m_shadowBias = 0;
721     float m_shadowMapFar = 5000;
722     float m_shadowMapFov = 90;
723 
724     // GraphObject interface
725 public:
726     void writeQmlHeader(QTextStream &output, int tabLevel) override;
727     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
728     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
729 };
730 
731 class  ModelNode : public Node
732 {
733 public:
734     enum Tessellation {
735         None = 0,
736         Linear,
737         Phong,
738         NPatch
739     };
740 
741     enum ModelPropertyChanges {
742         MeshChanges = 1 << Node::FIRST_FREE_PROPERTY_CHANGE_BIT
743     };
744 
745     ModelNode();
746     ~ModelNode() override;
747 
748     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
749     void applyPropertyChanges(const PropertyChangeList &changeList) override;
750 
751     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
752 
753     QString m_mesh_unresolved;
754     Tessellation m_tessellation = None;
755     float m_edgeTess = 4;
756     float m_innerTess = 4;
757 
758     // GraphObject interface
759 public:
760     void writeQmlHeader(QTextStream &output, int tabLevel) override;
761     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
762     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
763 };
764 
765 class GroupNode : public Node
766 {
767 public:
768     GroupNode();
769 
770     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
771     void applyPropertyChanges(const PropertyChangeList &changeList) override;
772 
773     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
774 
775     // GraphObject interface
776 public:
777     void writeQmlHeader(QTextStream &output, int tabLevel) override;
778     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
779     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
780 };
781 
782 
783 
784 class ComponentNode : public Node
785 {
786 
787 public:
788     ComponentNode();
789     ~ComponentNode() override;
790 
791     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
792     void applyPropertyChanges(const PropertyChangeList &changeList) override;
793 
794     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
795 
796     class Slide *m_masterSlide = nullptr;
797     class Slide *m_currentSlide = nullptr;
798 
799 
800     // GraphObject interface
801 public:
802     void writeQmlHeader(QTextStream &output, int tabLevel) override;
803     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
804     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
805 };
806 
807 class TextNode : public Node
808 {
809 
810 public:
811     enum HorizontalAlignment {
812         Left = 0,
813         Center,
814         Right
815     };
816 
817     enum VerticalAlignment {
818         Top = 0,
819         Middle,
820         Bottom
821     };
822 
823     enum WordWrap {
824         Clip = 0,
825         WrapWord,
826         WrapAnywhere
827     };
828 
829     enum Elide {
830         ElideNone = 0,
831         ElideLeft,
832         ElideMiddle,
833         ElideRight
834     };
835 
836     enum TextPropertyChanges {
837         TextureImageDepChanges = 1 << Node::FIRST_FREE_PROPERTY_CHANGE_BIT
838     };
839 
840     TextNode();
841 
842     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
843     void applyPropertyChanges(const PropertyChangeList &changeList) override;
844 
845     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
846 
847     QString m_text = QStringLiteral("Text");
848     QColor m_color = Qt::white;
849     QString m_font = QStringLiteral("TitilliumWeb-Regular");
850     float m_size = 36;
851     HorizontalAlignment m_horizAlign = Center;
852     VerticalAlignment m_vertAlign = Middle;
853     float m_leading = 0;
854     float m_tracking = 0;
855     bool m_shadow = false;
856     float m_shadowStrength = 80;
857     float m_shadowOffsetX = 0;
858     float m_shadowOffsetY = 0;
859     float m_shadowOffset = 10; // To be removed in 2.x (when UIP version is next updated)
860     HorizontalAlignment m_shadowHorzAlign = Right; // To be removed in 2.x (when UIP version is next updated)
861     VerticalAlignment m_shadowVertAlign = Bottom; // To be removed in 2.x (when UIP version is next updated)
862     QVector2D m_boundingBox;
863     WordWrap m_wordWrap = WrapWord;
864     Elide m_elide = ElideNone;
865 
866     // GraphObject interface
867 public:
868     void writeQmlHeader(QTextStream &output, int tabLevel) override;
869     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
870     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
871 };
872 
873 class DefaultMaterial : public GraphObject
874 {
875 public:
876     enum ShaderLighting {
877         PixelShaderLighting = 0,
878         NoShaderLighting
879     };
880 
881     enum BlendMode {
882         Normal = 0,
883         Screen,
884         Multiply,
885         Overlay,
886         ColorBurn,
887         ColorDodge
888     };
889 
890     enum SpecularModel {
891         DefaultSpecularModel = 0,
892         KGGX,
893         KWard
894     };
895 
896     enum DefaultMaterialPropertyChanges {
897         BlendModeChanges = 1 << 0
898     };
899 
900     DefaultMaterial();
901 
902     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
903     void applyPropertyChanges(const PropertyChangeList &changeList) override;
904 
905     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
906 
907     // GraphObject interface
908 public:
909     void writeQmlHeader(QTextStream &output, int tabLevel) override;
910     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
911     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
912 
913     ShaderLighting m_shaderLighting = PixelShaderLighting;
914     BlendMode m_blendMode = Normal;
915     bool m_vertexColors = false;
916     QColor m_diffuse = Qt::white;
917     QString m_diffuseMap_unresolved;
918     QString m_specularReflection_unresolved;
919     QColor m_specularTint = Qt::white;
920     float m_specularAmount = 0;
921     QString m_specularMap_unresolved;
922     SpecularModel m_specularModel = DefaultSpecularModel;
923     float m_specularRoughness = 0;
924     QString m_roughnessMap_unresolved;
925     float m_fresnelPower = 0;
926     float m_ior = 0.2f;
927     QString m_bumpMap_unresolved;
928     QString m_normalMap_unresolved;
929     float m_bumpAmount = 0.5f;
930     QString m_displacementMap_unresolved;
931     float m_displaceAmount = 20;
932     float m_opacity = 100;
933     QString m_opacityMap_unresolved;
934     QColor m_emissiveColor = Qt::white;
935     float m_emissiveFactor = 0;
936     QString m_emissiveMap_unresolved;
937     QString m_translucencyMap_unresolved;
938     float m_translucentFalloff = 1;
939     float m_diffuseLightWrap = 0;
940     // lightmaps
941     QString m_lightmapIndirectMap_unresolved;
942     QString m_lightmapRadiosityMap_unresolved;
943     QString m_lightmapShadowMap_unresolved;
944     // IBL override
945     QString m_lightProbe_unresolved;
946 };
947 
948 class ReferencedMaterial : public GraphObject
949 {
950 public:
951     enum ReferencedMaterialPropertyChanges {
952          ReferenceChanges = 1 << 0
953     };
954 
955     ReferencedMaterial();
956 
957     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
958     void applyPropertyChanges(const PropertyChangeList &changeList) override;
959 
960     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
961 
962     // GraphObject interface
963 public:
964     void writeQmlHeader(QTextStream &output, int tabLevel) override;
965     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
966     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
967 
968     QString m_referencedMaterial_unresolved;
969     GraphObject *m_referencedMaterial = nullptr;
970     // lightmap overrides
971     QString m_lightmapIndirectMap_unresolved;
972     QString m_lightmapRadiosityMap_unresolved;
973     QString m_lightmapShadowMap_unresolved;
974     // IBL override
975     QString m_lightProbe_unresolved;
976 };
977 
978 class CustomMaterialInstance : public GraphObject
979 {
980 public:
981     enum CustomMaterialPropertyChanges {
982         SourceChanges = 1 << 0
983     };
984 
985     CustomMaterialInstance();
986 
987     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
988     void applyPropertyChanges(const PropertyChangeList &changeList) override;
989 
990     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
991 
992     // GraphObject interface
993 public:
994     void writeQmlHeader(QTextStream &output, int tabLevel) override;
995     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
996     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
997 
998     QString m_material_unresolved;
999     bool m_materialIsResolved = false;
1000     QVariantMap m_materialPropertyVals;
1001     PropertyChangeList m_pendingCustomProperties;
1002     // lightmaps
1003     QString m_lightmapIndirectMap_unresolved;
1004     QString m_lightmapRadiosityMap_unresolved;
1005     QString m_lightmapShadowMap_unresolved;
1006     // IBL override
1007     QString m_lightProbe_unresolved;
1008 };
1009 
1010 class EffectInstance : public GraphObject
1011 {
1012 public:
1013     enum EffectInstancePropertyChanges {
1014         EyeBallChanges = 1 << 0,
1015         SourceChanges = 1 << 1
1016     };
1017 
1018     EffectInstance();
1019 
1020     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
1021     void applyPropertyChanges(const PropertyChangeList &changeList) override;
1022 
1023     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
1024 
1025     // GraphObject interface
1026 public:
1027     void writeQmlHeader(QTextStream &output, int tabLevel) override;
1028     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
1029     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
1030     void writeQmlFooter(QTextStream &output, int tabLevel) override;
1031 
1032     QString m_effect_unresolved;
1033     bool m_effectIsResolved = false;
1034     bool m_eyeballEnabled = true;
1035     PropertyChangeList m_pendingCustomProperties;
1036 };
1037 
1038 class  BehaviorInstance : public GraphObject
1039 {
1040 public:
1041     enum BehaviorInstancePropertyChanges {
1042         EyeBallChanges = 1 << 0
1043     };
1044 
1045     BehaviorInstance();
1046 
1047     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
1048     void applyPropertyChanges(const PropertyChangeList &changeList) override;
1049 
1050     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
1051 
1052     // GraphObject interface
1053 public:
1054     void writeQmlHeader(QTextStream &output, int tabLevel) override;
1055     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
1056     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
1057     void writeQmlFooter(QTextStream &output, int tabLevel) override;
1058 
1059     QString m_behavior_unresolved;
1060     bool m_behaviorIsResolved = false;
1061     bool m_eyeballEnabled = true;
1062     PropertyChangeList m_pendingCustomProperties;
1063     QVariantMap m_behaviorPropertyVals;
1064 };
1065 
1066 class AliasNode : public Node
1067 {
1068 public:
1069     AliasNode();
1070 
1071     void setProperties(const QXmlStreamAttributes &attrs, PropSetFlags flags) override;
1072     void applyPropertyChanges(const PropertyChangeList &changeList) override;
1073 
1074     template<typename V> void setProps(const V &attrs, PropSetFlags flags);
1075     // GraphObject interface
1076 public:
1077     void writeQmlHeader(QTextStream &output, int tabLevel) override;
1078     void writeQmlProperties(QTextStream &output, int tabLevel, bool isInRootLevel = false) override;
1079     void writeQmlProperties(const PropertyChangeList &changeList, QTextStream &output, int tabLevel) override;
1080 
1081     QString m_referencedNode_unresolved;
1082     GraphObject *m_referencedNode = nullptr;
1083 
1084 };
1085 
1086 struct UipPresentationData;
1087 class UipPresentation
1088 {
1089 public:
1090     UipPresentation();
1091     ~UipPresentation();
1092     void reset();
1093 
1094     enum Rotation {
1095         NoRotation = 0,
1096         Clockwise90,
1097         Clockwise180,
1098         Clockwise270
1099     };
1100 
1101     QString sourceFile() const;
1102     void setSourceFile(const QString &s);
1103     QString assetFileName(const QString &xmlFileNameRef, int *part) const;
1104 
1105     QString name() const;
1106     void setName(const QString &s);
1107 
1108     QString author() const;
1109     QString company() const;
1110     int presentationWidth() const;
1111     int presentationHeight() const;
1112     Rotation presentationRotation() const;
1113     bool maintainAspectRatio() const;
1114 
1115     void setAuthor(const QString &author);
1116     void setCompany(const QString &company);
1117     void setPresentationWidth(int w);
1118     void setPresentationHeight(int h);
1119     void setPresentationRotation(Rotation r);
1120     void setMaintainAspectRatio(bool maintain);
1121 
1122     Scene *scene() const;
1123     Slide *masterSlide() const;
1124 
1125     void setScene(Scene *p);
1126     void setMasterSlide(Slide *p);
1127 
1128     bool registerObject(const QByteArray &id, GraphObject *p); // covers both the scene and slide graphs
1129     void unregisterObject(const QByteArray &id);
1130 
1131     template <typename T = GraphObject>
object(const QByteArray & id)1132     const T *object(const QByteArray &id) const { return static_cast<const T *>(getObject(id)); }
1133     template <typename T = GraphObject>
object(const QByteArray & id)1134     T *object(const QByteArray &id) { return static_cast<T *>(getObject(id)); }
1135 
1136     template <typename T = GraphObject>
objectByName(const QString & name)1137     const T *objectByName(const QString &name) const { return static_cast<const T *>(getObjectByName(name)); }
1138     template <typename T = GraphObject>
objectByName(const QString & name)1139     T *objectByName(const QString &name) { return static_cast<T *>(getObjectByName(name)); }
1140 
1141     void registerImageBuffer(const QString &sourcePath, bool hasTransparency);
1142 
1143     typedef QHash<QString, bool> ImageBufferMap;
1144     const ImageBufferMap &imageBuffer() const;
1145 
1146     void applyPropertyChanges(const Slide::PropertyChanges &changeList) const;
1147     void applySlidePropertyChanges(Slide *slide) const;
1148 
newObject(const QByteArray & id)1149     template<typename T> T *newObject(const QByteArray &id)
1150     {
1151         T *obj = new T;
1152         return registerObject(id, obj) ? obj : nullptr; // also sets obj->id
1153     }
1154 
1155     GraphObject *newObject(const char *type, const QByteArray &id);
1156 
1157     GraphObject *getObject(const QByteArray &id) const;
1158     GraphObject *getObjectByName(const QString &name) const;
1159 
1160     QScopedPointer<UipPresentationData> d;
1161     QHash<QString, bool> m_imageTransparencyHash;
1162     friend class UipParser;
1163 };
1164 
1165 struct UipPresentationData
1166 {
1167     QString sourceFile;
1168     QString name;
1169     QString author;
1170     QString company;
1171     int presentationWidth = 0;
1172     int presentationHeight = 0;
1173     UipPresentation::Rotation presentationRotation = UipPresentation::NoRotation;
1174     bool maintainAspectRatio = false;
1175     qint64 loadTime = 0;
1176     qint64 meshesLoadTime = 0;
1177 
1178     Scene *scene = nullptr;
1179     Slide *masterSlide = nullptr;
1180     QHash<QByteArray, GraphObject *> objects; // node ptrs managed by scene, not owned
1181 
1182     // Note: the key here is the sourcePath before it's resolved!
1183     QHash<QString, bool /* hasTransparency */> imageBuffers;
1184 };
1185 
1186 QT_END_NAMESPACE
1187 
1188 #endif // UIPPRESENTATION_H
1189